|
本文中將介紹一個流行的機器學習項目——文本生成器,你將了解如何構建文本生成器,并了解如何實現馬爾可夫鏈以實現更快的預測模型。 ![]() 文本生成器簡介文本生成在各個行業(yè)都很受歡迎,特別是在移動、應用和數據科學領域。甚至新聞界也使用文本生成來輔助寫作過程。 在日常生活中都會接觸到一些文本生成技術,文本補全、搜索建議,Smart Compose,聊天機器人都是應用的例子, 本文將使用馬爾可夫鏈構建一個文本生成器。這將是一個基于字符的模型,它接受鏈的前一個字符并生成序列中的下一個字母。 通過使用樣例單詞訓練我們的程序,文本生成器將學習常見的字符順序模式。然后,文本生成器將把這些模式應用到輸入,即一個不完整的單詞,并輸出完成該單詞的概率最高的字符。 ![]() 文本生成是自然語言處理的一個分支,它根據之前觀察到的語言模式預測并生成下一個字符。 在沒有機器學習之前,NLP是通過創(chuàng)建一個包含英語中所有單詞的表,并將傳遞的字符串與現有的單詞匹配來進行文字生成的。這種方法有兩個問題。
機器學習和深度學習的出現,使得NLP允許我們大幅減少運行時并增加通用性,因為生成器可以完成它以前從未遇到過的單詞。如果需要NLP可以擴展到預測單詞、短語或句子! 對于這個項目,我們將專門使用馬爾可夫鏈來完成。馬爾可夫過程是許多涉及書面語言和模擬復雜分布樣本的自然語言處理項目的基礎。 馬爾可夫過程是非常強大的,以至于它們只需要一個示例文檔就可以用來生成表面上看起來真實的文本。 什么是馬爾可夫鏈?馬爾可夫鏈是一種隨機過程,它為一系列事件建模,其中每個事件的概率取決于前一個事件的狀態(tài)。該模型有一組有限的狀態(tài),從一個狀態(tài)移動到另一個狀態(tài)的條件概率是固定的。 每次轉移的概率只取決于模型的前一個狀態(tài),而不是事件的整個歷史。 例如,假設想要構建一個馬爾可夫鏈模型來預測天氣。 在這個模型中我們有兩種狀態(tài),晴天或雨天。如果我們今天一直處于晴朗的狀態(tài),明天就有更高的概率(70%)是晴天。雨也是如此;如果已經下過雨,很可能還會繼續(xù)下雨。 但是天氣會改變狀態(tài)是有可能的(30%),所以我們也將其包含在我們的馬爾可夫鏈模型中。 ![]() 馬爾可夫鏈是我們這個文本生成器的完美模型,因為我們的模型將僅使用前一個字符預測下一個字符。使用馬爾可夫鏈的優(yōu)點是,它是準確的,內存少(只存儲1個以前的狀態(tài))并且執(zhí)行速度快。 文本生成的實現這里將通過6個步驟完成文本生成器:
![]() 1、生成查找表 首先,我們將創(chuàng)建一個表,記錄訓練語料庫中每個字符狀態(tài)的出現情況。從訓練語料庫中保存最后的' K '字符和' K+1 '字符,并將它們保存在一個查找表中。 例如,想象我們的訓練語料庫包含,“the man was, they, then, the, the”。
下面是查找表中的結果: ![]() 在上面的例子中,我們取K = 3,表示將一次考慮3個字符,并將下一個字符(K+1)作為輸出字符。在上面的查找表中將單詞(X)作為字符,將輸出字符(Y)作為單個空格(' '),因為第一個the后面沒有單詞了。此外還計算了這個序列在數據集中出現的次數,在本例中為3次。 這樣就生成了語料庫中的每個單詞的數據,也就是生成所有可能的X和Y對。 下面是我們如何在代碼中生成查找表: def generateTable(data,k=4):T = {}for i in range(len(data)-k):X = data[i:i+k]Y = data[i+k]#print('X %s and Y %s '%(X,Y))if T.get(X) is None:T[X] = {}T[X][Y] = 1else:if T[X].get(Y) is None:T[X][Y] = 1else:T[X][Y] += 1return TT = generateTable('hello hello helli')print(T)#{'llo ': {'h': 2}, 'ello': {' ': 2}, 'o he': {'l': 2}, 'lo h': {'e': 2}, 'hell': {'i': 1, 'o': 2}, ' hel': {'l': 2}}代碼的簡單解釋: 在第3行,創(chuàng)建了一個字典,它將存儲X及其對應的Y和頻率值。第9行到第17行,檢查X和Y的出現情況,如果查找字典中已經有X和Y對,那么只需將其增加1。 2、將頻率轉換為概率 一旦我們有了這個表和出現的次數,就可以得到在給定x出現之后出現Y的概率。公式是: ![]() 例如如果X = the, Y = n,我們的公式是這樣的: 當X =the時Y = n的頻率:2,表中總頻率:8,因此:P = 2/8= 0.125= 12.5% 以下是我們如何應用這個公式將查找表轉換為馬爾科夫鏈可用的概率: def convertFreqIntoProb(T): for kx in T.keys():s = float(sum(T[kx].values()))for k in T[kx].keys():T[kx][k] = T[kx][k]/sreturn TT = convertFreqIntoProb(T)print(T)#{'llo ': {'h': 1.0}, 'ello': {' ': 1.0}, 'o he': {'l': 1.0}, 'lo h': {'e': 1.0}, 'hell': {'i': 0.3333333333333333, 'o': 0.6666666666666666}, ' hel': {'l': 1.0}}簡單解釋: 把一個特定鍵的頻率值加起來,然后把這個鍵的每個頻率值除以這個加起來的值,就得到了概率。 3、加載數據集 接下來將加載真正的訓練語料庫??梢允褂萌魏蜗胍拈L文本(.txt)文檔。 為了簡單起見將使用一個政治演講來提供足夠的詞匯來教授我們的模型。 text_path = 'train_corpus.txt'def load_text(filename):with open(filename,encoding='utf8') as f:return f.read().lower()text = load_text(text_path)print('Loaded the dataset.')這個數據集可以為我們這個樣例的項目提供足夠的事件,從而做出合理準確的預測。與所有機器學習一樣,更大的訓練語料庫將產生更準確的預測。 4、建立馬爾可夫鏈 讓我們構建馬爾可夫鏈,并將概率與每個字符聯系起來。這里將使用在第1步和第2步中創(chuàng)建的generateTable()和convertFreqIntoProb()函數來構建馬爾可夫模型。 def MarkovChain(text,k=4):T = generateTable(text,k)T = convertFreqIntoProb(T)return Tmodel = MarkovChain(text) 第1行,創(chuàng)建了一個方法來生成馬爾可夫模型。該方法接受文本語料庫和K值,K值是告訴馬爾可夫模型考慮K個字符并預測下一個字符的值。第2行,通過向方法generateTable()提供文本語料庫和K來生成查找表,該方法是我們在上一節(jié)中創(chuàng)建的。第3行,使用convertFreqIntoProb()方法將頻率轉換為概率值,該方法也是我們在上一課中創(chuàng)建的。 5、文本采樣 創(chuàng)建一個抽樣函數,它使用未完成的單詞(ctx)、第4步中的馬爾可夫鏈模型(模型)和用于形成單詞基的字符數量(k)。 我們將使用這個函數對傳遞的上下文進行采樣,并返回下一個可能的字符,并判斷它是正確的字符的概率。 import numpy as npdef sample_next(ctx,model,k):ctx = ctx[-k:]if model.get(ctx) is None:return ' 'possible_Chars = list(model[ctx].keys())possible_values = list(model[ctx].values())print(possible_Chars)print(possible_values)return np.random.choice(possible_Chars,p=possible_values)sample_next('commo',model,4)#['n']#[1.0]代碼解釋: 函數sample_next接受三個參數:ctx、model和k的值。 ctx是用來生成一些新文本的文本。但是這里只有ctx中的最后K個字符會被模型用來預測序列中的下一個字符。 在第 9 行和第 10 行,打印了可能的字符及其概率值,因為這些字符也存在于我們的模型中。我們得到下一個預測字符為n,其概率為1.0。因為 commo 這個詞在生成下一個字符后更可能是更常見的 在第12行,我們根據上面討論的概率值返回一個字符。 6、生成文本 最后結合上述所有函數來生成一些文本。 def generateText(starting_sent,k=4,maxLen=1000):sentence = starting_sentctx = starting_sent[-k:]for ix in range(maxLen):next_prediction = sample_next(ctx,model,k)sentence += next_predictionctx = sentence[-k:]return sentenceprint('Function Created Successfully!')text = generateText('dear',k=4,maxLen=2000)print(text)結果如下:
上面的函數接受三個參數:生成文本的起始詞、K的值以及需要文本的最大字符長度。運行代碼將得到一個以“dear”開頭的2000個字符的文本。 雖然這段講話可能沒有太多意義,但這些詞都是完整的,通常模仿了單詞中熟悉的模式。 接下來要學什么這是一個簡單的文本生成項目。通過這個項目可以了解自然語言處理和馬爾可夫鏈實際工作模式,可以在繼續(xù)您的深度學習之旅時使用。 本文只是為了介紹馬爾可夫鏈來進行的實驗項目,因為它不會再實際應用中起到任何的作用,如果你想獲得更好的文本生成效果,那么請學習GPT-3這樣的工具,因為:別問,問就是GPT-3 |
|
|