<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【NLP】用code2vec、glow和spaCy進(jìn)行詞嵌入

          共 4342字,需瀏覽 9分鐘

           ·

          2020-08-31 03:26

          作者 | Maria Malitckaya?

          編譯 | VK?

          來源 | Towards Data Science

          改進(jìn)機(jī)器學(xué)習(xí)模型的一個(gè)有效方法是使用詞嵌入。使用詞嵌入,你可以捕獲文檔中單詞的上下文,然后找到語義和語法上的相似之處。

          在這篇文章中,我們將討論詞嵌入技術(shù)的一個(gè)不尋常的應(yīng)用。我們將嘗試使用OpenAPI的規(guī)范作為數(shù)據(jù)集在其中找到最好的詞嵌入技術(shù)。作為OpenAPI規(guī)范的一個(gè)例子,我們將使用OpenAPI specifications(https://swagger.io/specification/)提供的OpenAPI規(guī)范數(shù)據(jù)集。

          最大的挑戰(zhàn)是,OpenAPI規(guī)范既不是自然語言,也不是代碼。但這也意味著我們可以自由使用任何可用的嵌入模型。在這個(gè)實(shí)驗(yàn)中,我們將研究三種可能可行的候選方案:code2vec、glow和spaCy。

          code2vec是一個(gè)神經(jīng)模型,可以學(xué)習(xí)與源代碼相關(guān)的類比。該模型是在Java代碼數(shù)據(jù)庫上訓(xùn)練的,但是你可以將其應(yīng)用于任何代碼。

          還有GloVe。GloVe是一種常用的自然語言處理算法。它是在維基百科和Gigawords上訓(xùn)練的。

          最后,我們有了spaCy。雖然spaCy是最近才發(fā)展起來的,但該算法已經(jīng)以世界上最快的詞嵌入而聞名。

          讓我們看看這些算法中哪一種更適合OpenAPI數(shù)據(jù)集,哪種算法對于OpenAPI規(guī)范的運(yùn)行速度更快. 我把這篇文章分為六個(gè)部分,每個(gè)部分都包含代碼示例和一些將來使用的提示,外加一個(gè)結(jié)論。

          1. 下載數(shù)據(jù)集

          2. 下載詞匯表

          3. 提取字段名稱

          4. 標(biāo)識化

          5. 創(chuàng)建字段名稱的數(shù)據(jù)集

          6. 測試嵌入

          7. 結(jié)論

          現(xiàn)在,我們可以開始了。

          1.下載數(shù)據(jù)集

          首先,我們需要下載整個(gè)apis-guru數(shù)據(jù)庫:https://apis.guru/。

          你會(huì)注意到,大多數(shù)apis-guru規(guī)范都是Swagger 2.0格式。但是,OpenAPI規(guī)范的最新版本是OpenAPI 3.0。

          因此,讓我們使用Unmock腳本將整個(gè)數(shù)據(jù)集轉(zhuǎn)換為這種格式!你可以按照Unmock openapi腳本的README文件中的說明完成此操作:https://github.com/meeshkan/unmock-openapi-scripts/blob/master/README.md。

          這可能需要一段時(shí)間,最后,你將得到一個(gè)大數(shù)據(jù)集。

          2.下載詞匯表

          「code2vec」

          1. 從code2vec GitHub頁面下載模型,按照快速入門部分中的說明進(jìn)行操作。

          2. 使用gensim庫加載。

          model?=?word2vec.load_word2vec_format(vectors_text_path,?binary=False)

          「GloVe」

          1. 從網(wǎng)站下載一個(gè)GloVe詞匯表。我們選了最大的一個(gè),因?yàn)檫@樣它就更有可能找到我們所有的單詞。你可以選擇下載它的位置,但為了方便起見,最好將其存儲(chǔ)在工作目錄中。

          2. 手動(dòng)加載GloVe詞匯表。

          embeddings_dict?=?{}
          with?open("../glove/glove.6B.300d.txt",?'r',?encoding="utf-8")?as?f:
          ????for?line?in?f:
          ????????values?=?line.split()
          ????????word?=?values[0]
          ????????vector?=?np.asarray(values[1:],?"float32")
          ????????embeddings_dict[word]?=?vector

          「spaCy」

          加載spaCy的詞匯表:

          nlp?=?spacy.load(‘en_core_web_lg’).

          3.提取字段名

          OpenAPI規(guī)范名稱的整個(gè)列表可以從scripts/fetch-list.sh文件或使用以下函數(shù)(對于Windows)獲?。?/p>

          def?getListOfFiles(dirName):
          ????listOfFile?=?os.listdir(dirName)
          ????allFiles?=?list()
          ????for?entry?in?listOfFile:
          ????????fullPath?=?posixpath.join(dirName,?entry)
          ????????if?posixpath.isdir(fullPath):
          ????????????allFiles?=?allFiles?+?getListOfFiles(fullPath)
          ????????else:
          ????????????allFiles.append(fullPath)
          ????????????????
          ????return?allFiles

          另一個(gè)大問題是從我們的OpenAPI規(guī)范中獲取字段名。為此,我們將使用openapi-typed庫。讓我們定義一個(gè)get_fields函數(shù),該函數(shù)接受OpenAPI規(guī)范并返回字段名列表:

          def?get_fields_from_schema(o:?Schema)?->?Sequence[str]:
          ????return?[
          ????????*(o['properties'].keys()?if?('properties'?in?o)?and?(type(o['properties'])?==?type({}))?else?[]),
          ????????*(sum([
          ????????????get_fields_from_schema(schema)?for?schema?in?o['properties'].values()?if?not?('$ref'?in?schema)?and?type(schema)?==?type({})],?[])?if?('properties'?in?o)?and?($????????*(get_fields_from_schema(o['additionalProperties'])?if?('additionalProperties'?in?o)?and?(type(o['additionalProperties'])?==?type({}))?else?[]),
          ????????*(get_fields_from_schema(o['items'])?if?('items'?in?o)?and??(type(o['items']?==?type({})))?else?[]),
          ????]

          def?get_fields_from_schemas(o:?Mapping[str,?Union[Schema,?Reference]])?->?Sequence[str]:
          ????return?sum([get_fields_from_schema(cast(Schema,?maybe_schema))?for?maybe_schema?in?o.values()?if?not?('$ref'?in?maybe_schema)?and?(type(maybe_schema)?==?type({}))],?[])


          def?get_fields_from_components(o:?Components)?->?Sequence[str]:
          ????return?[
          ????????*(get_fields_from_schemas(o['schemas'])?if?'schemas'?in?o?else?[]),
          ????????????]???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

          def?get_fields(o:?OpenAPIObject)?->?Sequence[str]:
          ????return?[
          ????????*(get_fields_from_components(o['components'])?if?'components'?in?o?else?[]),
          ????]

          恭喜!現(xiàn)在我們的數(shù)據(jù)集準(zhǔn)備好了。

          4.標(biāo)識化

          字段名可能包含標(biāo)點(diǎn)符號,如_和-符號,或大小寫為駝峰的單詞。我們可以把這些單詞切分,稱為標(biāo)識。

          下面的camel_case函數(shù)檢查駝峰命名。首先,它檢查是否有標(biāo)點(diǎn)符號。如果是,那就不是駝峰命名。然后,它檢查單詞內(nèi)部是否有大寫字母(不包括第一個(gè)和最后一個(gè)字符)。

          def?camel_case(example):??????
          ????if??any(x?in?example?for?x??in?string.punctuation)==True:
          ????????return?False
          ????else:
          ????????if?any(list(map(str.isupper,?example[1:-1])))==True:
          ????????????return?True
          ????????else:
          ????????????return?False

          下一個(gè)函數(shù)camel_case_split將駝峰單詞拆分為多個(gè)部分。為此,我們應(yīng)該識別大寫字母并標(biāo)記大小寫更改的位置。函數(shù)返回拆分后的單詞列表。例如,字段名BodyAsJson轉(zhuǎn)換為一個(gè)列表['Body','As','Json']。

          def?camel_case_split(word):
          ????idx?=?list(map(str.isupper,?word))
          ????case_change?=?[0]
          ????for?(i,?(x,?y))?in?enumerate(zip(idx,?idx[1:])):
          ????????if?x?and?not?y:??
          ????????????case_change.append(i)
          ????????elif?not?x?and?y:??
          ????????????case_change.append(i+1)
          ????case_change.append(len(word))
          ????return?[word[x:y]?for?x,?y?in?zip(case_change,?case_change[1:])?if?x?

          這個(gè)camel_case_split函數(shù)隨后用于以下標(biāo)記化算法。在這里,我們首先檢查單詞中是否有標(biāo)點(diǎn)符號。然后,我們把這個(gè)詞分成幾部分。這些詞有可能是駝峰詞。如果是這樣的話,我們可以把它分成小塊。最后,拆分每個(gè)元素后,整個(gè)列表將轉(zhuǎn)換為小寫。

          def?tokenizer(mylist):
          ????tokenized_list=[]
          ????for?word?in?mylist:

          ????????if?'_'??in?word:
          ????????????splitted_word=word.split('_')
          ????????????for?elem?in?splitted_word:
          ????????????????if?camel_case(elem):
          ????????????????????elem=camel_case_split(elem)
          ????????????????????for?el1?in?elem:
          ????????????????????????tokenized_list.append(el1.lower())
          ????????????????else:????
          ????????????????????tokenized_list.append(elem.lower())
          ????????elif?'-'?in?word:
          ????????????hyp_word=word.split('-')
          ????????????for?i?in?hyp_word:
          ????????????????if?camel_case(i):
          ????????????????????i=camel_case_split(i)
          ????????????????????for?el2?in?i:
          ????????????????????????tokenized_list.append(el2.lower())
          ????????????????else:?
          ????????????????????tokenized_list.append(i.lower())
          ????????elif?camel_case(word):
          ????????????word=camel_case_split(word)
          ????????????for?el?in?word:
          ????????????????tokenized_list.append(el.lower())
          ????????else:
          ????????????tokenized_list.append(word.lower())
          ????return(tokenized_list)
          tokenizer(my_word)

          5.創(chuàng)建字段名的數(shù)據(jù)集

          現(xiàn)在,讓我們用所有規(guī)范中的字段名創(chuàng)建一個(gè)大數(shù)據(jù)集。

          下面的dict_dataset函數(shù)獲取文件名和路徑的列表,并打開每個(gè)規(guī)范文件。對于每個(gè)文件,get_field函數(shù)返回字段名的列表。某些字段名稱可能在一個(gè)規(guī)范中重復(fù)。為了避免這種重復(fù),讓我們使用list(dict.fromkeys(col))將列表中的字段名列表轉(zhuǎn)換為字典,然后再返回。然后我們可以將列表標(biāo)識化。最后,我們創(chuàng)建一個(gè)以文件名為鍵,以字段名列表為值的字典。

          def?dict_dataset(datasets):
          ????dataset_dict={}
          ????for?i?in?datasets:
          ????????with?open(i,?'r')?as?foo:
          ????????????col=algo.get_fields(yaml.safe_load(foo.read()))
          ????????????if?col:
          ????????????????mylist?=?list(dict.fromkeys(col))
          ????????????????tokenized_list=tokenizer(mylist)
          ????????????????dataset_dict.update({i:?tokenized_list})
          ????????????else:
          ????????????????continue
          ????return?(dataset_dict)

          6.測試嵌入

          「code2vec和GloVe」

          現(xiàn)在我們可以找出詞匯表外的單詞(未識別的單詞)并計(jì)算這些單詞在code2vec詞匯表中所占的百分比。以下代碼也適用于GloVe。

          not_identified_c2v=[]
          count_not_indent=[]
          total_number=[]

          for?ds?in?test1:
          ????count=0
          ????for?i?in?data[ds]:
          ????????if?not?i?in?model:
          ????????????not_identified_c2v.append(i)
          ????????????count+=1
          ????count_not_indent.append(count)
          ????total_number.append(len(data[ds]))

          total_code2vec=sum(count_not_indent)/sum(total_number)*100

          「spaCy」

          spaCy詞匯表不同,因此我們需要相應(yīng)地修改代碼:

          not_identified_sp=[]
          count_not_indent=[]
          total_number=[]

          for?ds?in?test1:
          ????count=0
          ????for?i?in?data[ds]:
          ????????f?not?i?in?nlp.vocab:
          ????????????????count+=1
          ????????????????not_identified_sp.append(i)
          ????count_not_indent.append(count)
          ????total_number.append(len(data[ds]))

          ????????
          total_spacy=sum(count_not_indent)/sum(total_number)*100

          對于code2vec、glow和spaCy,未識別單詞的百分比分別為3.39、2.33和2.09。由于每個(gè)算法的百分比相對較小且相似,因此我們可以進(jìn)行另一個(gè)測試。

          首先,讓我們創(chuàng)建一個(gè)測試字典,其中的單詞應(yīng)該在所有API規(guī)范中都是相似的:

          test_dictionary={'host':?'server',
          'pragma':?'cache',
          'id':?'uuid',
          'user':?'client',
          'limit':?'control',
          'balance':?'amount',
          'published':?'date',
          'limit':?'dailylimit',
          'ratelimit':?'rate',
          'start':?'display',
          'data':?'categories'}

          對于GloVe和code2vec,我們可以使用gensim庫提供的similar_by_vector方法。spaCy還沒有實(shí)現(xiàn)這個(gè)方法,但是通過這個(gè)我們可以自己找到最相似的單詞。

          為此,我們需要格式化輸入向量,以便在距離函數(shù)中使用。我們將在字典中創(chuàng)建每個(gè)鍵,并檢查對應(yīng)的值是否在100個(gè)最相似的單詞中。

          首先,我們將格式化詞匯表以便使用distance.cdist函數(shù)。這個(gè)函數(shù)計(jì)算詞匯表中每對向量之間的距離。然后,我們將從最小距離到最大距離對列表進(jìn)行排序,并取前100個(gè)單詞。

          from?scipy.spatial?import?distance

          for?k,?v?in?test_dictionary.items():
          ????input_word?=?k
          ????p?=?np.array([nlp.vocab[input_word].vector])
          ????closest_index?=?distance.cdist(p,?vectors)[0].argsort()[::-1][-100:]
          ????word_id?=?[ids[closest_ind]?for?closest_ind?in?closest_index]
          ????output_word?=?[nlp.vocab[i].text?for?i?in?word_id]
          ????#output_word
          ????list1=[j.lower()?for?j?in?output_word]
          ????mylist?=?list(dict.fromkeys(list1))[:50]
          ????count=0
          ????if?test_dictionary[k]?in?mylist:
          ????????count+=1
          ????????print(k,count,?'yes')
          ????else:
          ????????print(k,?'no')

          下表總結(jié)了結(jié)果。spaCy顯示單詞“client”位于單詞“user”的前100個(gè)最相似的單詞中。它對幾乎所有的OpenAPI規(guī)范都是有用的,并且可以用于將來OpenAPI規(guī)范相似性的分析。單詞“balance”的向量接近單詞“amount”的向量。我們發(fā)現(xiàn)它對支付API特別有用。

          結(jié)論

          我們已經(jīng)為OpenAPI規(guī)范嘗試了三種不同的詞嵌入算法。盡管這三個(gè)詞在這個(gè)數(shù)據(jù)集上都表現(xiàn)得很好,但是對最相似的單詞進(jìn)行額外的比較表明spaCy對我們的情況更好。

          spaCy比其他算法更快。spaCy詞匯表的讀取速度比glow或code2vec詞匯表快5倍。然而,在使用該算法時(shí),缺少內(nèi)置函數(shù)(如similar_by_vector和similar_word)是一個(gè)障礙。

          另外,spaCy與我們的數(shù)據(jù)集很好地工作,這并不意味著spaCy對世界上的每個(gè)數(shù)據(jù)集都會(huì)更好。所以,請隨意嘗試為你自己的數(shù)據(jù)集嵌入不同的單詞,感謝你的閱讀!

          原文鏈接:https://towardsdatascience.com/word-embeddings-with-code2vec-glove-and-spacy-5b26420bf632



          往期精彩回顧





          獲取一折本站知識星球優(yōu)惠券,復(fù)制鏈接直接打開:

          https://t.zsxq.com/662nyZF

          本站qq群1003271085。

          加入微信群請掃碼進(jìn)群(如果是博士或者準(zhǔn)備讀博士請說明):

          瀏覽 56
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩成人性爱视频 | 大香蕉国语黄色录像 | 麻豆免费视频在线观看 | 国产真空露出福利视频 | 午夜福利视频一区 |