python新闻标题分类_机器学习也会“标题党”?这个算法能根据标题判断新闻类别...
全文共3624字,預計學習時長19分鐘
圖源:unsplash
語言處理中的大多數分類情況是通過監督式機器學習完成的,在該過程中,我們將與某種正確輸出相關聯的輸入觀測數據集稱作監督信號。任何分類算法的目的都是學習如何將一個新的觀測值映射到正確輸入中。
分類算法的任務是獲取一組輸入x和一組輸出類別Y,并返回預測類別y ∈(屬于) Y。在文本分類中,輸入x通常用字母d表示,代表“documents”(文檔),輸出Y通常用字母c表示,代表“classes”(類),這種表達方式沿用至今。文檔中的單詞通常被稱為“features”(特征)。
用于構建分類器的算法有許多種,但本文討論的是樸素貝葉斯算法。同時,依據不同的特征和類別,這種算法也有很多變式。其中,符合分類目的的變式為多項式型。
樸素貝葉斯法是一種基于概率的分類器,能夠得出觀察結果在類別中出現的概率。也就是說,我們會用公式計算c類別每項特征的出現頻率(這個我后面馬上會講到),最后選擇最高概率項,并由此得出類別。
初始公式為:
先驗概率P(c)的計算方式為,在所有訓練數據文檔中,c類文檔所占的百分比。
其中Nc為數據中c類文檔總數,而Ndoc為文檔總數。
由于文檔d表示為一組特征(單詞)w,因此類別中每個單詞的初始似然函數公式為:
這表示,可能性等于c類中給定單詞w-i的總數和c類中所有w單詞的總數間的分數值。
然而,該方法存在一個缺陷。如果計算一個單詞的出現概率,該單詞在詞匯表V中,但不在特定類別中,則該對的概率將為0。但由于我們將所有特征似然相乘,零概率將導致整個類別的概率也為零。
對此,我們需要添加一種平滑技術。平滑技術在語言處理算法中十分受歡迎。無需投入過多,使用拉普拉斯發明的一項技術(Laplace),它可以在計算中添加+1。公式最終將變為這樣:
其中,V是單詞類型的集合。單詞類型為文檔中出現的唯一單詞的列表。
此外,為避免下溢出并提升速度,語言處理計算在logspace函數中完成。樸素貝葉斯算法與此同理。因此,初始公式變為:
Python中多項式樸素貝葉斯算法的本機實踐
作為一種流行的分類算法,很多軟件包都可為樸素貝葉斯算法提供支持。我們將完全使用本機實現方式達到目的。輸入新聞標題,看看樸素貝葉斯算法是如何預測新聞類別的?
圖源:unsplash
前提
在Python3.x環境中開發腳本。利用Numpy包進行數組操作,并使用Pandas來管理數據。數據的使用將在“與數據打交道”部分中進行解釋。
訓練
訓練/建立/擬合機器學習模型意味著使用某個數據集來生成信息,然后使用這些信息進行預測。依據目標,訓練方法旨在執行機器算法,該算法可能簡單、可能復雜。在我們的事例中,該方法將執行上述公式,并生成用于預測的必要數據,例如概率、似然和詞匯表。
訓練將在fit()函數中被完成。在fit函數方法中,假設文檔和類別在兩個單獨的矢量中給出,并通過索引維持聯系。在該方法中,也能生成詞匯表。
建立詞匯表
在我們的算法中,需要兩種詞匯表。其一是所有唯一單詞類型的列表,稱作整體詞匯表;另一個是特定類別詞匯表,包含一個詞典中各類的文檔詞匯。
生成各詞匯表的執行方法為:
defbuildGlobalVocab(self):
vocab = []
for doc in self.docs:
vocab.extend(self.cleanDoc(doc))
return np.unique(vocab)
defbuildClassVocab(self, _cls):
curr_word_list = []
for idx, doc inenumerate(self.docs):
if self.classes[idx] == _cls:
curr_word_list.extend(self.cleanDoc(doc))
if _cls notinself.class_vocab:
self.class_vocab[_cls]=curr_word_list
else:
self.class_vocab[_cls].append(curr_word_list)
在這些方法中,我們使用了一種自定義方法cleanDoc,來處理各個文檔。目前,在語言處理算法中,清理方法可能包括刪除 the和a這樣的停止詞,這是很常見的。但在這里,刪除停止詞并不能提升性能,我們唯一要做的清理是刪除文檔標點、將字母小寫并用空格分隔開。
@staticmethod
defcleanDoc(doc):
return re.sub(r'[^a-z\d ]', '', doc.lower()).split(' ')
在使用fit函數方法的過程中,我們從類別表中獲得唯一項目的列表。然后迭代該列表,并為每個唯一類別生成logprior,構建類詞匯表,針對在整體詞匯表中的單詞,只需檢查當前類別和詞匯表中的計數器即可。在單詞迭代內部,我們解決了單詞-類別對的對數似然函數值。
我們將logprior、類別詞匯表和對數似然函數值之類的信息保存在字典中。為獲取單詞計數,使用Counter計數器collection模塊。
完整fit()函數方法如下:
deffit(self, x, y):
self.docs = x
self.classes = y
num_doc =len(self.docs)
uniq_cls = np.unique(self.classes)
self.vocab = self.buildGlobalVocab()
vocab_cnt =len(self.vocab)
for _cls in uniq_cls:
cls_docs_num = self.countCls(_cls)
self.logprior[_cls] = np.log(cls_docs_num/num_doc)
self.buildClassVocab(_cls)
class_vocab_counter =Counter(self.class_vocab[_cls])
class_vocab_cnt =len(self.class_vocab[_cls])
for word in self.vocab:
w_cnt =class_vocab_counter[word]
self.loglikelihood[word, _cls] = np.log((w_cnt +1)/(class_vocab_cnt+ vocab_cnt))
測試
測試/預測方法包含一種可以評估我們訓練出的模型的算法。
本例中,對于測試文檔中每個唯一類別和單詞,我們都尋找此類配對的先前概率,并將其添加到該類別概率的總和中,該總和與其所屬類別的logprior值一起被初始化。最終,從所有總和中得到最大值,然后將其縮小至一類。
我們已將該邏輯與預測方法進行了適配。
defpredict(self,test_docs):
output = []
for doc in test_docs:
uniq_cls = np.unique(self.classes)
sum =dict()
for _cls in uniq_cls:
sum[_cls] =self.logprior[_cls]
for word in self.cleanDoc(doc):
if word in self.vocab:
try:
sum[_cls] +=self.loglikelihood[word, _cls]
except:
print(sum, _cls)
result = np.argmax(list(sum.values()))
output.append(uniq_cls[result])
return output
與數據打交道
發現(和生成)一個用于數據分析的良好數據集本身就是一門學科。且數據集可能會不平均,可能擁有過多或過少數據。你可能過擬合或欠擬合數據,但本文我們不會對數據進行預處理。
圖源:unsplash
為預測新聞類別,我們將使用新聞聚合器數據集,該數據集由加利福尼亞大學爾灣分校(UCI)(自2014年3月10日到8月10日)開發,涵蓋約40萬行分為幾個專欄的新聞,包括標題和類別。
新聞類型主要有“商業”、“科技”、“娛樂”、“健康”四類,分別標記為b、t、 e、 m。
使用Pandas讀取數據,并把數據集劃分為訓練數據和測試數據。我們還將自定義電子閱讀器方法,來接受有關即將讀取的數據大小和拆分率的參數。
defreadFile(self, size =70000, testSize =0.3):
lines = pd.read_csv("data/news_aggregator.csv", nrows = size);
x = lines.TITLE
y = lines.CATEGORY
skip =round(size * (1- testSize))
x_train, y_train, x_test, y_test = x[:skip],y[:skip], x[skip:size], y[skip:size]
print('Train data: ', len(x_train), 'Testing data: ', len(x_test), 'Total: ', len(x))
return x_train, y_train,x_test, y_test
使用上述所有方法
將上述所有方法一起使用,獲取數據、訓練分類器并使用測試數據對分類器進行測試。最后,檢測分類準確率得分。
defmain(self):
x_train, y_train, x_test, y_test = self.readFile(size =50000, testSize=0.3)
nb =MultinominalNB()
nb.fit(x_train, y_train)
predictions = nb.predict(x_test)
print('Accuracy: ', self.accuracy(predictions,y_test))
訓練結果
在該模型中,我們訓練了35000個文檔,測試了15000個其他文檔,達到了82.9%的分類準確率得分,這非常好。
為避免每次預測時都訓練模型,可以對生成的數據進行加工。輔助方法為:
defsaveModel(self):
try:
f =open("models/classifier", "wb")
pickle.dump([self.logprior,self.vocab, self.loglikelihood, self.classes], f)
f.close()
except:
print('Error savingthe model')
@staticmethod
defreadModel():
try:
f =open("models/classifier", "rb")
model = pickle.load(f)
f.close()
return model
except:
print('Error readingthe model')
因而完整的fit函數和預測方法變為:
deffit(self, x, y,save =False):
self.docs = x
self.classes = y
num_doc =len(self.docs)
uniq_cls = np.unique(self.classes)
self.vocab = self.buildGlobalVocab()
vocab_cnt =len(self.vocab)
t =time()
for _cls in uniq_cls:
cls_docs_num = self.countCls(_cls)
self.logprior[_cls] = np.log(cls_docs_num/num_doc)
self.buildClassVocab(_cls)
class_vocab_counter =Counter(self.class_vocab[_cls])
class_vocab_cnt =len(self.class_vocab[_cls])
for word in self.vocab:
w_cnt =class_vocab_counter[word]
self.loglikelihood[word, _cls] = np.log((w_cnt +1)/(class_vocab_cnt+ vocab_cnt))
if save:
self.saveModel()
print('Trainingfinished at {} mins.'.format(round((time() - t) /60, 2)))
defpredict(self,test_docs,cached =False):
output = []
ifnot cached:
logprior = self.logprior
vocab = self.vocab
loglikelihood = self.loglikelihood
classes = self.classes
else:
logprior, vocab, loglikelihood, classes = self.readModel()
for doc in test_docs:
uniq_cls = np.unique(classes)
sum =dict()
for _cls in uniq_cls:
sum[_cls] = logprior[_cls]
for word in self.cleanDoc(doc):
if word in vocab:
try:
sum[_cls] +=loglikelihood[word, _cls]
except:
print(sum, _cls)
result = np.argmax(list(sum.values()))
output.append(uniq_cls[result])
return output
且執行變為:
defmain(self):
x_train, y_train, x_test, y_test = self.readFile(size =50000, testSize=0.3)
nb =MultinominalNB()
"""
Run the code below the first time you runthe script
nb.fit(x_train,y_train, save = True)
"""
predictions = nb.predict(['Google launchesa new app.'], cached =True)
print(predictions)
這樣就建立了一個能夠預測新聞標題類別的模型。
替代法
圖源:unsplash
前文也提到了,樸素貝葉斯不少軟件包的支持。其中最常見的一個軟件包便是Sklearn。它支持所有類型的樸素貝葉斯分類算法。處理多項式算法時,Sklearn用作為數據編碼器的CountVectorizer轉換輸入形式,從而縮短訓練和測試時間。
然而,使用與之前相同的訓練和測試數據,其準確性僅比本機實現算法略高,為83.4%。
用Sklearn樸素貝葉斯分類器訓練和測試的結果。
看來樸素貝葉斯算法的眼光相當“毒辣”,預測新聞的準確性還是很不錯的。
留言點贊關注
我們一起分享AI學習與發展的干貨
如轉載,請后臺留言,遵守轉載規范
總結
以上是生活随笔為你收集整理的python新闻标题分类_机器学习也会“标题党”?这个算法能根据标题判断新闻类别...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Odoo看板视图
- 下一篇: 股指跨期套利基础学习