zoukankan      html  css  js  c++  java
  • 课程五(Sequence Models),第二 周(Natural Language Processing & Word Embeddings) —— 1.Programming assignments:Operations on word vectors

    Operations on word vectors

    Welcome to your first assignment of this week!

    Because word embeddings are very computionally expensive to train, most ML practitioners will load a pre-trained set of embeddings.

    After this assignment you will be able to:

    • Load pre-trained word vectors, and measure similarity using cosine similarity (余弦相似度)
    • Use word embeddings to solve word analogy problems such as Man is to Woman as King is to __.
    • Modify word embeddings to reduce their gender bias

    Let's get started! Run the following cell to load the packages you will need.

    【code】

    import numpy as np
    from w2v_utils import *
    

    Next, lets load the word vectors. For this assignment, we will use 50-dimensional GloVe vectors to represent words. Run the following cell to load the word_to_vec_map.  

    【code】

    words, word_to_vec_map = read_glove_vecs('data/glove.6B.50d.txt')
    

    You've loaded:

    • words: set of words in the vocabulary.
    • word_to_vec_map: dictionary mapping words to their GloVe vector representation.

    You've seen that one-hot vectors do not do a good job cpaturing what words are similar. GloVe vectors provide much more useful information about the meaning of individual words. Lets now see how you can use GloVe vectors to decide how similar two words are.

    1 - Cosine similarity

    To measure how similar two words are, we need a way to measure the degree of similarity between two embedding vectors for the two words. Given two vectors uu and vv, cosine similarity is defined as follows:

    where u.v is the dot product (or inner product) of two vectors, ||u||2is the norm (or length) of the vector u, and θ is the angle between and v. This similarity depends on the angle between u and v. If u and v are very similar, their cosine similarity will be close to 1; if they are dissimilar, the cosine similarity will take a smaller value.

    Exercise: Implement the function cosine_similarity() to evaluate similarity between word vectors.

    Reminder: The norm of uu is defined as 

    【code】

    # GRADED FUNCTION: cosine_similarity
    
    def cosine_similarity(u, v):
        """
        Cosine similarity reflects the degree of similariy between u and v
            
        Arguments:
            u -- a word vector of shape (n,)          
            v -- a word vector of shape (n,)
    
        Returns:
            cosine_similarity -- the cosine similarity between u and v defined by the formula above.
        """
        
        distance = 0.0
        
        ### START CODE HERE ###
        # Compute the dot product between u and v (≈1 line)
        dot = np.dot(u,v)
        # Compute the L2 norm of u (≈1 line)
        norm_u =np.sqrt(np.dot(u,u))
        
        # Compute the L2 norm of v (≈1 line)
        norm_v =np.sqrt(np.dot(v,v))
        # Compute the cosine similarity defined by formula (1) (≈1 line)
        cosine_similarity =dot / (norm_u * norm_v)
        ### END CODE HERE ###
        
        return cosine_similarity
    
    father = word_to_vec_map["father"]
    mother = word_to_vec_map["mother"]
    ball = word_to_vec_map["ball"]
    crocodile = word_to_vec_map["crocodile"]
    france = word_to_vec_map["france"]
    italy = word_to_vec_map["italy"]
    paris = word_to_vec_map["paris"]
    rome = word_to_vec_map["rome"]
    
    print("cosine_similarity(father, mother) = ", cosine_similarity(father, mother))
    print("cosine_similarity(ball, crocodile) = ",cosine_similarity(ball, crocodile))
    print("cosine_similarity(france - paris, rome - italy) = ",cosine_similarity(france - paris, rome - italy))
    

    【result】

    cosine_similarity(father, mother) =  0.890903844289
    cosine_similarity(ball, crocodile) =  0.274392462614
    cosine_similarity(france - paris, rome - italy) =  -0.675147930817
    

    Expected Output】  

    cosine_similarity(father, mother) =	0.890903844289
    cosine_similarity(ball, crocodile) =	0.274392462614
    cosine_similarity(france - paris, rome - italy) =	-0.675147930817
    

    After you get the correct expected output, please feel free to modify the inputs and measure the cosine similarity between other pairs of words! Playing around the cosine similarity of other inputs will give you a better sense of how word vectors behave.  

    2 - Word analogy task

    In the word analogy task, we complete the sentence "a is to b as c is to __". An example is 'man is to woman as king is to queen. In detail, we are trying to find a word d, such that the associated word vectors ea,eb,ec,eare related in the following manner: ebeaedec. We will measure the similarity between ebeand edec using cosine similarity.

    Exercise: Complete the code below to be able to perform word analogies!

    【code】

    # GRADED FUNCTION: complete_analogy
    
    def complete_analogy(word_a, word_b, word_c, word_to_vec_map):
        """
        Performs the word analogy task as explained above: a is to b as c is to ____. 
        
        Arguments:
        word_a -- a word, string
        word_b -- a word, string
        word_c -- a word, string
        word_to_vec_map -- dictionary that maps words to their corresponding vectors. 
        
        Returns:
        best_word --  the word such that v_b - v_a is close to v_best_word - v_c, as measured by cosine similarity
        """
        
        # convert words to lower case
        word_a, word_b, word_c = word_a.lower(), word_b.lower(), word_c.lower()
        
        ### START CODE HERE ###
        # Get the word embeddings v_a, v_b and v_c (≈1-3 lines)
        e_a,e_b,e_c =  word_to_vec_map[word_a],word_to_vec_map[word_b],word_to_vec_map[word_c]
        
        ### END CODE HERE ###
        
        words = word_to_vec_map.keys()
        max_cosine_sim = -100              # Initialize max_cosine_sim to a large negative number
        best_word = None                   # Initialize best_word with None, it will help keep track of the word to output
    
        # loop over the whole word vector set
        for w in words:        
            # to avoid best_word being one of the input words, pass on them.
            if w in [word_a, word_b, word_c] :
                continue
            
            ### START CODE HERE ###
            # Compute cosine similarity between the vector (e_b - e_a) and the vector ((w's vector representation) - e_c)  (≈1 line)
            cosine_sim =  cosine_similarity(e_b - e_a, word_to_vec_map[w] - e_c )
            
            # If the cosine_sim is more than the max_cosine_sim seen so far,
                # then: set the new max_cosine_sim to the current cosine_sim and the best_word to the current word (≈3 lines)
            if  cosine_sim > max_cosine_sim:
                max_cosine_sim = cosine_sim
                best_word = w
            ### END CODE HERE ###
            
        return best_word
    

    Run the cell below to test your code, this may take 1-2 minutes.

    【code】

    triads_to_try = [('italy', 'italian', 'spain'), ('india', 'delhi', 'japan'), ('man', 'woman', 'boy'), ('small', 'smaller', 'large')]
    for triad in triads_to_try:
        print ('{} -> {} :: {} -> {}'.format( *triad, complete_analogy(*triad,word_to_vec_map)))
    

    【result】

    italy -> italian :: spain -> spanish
    india -> delhi :: japan -> tokyo
    man -> woman :: boy -> girl
    small -> smaller :: large -> larger
    

    Expected Output】  

    italy -> italian ::	spain -> spanish
    india -> delhi ::	japan -> tokyo
    man -> woman ::	boy -> girl
    small -> smaller ::	large -> larger
    

    Once you get the correct expected output, please feel free to modify the input cells above to test your own analogies. Try to find some other analogy pairs that do work, but also find some where the algorithm doesn't give the right answer: For example, you can try small->smaller as big->?. 

    【code】

    triads_to_try = [('italy', 'italian', 'spain'), ('india', 'delhi', 'japan'), ('man', 'woman', 'boy'), ('small', 'smaller', 'big')]
    for triad in triads_to_try:
        print ('{} -> {} :: {} -> {}'.format( *triad, complete_analogy(*triad,word_to_vec_map)))

    【result】 

    italy -> italian :: spain -> spanish
    india -> delhi :: japan -> tokyo
    man -> woman :: boy -> girl
    small -> smaller :: big -> competitors
    

    Congratulations!

    You've come to the end of this assignment. Here are the main points you should remember:

    • Cosine similarity a good way to compare similarity between pairs of word vectors. (Though L2 distance works too.)
    • For NLP applications, using a pre-trained set of word vectors from the internet is often a good way to get started.

    Even though you have finished the graded portions, we recommend you take a look too at the rest of this notebook.

    Congratulations on finishing the graded portions of this notebook!

     

    3 - Debiasing word vectors (OPTIONAL/UNGRADED)

    In the following exercise, you will examine gender biases that can be reflected in a word embedding, and explore algorithms for reducing the bias. In addition to learning about the topic of debiasing, this exercise will also help hone your intuition about what word vectors are doing. This section involves a bit of linear algebra, though you can probably complete it even without being expert in linear algebra, and we encourage you to give it a shot. This portion of the notebook is optional and is not graded.

    Lets first see how the GloVe word embeddings relate to gender. You will first compute a vector g=ewomaneman, where ewoman represents the word vector corresponding to the word woman, and eman corresponds to the word vector corresponding to the word man. The resulting vector g roughly encodes the concept of "gender". (You might get a more accurate representation if you compute g1=emotherefatherg2=egirleboy, etc. and average over them. But just using ewomanemawill give good enough results for now.)

    【中文翻译】 

    在下面的练习中, 您将检查在嵌入词中可以反映的性别偏见, 并探索减少偏差的算法。除了了解 debiasing 的主题外, 这项练习还将有助于磨练你对词向量正在做什么的直觉。这部分涉及到一个线性代数, 虽然你可能会完成它, 即不是线性代数的专家, 我们鼓励你尝试一下。笔记本的这一部分是可选的, 不计分数。

    让我们先看看 GloVe词嵌入与性别的关系。你将首先计算一个向量  g=ewomaneman, 其中 ewoman代表词向量,对应于词woman, 并且 eman 对应于词向量,对应于词man。由此产生的矢量 g 粗略地对 "性别 " 的概念进行编码。(如果计算 g1=emotherefatherg2=egirleboy 等,然后计算平均值, 则可以得到更准确的表示形式。但仅仅使用 ewomaneman 就会得到足够好的结果了。

    【code】

    g = word_to_vec_map['woman'] - word_to_vec_map['man']
    print(g)
    

    【result】

    [-0.087144    0.2182     -0.40986    -0.03922    -0.1032      0.94165
     -0.06042     0.32988     0.46144    -0.35962     0.31102    -0.86824
      0.96006     0.01073     0.24337     0.08193    -1.02722    -0.21122
      0.695044   -0.00222     0.29106     0.5053     -0.099454    0.40445
      0.30181     0.1355     -0.0606     -0.07131    -0.19245    -0.06115
     -0.3204      0.07165    -0.13337    -0.25068714 -0.14293    -0.224957
     -0.149       0.048882    0.12191    -0.27362    -0.165476   -0.20426
      0.54376    -0.271425   -0.10245    -0.32108     0.2516     -0.33455
     -0.04371     0.01258   ]
    

    Now, you will consider the cosine similarity of different words with g. Consider what a positive value of similarity means vs a negative cosine similarity. 

    【code】 

    print ('List of names and their similarities with constructed vector:')
    
    # girls and boys name
    name_list = ['john', 'marie', 'sophie', 'ronaldo', 'priya', 'rahul', 'danielle', 'reza', 'katy', 'yasmin']
    
    for w in name_list:
        print (w, cosine_similarity(word_to_vec_map[w], g))
    

    【result】

    List of names and their similarities with constructed vector:
    john -0.23163356146
    marie 0.315597935396
    sophie 0.318687898594
    ronaldo -0.312447968503
    priya 0.17632041839
    rahul -0.169154710392
    danielle 0.243932992163
    reza -0.079304296722
    katy 0.283106865957
    yasmin 0.233138577679
    

    As you can see, female first names tend to have a positive cosine similarity with our constructed vector g, while male first names tend to have a negative cosine similarity. This is not suprising, and the result seems acceptable.

    But let's try with some other words.

    【code】

    print('Other words and their similarities:')
    word_list = ['lipstick', 'guns', 'science', 'arts', 'literature', 'warrior','doctor', 'tree', 'receptionist', 
                 'technology',  'fashion', 'teacher', 'engineer', 'pilot', 'computer', 'singer']
    for w in word_list:
        print (w, cosine_similarity(word_to_vec_map[w], g))
    

    【result】

    Other words and their similarities:
    lipstick 0.276919162564
    guns -0.18884855679
    science -0.0608290654093
    arts 0.00818931238588
    literature 0.0647250443346
    warrior -0.209201646411
    doctor 0.118952894109
    tree -0.0708939917548
    receptionist 0.330779417506
    technology -0.131937324476
    fashion 0.0356389462577
    teacher 0.179209234318
    engineer -0.0803928049452
    pilot 0.00107644989919
    computer -0.103303588739
    singer 0.185005181365
    

    Do you notice anything surprising? It is astonishing how these results reflect certain unhealthy gender stereotypes(成见). For example, "computer" is closer to "man" while "literature" is closer to "woman". Ouch!

    We'll see below how to reduce the bias of these vectors, using an algorithm due to Boliukbasi et al., 2016. Note that some word pairs such as "actor"/"actress" or "grandmother"/"grandfather" should remain gender specific, while other words such as "receptionist" or "technology" should be neutralized(中和), i.e. not be gender-related. You will have to treat these two type of words differently when debiasing.

    3.1 - Neutralize bias for non-gender specific words

    The figure below should help you visualize what neutralizing does. If you're using a 50-dimensional word embedding, the 50 dimensional space can be split into two parts: The bias-direction g, and the remaining 49 dimensions, which we'll call g. In linear algebra, we say that the 49 dimensional g is perpendicular(垂直) or othogonal (正交) to g, meaning it is at 90 degrees to g. The neutralization step takes a vector such as ereceptionisand zeros out the component in the direction of g, giving us .

    Exercise: Implement neutralize() to remove the bias of words such as "receptionist" or "scientist". Given an input embedding ee, you can use the following formulas to compute edebiased:

    If you are an expert in linear algebra, you may recognize ebias_component as the projection of ee onto the direction g. If you're not an expert in linear algebra, don't worry about this.

    【注】

    【code】

    def neutralize(word, g, word_to_vec_map):
        """
        Removes the bias of "word" by projecting it on the space orthogonal to the bias axis. 
        This function ensures that gender neutral words are zero in the gender subspace.
        
        Arguments:
            word -- string indicating the word to debias
            g -- numpy-array of shape (50,), corresponding to the bias axis (such as gender)
            word_to_vec_map -- dictionary mapping words to their corresponding vectors.
        
        Returns:
            e_debiased -- neutralized word vector representation of the input "word"
        """
        
        ### START CODE HERE ###
        # Select word vector representation of "word". Use word_to_vec_map. (≈ 1 line)
        e = word_to_vec_map[word]
        
        # Compute e_biascomponent using the formula give above. (≈ 1 line)
        e_biascomponent = (np.dot(e,g)/np.dot(g,g))*g
     
        # Neutralize e by substracting e_biascomponent from it 
        # e_debiased should be equal to its orthogonal projection. (≈ 1 line)
        e_debiased = e -  e_biascomponent
        ### END CODE HERE ###
        
        return e_debiased
    
    e = "receptionist"
    print("cosine similarity between " + e + " and g, before neutralizing: ", cosine_similarity(word_to_vec_map["receptionist"], g))
    
    e_debiased = neutralize("receptionist", g, word_to_vec_map)
    print("cosine similarity between " + e + " and g, after neutralizing: ", cosine_similarity(e_debiased, g))
    

    【result】

    cosine similarity between receptionist and g, before neutralizing:  0.330779417506
    cosine similarity between receptionist and g, after neutralizing:  -5.60374039375e-17
    

    【Expected Output】 The second result is essentially 0, up to numerical roundof (on the order of 1017).  

    cosine similarity between receptionist and g, before neutralizing: :	0.330779417506
    cosine similarity between receptionist and g, after neutralizing: :	-3.26732746085e-17

    【注】此处得到的 cosine similarity between receptionist and g, after neutralizing的值与期望值有一点点差异。应该是没有用seed的原因,但结果都接近0。

      

    3.2 - Equalization algorithm for gender-specific words

    Next, lets see how debiasing can also be applied to word pairs such as "actress" and "actor." Equalization is applied to pairs of words that you might want to have differ only through the gender property. As a concrete example, suppose that "actress" is closer to "babysit" than "actor." By applying neutralizing to "babysit" we can reduce the gender-stereotype associated with babysitting. But this still does not guarantee that "actor" and "actress" are equidistant from "babysit." The equalization algorithm takes care of this.

    The key idea behind equalization is to make sure that a particular pair of words are equi-distant from the 49-dimensional g. The equalization step also ensures that the two equalized steps are now the same distance from , or from any other work that has been neutralized. In pictures, this is how equalization works:

    【中文翻译】

    3.2 - 含性别特定词语的均衡算法
    接下来, 让我们看看如何 debiasing 也可以应用到词对, 如 "actress " 和 "actor". "均衡" 适用于您可能希望仅通过性别属性不同的单词对。作为一个具体的例子, 假设 "actress " 比 "actor"接近 "babysit " . 通过给"babysit "应用中和 , 我们可以减少与babysit有关的性别刻板印象。但这仍然不能保证 "actor " 、 "actress员" 和 "babysit" 是等距的. 均衡算法负责这一点。

    均衡的关键思想是确保特定的一对词与49维 g的距离是相等的。均衡步骤还确保两个均衡的步骤现在与的距离相同, 或与已中和的任何其他工作相同。在图片中, 这就是均衡的工作方式:

    The derivation of the linear algebra to do this is a bit more complex. (See Bolukbasi et al., 2016 for details.) But the key equations are:

    Exercise: Implement the function below. Use the equations above to get the final equalized version of the pair of words. Good luck!

    【code 】

    def equalize(pair, bias_axis, word_to_vec_map):
        """
        Debias gender specific words by following the equalize method described in the figure above.
    
        Arguments:
        pair -- pair of strings of gender specific words to debias, e.g. ("actress", "actor") 
        bias_axis -- numpy-array of shape (50,), vector corresponding to the bias axis, e.g. gender
        word_to_vec_map -- dictionary mapping words to their corresponding vectors
    
        Returns
        e_1 -- word vector corresponding to the first word
        e_2 -- word vector corresponding to the second word
        """
    
        ### START CODE HERE ###
        # Step 1: Select word vector representation of "word". Use word_to_vec_map. (≈ 2 lines)
        w1, w2 = pair
        e_w1, e_w2 = word_to_vec_map[w1], word_to_vec_map[w2]
    
        # Step 2: Compute the mean of e_w1 and e_w2 (≈ 1 line)
        mu = (e_w1 + e_w2)/2
    
        # Step 3: Compute the projections of mu over the bias axis and the orthogonal axis (≈ 2 lines)
        mu_B = np.dot(mu, bias_axis) / np.dot(bias_axis, bias_axis) * bias_axis
        mu_orth = mu - mu_B
    
        # Step 4: Use equations (7) and (8) to compute e_w1B and e_w2B (≈2 lines)
        e_w1B = np.dot(e_w1, bias_axis) / np.dot(bias_axis, bias_axis) * bias_axis
        e_w2B = np.dot(e_w2, bias_axis) / np.dot(bias_axis, bias_axis) * bias_axis
    
        # Step 5: Adjust the Bias part of e_w1B and e_w2B using the formulas (9) and (10) given above (≈2 lines)
        corrected_e_w1B = np.sqrt(np.abs(1-np.dot(mu_orth, mu_orth)))*(e_w1B-mu_B)/np.linalg.norm(e_w1 - mu_orth - mu_B)
        corrected_e_w2B = np.sqrt(np.abs(1-np.dot(mu_orth, mu_orth)))*(e_w2B-mu_B)/np.linalg.norm(e_w2 - mu_orth - mu_B)
    
        # Step 6: Debias by equalizing e1 and e2 to the sum of their corrected projections (≈2 lines)
        e1 = corrected_e_w1B + mu_orth
        e2 = corrected_e_w2B + mu_orth
    
        ### END CODE HERE ###
    
        return e1, e2
    
    print("cosine similarities before equalizing:")
    print("cosine_similarity(word_to_vec_map["man"], gender) = ", cosine_similarity(word_to_vec_map["man"], g))
    print("cosine_similarity(word_to_vec_map["woman"], gender) = ", cosine_similarity(word_to_vec_map["woman"], g))
    print()
    e1, e2 = equalize(("man", "woman"), g, word_to_vec_map)
    print("cosine similarities after equalizing:")
    print("cosine_similarity(e1, gender) = ", cosine_similarity(e1, g))
    print("cosine_similarity(e2, gender) = ", cosine_similarity(e2, g))
    

    【result】

    cosine similarities before equalizing:
    cosine_similarity(word_to_vec_map["man"], gender) =  -0.117110957653
    cosine_similarity(word_to_vec_map["woman"], gender) =  0.356666188463
    
    cosine similarities after equalizing:
    cosine_similarity(e1, gender) =  -0.700436428931
    cosine_similarity(e2, gender) =  0.700436428931
    

    Expected Output  

    cosine similarities before equalizing:
    
    cosine_similarity(word_to_vec_map["man"], gender) =	-0.117110957653
    cosine_similarity(word_to_vec_map["woman"], gender) =	0.356666188463
    cosine similarities after equalizing:
    
    cosine_similarity(u1, gender) =	-0.700436428931
    cosine_similarity(u2, gender) =	0.700436428931
    

    Please feel free to play with the input words in the cell above, to apply equalization to other pairs of words.

    These debiasing algorithms are very helpful for reducing bias, but are not perfect and do not eliminate all traces of bias. For example, one weakness of this implementation was that the bias direction gg was defined using only the pair of words woman and man. As discussed earlier, if gg were defined by computing g1=ewomanemang2=emotherefatherg3=egirleboy; and so on and averaging over them, you would obtain a better estimate of the "gender" dimension in the 50 dimensional word embedding space. Feel free to play with such variants as well.

      

    Congratulations

    You have come to the end of this notebook, and have seen a lot of the ways that word vectors can be used as well as modified.

    Congratulations on finishing this notebook!

      

    References:

  • 相关阅读:
    [LeetCode] 687. Longest Univalue Path
    [Daily Coding Problem] 1 (LeetCode 1). Find if two numbers in an array add up to k
    [Daily Coding Problem] 18 (LeetCode 239). Sliding Window Maximum
    [Daily Coding Problem 24] Implement locking in a binary tree.
    [LeetCode] 208(LintCode). Implement Trie(Prefix Tree)
    [Daily Coding Problem] 16. Last N order ids implementation
    队伍总结 2017年5月14日
    ECNU 3260 袋鼠妈妈找孩子(dfs)
    ECNU 3263 丽娃河的狼人传说 (贪心)
    UVA 213 信息解码(二进制&位运算)
  • 原文地址:https://www.cnblogs.com/hezhiyao/p/8648119.html
Copyright © 2011-2022 走看看