一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

手把手教你使用Keras構(gòu)造日文的神經(jīng)網(wǎng)絡語言模型(內(nèi)附源碼)

 新用戶0175WbuX 2022-02-18

  手把手教你使用Keras構(gòu)造日文的神經(jīng)網(wǎng)絡語言模型(內(nèi)附源碼)

  作者:GjZero

  標簽:Python, Keras, 語言模型, 日語

  本文約2400字,建議閱讀10分鐘。

  本文介紹了語言模型,并介紹如何用MeCab和Keras實現(xiàn)一個日文的神經(jīng)網(wǎng)絡語言模型。(為什么是日文呢?純屬作者興趣)

  依據(jù)Wikepedia,語言模型的定義是“句子們的概率分布”。給定一個長度為m的句子,則可以有概率

  P(w_1,...,w_m)

  由條件概率公式有

  P(w_1,...w_m)=\prod_{i=1}^mP(w_i|w_1,...w_{i-1})

  n-gram模型假設,第i個詞語的概率分布只和前面固定的n個詞有關(Markov性),那么就有

  P(w_1,...w_m)=\prod_{i=1}^mP(w_i|w_1,...w_{i-1}) \approx \prod_{i=1}^mP(w_i|w_{i-(n-1)},...,w_{i-1})

  所以估計

  P(w_1,...w_m)

  的任務變成了估計

  P(w_i|w_{i-(n-1)},...,w_{i-1})

  用傳統(tǒng)的統(tǒng)計方法面臨著

  維度災難(當n變大,存儲空間不夠)n元組并不會在語料庫中全部出現(xiàn)

  所以這里使用神經(jīng)網(wǎng)絡近似函數(shù)

  P(w_i|w_{i-(n-1)},...,w_{i-1})

  神經(jīng)網(wǎng)絡方法解決了如上兩個困難

  當n變大,神經(jīng)網(wǎng)絡的參數(shù)以線性級別增長n元組雖然沒有全部出現(xiàn),但詞向量可以捕捉到不同的詞可能代表的相似的含義

  一個傳統(tǒng)的基于神經(jīng)網(wǎng)絡的模型結(jié)構(gòu)如下圖所示:

  手把手教你使用Keras構(gòu)造日文的神經(jīng)網(wǎng)絡語言模型(內(nèi)附源碼)

  MeCab(めかぶ)是一款日語分詞工具。Linux用戶可以用如下指令安裝MeCab:

  sudo apt-get install mecab mecab-ipadic-utf8 libmecab-dev swigpip install mecab-python3

  MeCab可以對一個句子進行分詞,并分析各詞的詞性。對于句子“すもももももももものうち”有

  すもももももももものうちすもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモも 助詞,係助詞,*,*,*,*,も,モ,モもも 名詞,一般,*,*,*,*,もも,モモ,モモも 助詞,係助詞,*,*,*,*,も,モ,モもも 名詞,一般,*,*,*,*,もも,モモ,モモの 助詞,連體化,*,*,*,*,の,ノ,ノうち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ

  EOS

  為了將分析的結(jié)果轉(zhuǎn)化為分詞結(jié)果,可用如下的`mecab_to_text`函數(shù),則會輸出“すもも も もも も もも の うち”。

  Python

  def mecab_to_text(sentence_list):

  """

  :param sentence_list: A list of sentences or one single sentence.

  :return: A list of segmented sentences.

  :note: Use mecab to segment a list of sentences or one single sentence in Japanese.

  """

  import MeCab

  mecab=MeCab.Tagger("-Ochasen")

  single_flag=False

  if isinstance(sentence_list, str):

  sentence_list=[sentence_list]

  single_flag=True

  ret_list=[]

  for sentence in sentence_list:

  text_list=[]

  m=mecab.parseToNode(sentence)

  while m:

  text_list.append(m.surface)

  m=m.next

  seg_sentence=" ".join(text_list).strip()

  ret_list.append(seg_sentence)

  if single_flag:

  return ret_list[0]

  return ret_list

  我們需要先構(gòu)建我們的訓練樣本,語料庫來自日語小說。對語料庫中的句子用MeCab進行分詞之后,用給定的窗寬k分割出訓練集。訓練集中的詞和詞向量進行對應為300維的向量。這樣訓練集中的每一個x(特征)對應一個(k-1)×300維的矩陣,每一個y(結(jié)果)對應一個one-hot的向量。

  語料庫

  語料庫是來自于網(wǎng)絡上的日語小說,因為版權(quán)因素這里不提供下載。用什么樣的小說并不會太影響我們后續(xù)的過程。在這里實現(xiàn)了`load_text`,`make_word_dictionary`,`clear_dictionary`;分別用來讀入語料庫,從分好詞的語料庫中生成詞典,清理詞典中在詞向量里沒有出現(xiàn)的詞。

  Python

  def load_text(use_length=-1, min_len=10):

  start=time.clock()

  japanese_text_path="H:\\Work\\JapaneseModel\\Japanese_book\"

  text_list=[]

  if use_length==-1:

  for file in os.listdir(japanese_text_path):

  with open(japanese_text_path + file, 'r', encoding='utf-8') as f:

  for line in f.readlines():

  line_use=line.strip()

  if len(line_use) > min_len:

  text_list.append(line_use)

  else:

  counter=0

  for file in os.listdir(japanese_text_path):

  with open(japanese_text_path + file, 'r', encoding='utf-8') as f:

  for line in f.readlines():

  line_use=line.strip()

  if len(line_use) > min_len:

  text_list.append(line_use)

  counter +=1

  if counter==use_length:

  print("Japanese text loaded %d lines."%use_length)

  elapsed=time.clock() - start

  print("Time used:", round(elapsed, 3))

  return text_list

  print("Japanese text loaded all lines.")

  elapsed=time.clock() - start

  print("Time used:", round(elapsed, 3))

  return text_list

  def make_word_dictionary(split_text_list, lower_bound=100):

  start=time.clock()

  word_dictionary=dict()

  for sentence in split_text_list:

  sentence_use=sentence.split(" ")

  for word in sentence_use:

  if not word in word_dictionary:

  word_dictionary[word]=1

  else:

  word_dictionary[word] +=1

  print("Word dictionary established.")

  elapsed=time.clock() - start

  print("Time used:", round(elapsed, 3))

  if lower_bound > 0:

  pop_list=[]

  for word in word_dictionary:

  if word_dictionary[word] < lower_bound:

  pop_list.append(word)

  for word in pop_list:

  word_dictionary.pop(word)

  word_list=[]

  for word in word_dictionary:

  word_list.append(word)

  return word_list

  def clear_dictionary(dictionary, embedding_dictionary):

  ret_list=[]

  for word in dictionary:

  if word in embedding_dictionary:

  ret_list.append(word)

  return ret_list

  實現(xiàn)了這幾個函數(shù)以后,就可以用如下的方式讀入語料庫。

  Python

  japanese_text=load_text(use_text_length)

  split_japanese_text=mecab_to_text(japanese_text)

  dictionary=make_word_dictionary(split_japanese_text, lower_bound=10)

  dictionary=clear_dictionary(dictionary, embeddings_index)

  我們使用facebook在fastText項目中預訓練好的日語300維詞向量,下載地址點擊[這里](

  s3-us-west-1.amazonaws/fasttext-vectors/word-vectors-v2/cc.ja.300.vec.gz)。因為該文件的第一行保存了詞向量文件的信息,你應該手動刪除該行,然后用`load_embedding`函數(shù)來讀取詞向量。

  Python

  def load_embedding():

  start=time.clock()

  """

  Total 2000000 words in this embedding file, 300-d. It is float16 type.

  The first line is "2000000 300".

  You should delete this line.

  """

  EMBEDDING_FILE='H:\\Work\\cc.ja.300.vec'

  def get_coefs(word, *arr): return word, np.asarray(arr, dtype='float16')

  embeddings_index=dict(get_coefs(*o.strip().split(" ")) for o in open(EMBEDDING_FILE, 'r', encoding="utf-8"))

  elapsed=time.clock() - start

  print("Word vectors loaded.")

  print("Time used:", round(elapsed, 3))

  return embeddings_index

  假設我們的窗寬為k,那么我們的訓練集技巧教程由k-1個詞組成x_train,由之后連接的詞組成y_train。如果k=3,我們語料庫中的一個句子為“a bb ccc d”, 其中a、bb、ccc、d分別是4個詞。那么我們將這個句子前面連接k-1=2個“space”,結(jié)尾連接一個“eol”,擴充為“space space a bb ccc d eof”。這樣可以得到如下的訓練樣本:

  x1|x2|y:- | :- | :-space|space|aspace|a|bba|bb|cccbb|ccc|dccc|d|eol

  “generate_train”函數(shù)實現(xiàn)了上述生成訓練集的算法

  Python

  def generate_train(window, end_index, text_seq):

  prefix=[0] * (window - 1)

  suffix=[end_index]

  x_list=[]

  y_list=[]

  for seq in text_seq:

  if len(seq) > 1:

  seq_use=prefix + seq + suffix

  # print(seq_use)

  for i in range(len(seq_use) - window + 1):

  x_list.append(seq_use[i: i + window - 1])

  y_list.append(seq_use[i + window - 1])

  # print(seq_use[i: i + window])

  return x_list, y_list

  和傳統(tǒng)的神經(jīng)網(wǎng)絡語言模型有所不同:先將x映射為詞向量,連接雙層BiLSTM作為隱藏層,再連接一個Softmax來預測下一個詞是什么。在Keras中,實現(xiàn)BiLSTM非常容易。因為`CuDNNLSTM`的實現(xiàn)比`LSTM`要快很多,推薦安裝cudnn來使用這個函數(shù)。加入了一些`Dropout`層來避免過擬合。

  Python

  # Model

  inp=Input(shape=(window - 1,))

  x=Embedding(nb_words, 300, trainable=True, weights=[embedding_matrix])(inp)

  x=Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)

  x=Dropout(0.1)(x)

  x=Bidirectional(CuDNNLSTM(128, return_sequences=False))(x)

  x=Dropout(0.1)(x)

  x=Dense(128, activation="relu")(x)

  x=Dropout(0.1)(x)

  x=Dense(nb_words, activation="softmax")(x)

  model=Model(inputs=inp, outputs=x)

  opt=keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999,

  epsilon=None, decay=0.0, amsgrad=False)

  modelpile(loss='categorical_crossentropy',

  optimizer=opt, metrics=['accuracy'])

  history=LossHistory()

  epoch_nb=80 # 40 is enough

  batch=64

  model.fit(x_train, y_train, batch_size=batch, epochs=epoch_nb, verbose=1,

  validation_data=(x_test, y_test), callbacks=[history])

  用`predict_random_sentence`函數(shù)來生成隨機句子,其中的`reverse_index`保存了從語料庫生成的詞典中的詞和序號的一一對應。若將[0,0,0,0]更改為其他數(shù)字,即可生成給定開頭的句子。

  Python

  def predict_random_sentence(new=[0] * (window - 1)):

  sentence=reverse_index[new[0]] + reverse_index[new[1]] + reverse_index[new[2]] + reverse_index[new[3]]

  while new[-1] !=end_index:

  prob=model.predict(np.asarray([new]))[0]

  new_predict=int(random.choices(word_ind, weights=prob)[0])

  sentence +=reverse_index[new_predict]

  new=new[1:] + [new_predict]

  return sentence

  predict_random_sentence([0,0,0,0])

  保存模型到本地,以后就可以直接調(diào)用,避免重復訓練。上文中提到的tokenizer和神經(jīng)網(wǎng)絡模型都需要保存。

  Python

  with open("../result/tokenizer.pkl", "wb") as handle:

  pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL)

  model.save('../model/language_model.model')

  我們訓練了80個epoch,使用了20000句話進行訓練,選擇的窗寬為5。以下是從日文語言模型中隨機生成的一些句子。

  '「なんだろう。僕が仕事を休みになり、でもまあ……見てた」''アグライアはグラスをじっと見つめた。''それにしても、それを使って、ジークをから表情になって貓のように《さ》がを受けた。''森そうだ、そんなことか」''真剣で命をように、そのの人は、辻宮氏はだいたい邸にてあげた《と?》みをうとした?!袱饯螭暑啢坤盲平瘢俊?#39;'佳澄ちゃんが……俺とさっきに言わせて下さい。''沙耶「まあ、沙耶ねえ先に戻ることにになってきます?」''「最近はどうしてそういうつもりじゃないでしょうね」'

  簡單的翻譯一下生成的句子(日語水平比較爛,可能翻譯錯了)

  '怎么說呢。我雖然下班了,但還是……看到了'

  'Agria凝視著玻璃杯'

  '即使如此,使用它,Sieg看來像貓一樣的表情接受了さ'

  '像樹林啊,是這樣嗎'

  這句話實在不太通順……

  '佳澄醬,請給我說下剛才的事情'

  '沙耶:“嘛,沙耶先回去了?。俊?#39;

  '最近為什么不打算這樣做了呢'

  總體來說,該語言模型可以生成出一些通順的話語。以上都是從空句子開始生成的,也可以改變生成句子的開頭。

  項目地址及參考文獻

  完整的項目代碼見

  [GitHub]

  (github/GanjinZero/DeepLearningPlayground/tree/master/code/Language%20Model)

  [Language_model]

  (en.wikipedia/wiki/Language_model)

  [MeCab]

  (taku910.github/mecab/)

  [fastText]

  (github/facebookresearch/fastText/blob/master/docs/crawl-vectors.md)

  【作者簡介】

  手把手教你使用Keras構(gòu)造日文的神經(jīng)網(wǎng)絡語言模型(內(nèi)附源碼)

  GjZero,清華大學統(tǒng)計中心博士二年級在讀。研究方向是醫(yī)學信息學中的自然語言處理。興趣是撲克、麻將等和博弈論有關的運動。

  編輯:王菁

  校對:林亦霖

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    激情三级在线观看视频| 亚洲中文字幕在线视频频道| 果冻传媒精选麻豆白晶晶 | 五月婷婷六月丁香亚洲| 婷婷亚洲综合五月天麻豆| 国产综合一区二区三区av| 国产成人精品午夜福利av免费| 男女午夜在线免费观看视频| 日本午夜一本久久久综合| 中日韩免费一区二区三区| 九九热精彩视频在线免费| 欧美一级特黄大片做受大屁股| 视频一区二区三区自拍偷| 欧美亚洲国产日韩一区二区| 亚洲精品成人福利在线| 欧美国产极品一区二区| 中文久久乱码一区二区| 青草草在线视频免费视频| 色鬼综合久久鬼色88| 观看日韩精品在线视频| 欧美日韩国产成人高潮| 美女黄色三级深夜福利| 日韩欧美国产精品中文字幕| 国产又色又粗又黄又爽| 中文字幕欧美精品人妻一区| 日本在线 一区 二区| 国产不卡免费高清视频| 色婷婷久久五月中文字幕| 国产又粗又猛又长又黄视频| 国产一级特黄在线观看| 色婷婷久久五月中文字幕| 九九热视频经典在线观看 | 亚洲中文在线观看小视频| 激情五月天深爱丁香婷婷| 99少妇偷拍视频在线| 91人妻丝袜一区二区三区| 久久综合日韩精品免费观看| 日本办公室三级在线观看| 好吊一区二区三区在线看| 国产一区一一一区麻豆| 精品一区二区三区乱码中文|