機(jī)器學(xué)習(xí)——自然語言處理(NLP)一
前言
自然語言處理(Natural Language Processing,NLP)是一門研究如何使計算機(jī)能夠理解和處理人類語言的學(xué)科,其中有許多常用的算法和技術(shù),本文則主要介紹比較基礎(chǔ)的TF-IDF算法和樸素貝葉斯算法。
一、TF-IDF算法
1.1. 原理
一種用于評估一個詞語對于一個文件集或一個語料庫的重要程度的統(tǒng)計方法。 可以參與文本分類、文本相似度計算、信息檢索等任務(wù)。(TF-IDF算法本身并不是一個分類算法,只是用于將文本數(shù)據(jù)轉(zhuǎn)換為可供分類算法使用的特征表示)
它通過計算一個詞語在文檔中的出現(xiàn)頻率(TF)和在整個語料庫中的出現(xiàn)頻率的比值,來衡量該詞語對于文檔的重要性。
-
TF(詞頻)表示一個詞語在文檔中出現(xiàn)的頻率,計算公式為:
TF = (詞語在文檔中出現(xiàn)的次數(shù)) / (文檔中的總詞語數(shù))。 -
IDF(逆文檔頻率)表示一個詞語在整個語料庫中的出現(xiàn)頻率的倒數(shù),計算公式為:
IDF = log((語料庫中的文檔總數(shù)) / (包含該詞語的文檔數(shù) + 1))。 -
TF-IDF的計算公式為:
TF-IDF = TF * IDF。
1.2. 算法步驟:
1.2.1. 文本預(yù)處理
文本預(yù)處理: 在應(yīng)用TF-IDF算法之前,需要對文本進(jìn)行預(yù)處理,包括去除標(biāo)點(diǎn)符號、停用詞等。
-
刪除停用詞:去除常見的無實(shí)際含義的詞語,它們通常無法告訴你關(guān)于文檔的內(nèi)容,如“a”、“is”、“the”等。
-
去除標(biāo)點(diǎn)符號:使用正則表達(dá)式或字符串操作函數(shù)去除文本中的標(biāo)點(diǎn)符號
-
詞干提取/還原:如一個單詞有多種形式(過去時、現(xiàn)代時等等),可以合并為一種形式
-
分詞:將文本分割成單個的詞語或標(biāo)記,可以使用空格或其他分隔符進(jìn)行分詞
…
1.2.2. 構(gòu)建詞袋模型
構(gòu)建詞袋模型:將預(yù)處理后的文本轉(zhuǎn)換為詞袋(BOW)的表現(xiàn)形式,即向量化文本,創(chuàng)建詞條-文檔矩陣,矩陣的每一列表示一個詞語,而每個文檔對應(yīng)于每一行,兩者的交點(diǎn)是該詞語在文本中出現(xiàn)的次數(shù)。
1.2.3. 計算TF-IDF值
計算TF-IDF值:將TF和IDF相乘,得到每個詞語的TF-IDF值。TF-IDF值越大,表示詞語在文本中越重要
1.2.4. 特征選擇
根據(jù)設(shè)定的閾值或其他規(guī)則,選擇具有較高TF-IDF值的詞語作為特征詞,
因?yàn)橛蓆f-idf值的計算公式可知,為了獲得較高的tf-idf值,一個詞條需要在較少的文檔中出現(xiàn)較高的次數(shù),這樣我們就可認(rèn)為文檔由具有較高tf-idf值的詞條所表示
1.3. 代碼實(shí)現(xiàn)
數(shù)據(jù)集為sklearn庫中的新聞組數(shù)據(jù)集(fetch_20newsgroups)
1.3.1. TF-IDF
TfidfVectorizer(ngram_range= , stop_words= , min_df= )
- ngram_range:表示文檔是如何被分詞的。以文檔" This is stone" 為例,ngram_range=(1, 3)表示提取單個詞、相鄰兩個詞、相鄰三個詞的組合,即 ”This"、“This is”、“This is stone"、“is”、“is stone” 和 “stone”
這樣進(jìn)行分詞,能將觀察單詞與單詞之間的關(guān)系的窗口擴(kuò)大,幫助算法更好理解文本。
-
stop_words :刪除指定的停用詞,例如 stop_words=“english”,表示刪除所有的英語停用詞
-
mid_df:這里會刪除所有文檔頻率小于指定數(shù)的單詞,可移除那些極其罕見的詞條來減小矩陣規(guī)模。
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score
import pandas as pd
# 加載新聞組數(shù)據(jù)集
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
data_train = newsgroups_train.data
target_train = newsgroups_train.target
data_test = newsgroups_test.data
target_test = newsgroups_test.target
# df_train = pd.DataFrame(data= np.c_[newsgroups_train.data,newsgroups_train.target],columns= ["text","target"])
# df_train.to_csv("newsgroups_train.csv")
# df_test = pd.DataFrame(data= np.c_[newsgroups_test.data,newsgroups_test.target],columns= ["text","target"])
# df_test.to_csv("newsgroups_test.csv")
# 創(chuàng)建TF-IDF向量化器
vectorizer = TfidfVectorizer(stop_words="english", min_df=3)
# 對訓(xùn)練集和測試集進(jìn)行向量化
data_train_tfidf = vectorizer.fit_transform(data_train)
data_test_tfidf = vectorizer.transform(data_test)
#整合為數(shù)據(jù)框形式
df = pd.DataFrame(
data= data_train_tfidf.toarray(),
columns = vectorizer.get_feature_names()
)
1.3.2 計數(shù)器向量化文本
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(stop_words="english",min_df= 3)
data_train_tfidf = vectorizer.fit_transform(data_train)
data_test_tfidf = vectorizer.transform(data_test)
1.3.3. 兩者的區(qū)別
-
計數(shù)器向量化文本只考慮了詞頻,而TF-IDF算法向量化文本同時考慮了詞頻和詞的重要性,給常見詞較低的權(quán)重,給罕見詞較高的權(quán)重。
-
計數(shù)器向量化文本沒有對常見詞進(jìn)行特殊處理,而TF-IDF算法向量化文本通過逆文檔頻率來減小常見詞的權(quán)重,提高罕見詞的權(quán)重。
-
總之,計數(shù)器向量化文本適用于簡單的文本分類任務(wù),TF-IDF算法適用于更復(fù)雜的文本處理任務(wù)。
1.3.4. 繪制簡單的詞云圖(額外)
#簡單的對一個文檔進(jìn)行詞云圖繪制
data_train_ciyu =[data_train[0]]
#print(data_train_ciyu)
vectorizer = TfidfVectorizer( stop_words="english")
tfidf_matrix = vectorizer.fit_transform(data_train_ciyu)
# 獲取詞條列表
feature_names = vectorizer.get_feature_names()
# 獲取每個詞條的TF-IDF值
tfidf_values = tfidf_matrix.toarray()[0]
df = pd.DataFrame(
data= tfidf_matrix.toarray(),
columns = vectorizer.get_feature_names()
)
print(df)
15 60s 70s ... wam wondering years
0 0.104828 0.104828 0.104828 ... 0.209657 0.104828 0.104828
# 創(chuàng)建一個字典,將詞條和對應(yīng)的TF-IDF值存儲起來
word_tfidf_dict = dict(zip(feature_names, tfidf_values))
# 按TF-IDF值降序排序
sorted_words = sorted(word_tfidf_dict.items(), key=lambda x: x[1], reverse=True)
#print(sorted_words)
from wordcloud import WordCloud
# 獲取文檔頻率最高的詞條
top_words = dict(sorted_words[:10])
print(top_words)
{'car': 0.5241424183609592, 'edu': 0.20965696734438366, 'lerxst': 0.20965696734438366, 'umd': 0.20965696734438366, 'wam': 0.20965696734438366, '15': 0.10482848367219183, '60s': 0.10482848367219183, '70s': 0.10482848367219183, 'addition': 0.10482848367219183, 'body': 0.10482848367219183}
# 創(chuàng)建詞云對象
wordcloud = WordCloud()
# 生成詞云圖
wordcloud.generate_from_frequencies(top_words)
# 繪制詞云圖
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
從該圖中可看出car這個單詞出現(xiàn)頻率最高,故可推斷該文檔應(yīng)該與汽車有關(guān),(事實(shí)上確實(shí)是講述汽車的新聞),原文檔如下圖所示:
這個詞云圖的繪制還是相當(dāng)粗糙的,一般情況下是要根據(jù)自己的要求來對文檔中單詞的讀取進(jìn)行一定的選擇(比如,去掉無實(shí)際意義的數(shù)字,字符等等),還有許多別的什么操作等等。這樣才能繪制滿足自己要求的精致的詞云圖。
二、樸素貝葉斯算法
2.1. 原理
樸素貝葉斯算法是基于貝葉斯定理與特征條件獨(dú)立假設(shè)的分類方法(“樸素”,指的就是特征條件獨(dú)立),
對于給出的待分類項(xiàng),求解在此項(xiàng)出現(xiàn)的條件下各個類別出現(xiàn)的概率(即求條件概率),然后綜合這些概率對其所在的特征向量做出分類預(yù)測(哪個最大,就認(rèn)為此待分類項(xiàng)屬于哪個類別)
貝葉斯定理是概率論中的重要定理,用于計算在已知一些先驗(yàn)信息的情況下,根據(jù)新的觀測數(shù)據(jù)來更新對事件的概率估計。
對于事件 A 和事件 B,貝葉斯定理可以表示為:
P(A|B) = (P(B|A) * P(A)) / P(B)
表示事件B已經(jīng)發(fā)生的前提下,事件A發(fā)生的概率(即事件B發(fā)生下事件A的條件概率)
2.2. 算法步驟
當(dāng)觀察到輸入樣本X時,其屬于類別C的概率值為:P(C|X) = P(X|C) * P( C ) / P(X)
樸素貝葉斯算法的核心思想是基于貝葉斯定理來計算后驗(yàn)概率P(C|X),并選擇具有最大后驗(yàn)概率的類別作為預(yù)測結(jié)果。對于給定的輸入樣本X,樸素貝葉斯算法通過以下步驟進(jìn)行分類:
-
建立訓(xùn)練集:從已標(biāo)記的數(shù)據(jù)集中,統(tǒng)計每個類別的先驗(yàn)概率 P( C)(類別 A中的樣本數(shù)除以總樣本數(shù))以及每個特征在各個類別條件下的條件概率 P(X|C)(表示在類別 C下特征 X 出現(xiàn)的概率)。
-
特征條件獨(dú)立性假設(shè):樸素貝葉斯算法假設(shè)所有特征之間相互獨(dú)立。即對于給定的類別 C 和特征集合 X={x?, x?, …, x?},條件概率可以表示為 P(X|C) = P(x?|C) * P(x?|C) * … * P(x?|C)。
-
計算后驗(yàn)概率:對于每個類別 C,計算后驗(yàn)概率 P(C|X) = P(X|C) * P(C ),其中 P(X|C) 表示在類別 C 下特征 X 出現(xiàn)的概率,P(C ) 是先驗(yàn)概率。
-
預(yù)測分類:選擇具有最大后驗(yàn)概率的類別作為預(yù)測結(jié)果。即找到 max P(C|X)。
2.3. 代碼實(shí)現(xiàn)
alpha是一個平滑參數(shù),越小越易過擬合,反之則欠擬合
from sklearn.naive_bayes import MultinomialNB
model = MultinomialNB(alpha= 0.001)
model.fit(data_train_tfidf,target_train)
print(model.score(data_test_tfidf,target_test))
print(model.score(data_train_tfidf,target_train))
#結(jié)果:
0.8199681359532661
0.9953155382711685
#使用網(wǎng)格搜索
import numpy as np
from sklearn.model_selection import GridSearchCV
params = {
"alpha": np.linspace(0.00001,0.01,100),
"fit_prior": [True,False],
}
grid_search = GridSearchCV(MultinomialNB(),param_grid= params,cv= 5)
grid_search.fit(data_train_tfidf,target_train)
best_NB = grid_search.best_estimator_
print(best_NB)
print(grid_search.best_score_)
print(grid_search.best_params_)
best_NB.fit(data_train_tfidf,target_train)
# 在測試集上進(jìn)行預(yù)測
y_pred = best_NB.predict(data_test_tfidf)
# 計算準(zhǔn)確率
accuracy = accuracy_score(target_test, y_pred)
print('Accuracy:', accuracy)
#結(jié)果:
MultinomialNB(alpha=0.007880909090909091)
0.9106417269627534
{'alpha': 0.007880909090909091, 'fit_prior': True}
Accuracy: 0.830323951141795
#模型的評價
#使用classification_report函數(shù),查看預(yù)測結(jié)果的準(zhǔn)確性
from sklearn.metrics import classification_report
model = best_NB
model.fit(data_train_tfidf, target_train)
pred = model.predict(data_test_tfidf)
#print(pred)
import pprint
pprint.pprint(classification_report(y_true=target_test,y_pred= pred,target_names=newsgroups_test.target_names))
#使用混淆矩陣,觀察每種類別被錯誤分類的情況
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(target_test,pred)
#print(cm)
#混淆矩陣的可視化
import seaborn as sns
sns.heatmap(cm, annot=True, fmt='d', cmap='Reds')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Confusion Matrix')
plt.show()
sns.heatmap(cm, annot=False, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Confusion Matrix')
plt.show()
#cmap參數(shù):
"""
'Blues': 藍(lán)色調(diào)的漸變色圖譜
'Greens': 綠色調(diào)的漸變色圖譜
'Reds': 紅色調(diào)的漸變色圖譜
'Oranges': 橙色調(diào)的漸變色圖譜
'coolwarm': 冷暖色調(diào)的漸變色圖譜
'viridis': 從藍(lán)色到黃色的漸變色圖譜
'hot': 火熱色調(diào)的漸變色圖譜
"""
#整合起來
li = list(zip(data_test,pred))
#print(len(li))
#print(len(data_test))
result = pd.DataFrame(data= np.c_[ [ li[x][0] for x in range(len(li))],[li[x][1] for x in range(len(li))]], columns= ["data_test","predict"])
#print(result.head())
result.to_csv("result.csv",index= False)
由此通過樸素貝葉斯算法得到了一個簡單的分類模型,我們可以取任意的文本來測試一下分類情況:
print(model)
MultinomialNB(alpha=0.007880909090909091)
documents = ["This new department would become the world's primary research center for computer graphics",
"The three astronauts of Shenzhou ten return safe space congratulations "
]
documents_vector = vectorizer.transform(documents)
model.fit(data_train_tfidf,target_train)
pred = model.predict(documents_vector)
print(pred)
[ 1 14]
#print(list(zip(documents,pred)))
這兩個文本分別是介紹計算機(jī)圖形學(xué)和航天的內(nèi)容,分別是1、14,成功分類。(當(dāng)然由于模型比較簡單的問題,可能會出現(xiàn)許多分類錯誤問題)
這時,我們就需要不斷對算法進(jìn)行優(yōu)化和改善了。
或者運(yùn)用其它分類算法(總之就是為了得到最佳的算法模型)
三、其它分類算法
3.1. 支持向量機(jī)
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
"""
params = {
"kernel": ["rbf","sigmoid","poly","linear"],
"C": np.arange(1,6),
"gamma": np.arange(0,0.5,0.001),
"degree":np.arange(1,5)
}
# 創(chuàng)建SVM分類器并進(jìn)行訓(xùn)練
svm = SVC()
grid_searchcv = GridSearchCV(svm,param_grid= params,cv= 5)
grid_searchcv.fit(data_train_tfidf, target_train)
best_svc = grid_searchcv.best_estimator_
print(best_svc)
best_svc.fit(data_train_tfidf,target_train)
# 在測試集上進(jìn)行預(yù)測
y_pred = best_svc.predict(data_test_tfidf)
print(best_svc.score(target_test,y_pred))
# 計算準(zhǔn)確率
accuracy = accuracy_score(target_test, y_pred)
print('Accuracy:', accuracy)
"""
#因?yàn)榈却龝r間太過漫長,就不進(jìn)行網(wǎng)格搜索了,直接創(chuàng)建簡單的模型
best_svc= SVC()
best_svc.fit(data_train_tfidf,target_train)
y_pred = best_svc.predict(data_test_tfidf)
# 計算準(zhǔn)確率
accuracy = accuracy_score(target_test, y_pred)
print('Accuracy:', accuracy)
Accuracy: 0.8251460435475305
3.2. 隨機(jī)森林
from sklearn.ensemble import RandomForestClassifier
# 創(chuàng)建隨機(jī)森林分類器并進(jìn)行訓(xùn)練
"""
param_grids = {
"criterion": ["gini","entropy"],
"max_depth":np.arange(1,10),
"min_samples_leaf":np.arange(1,10),
"max_features": np.arange(1,3)
}
rf = RandomForestClassifier()
grid_search = GridSearchCV(rf,param_grid=param_grids,n_jobs= 4,scoring="accuracy",cv=5)
grid_search.fit(data_train_tfidf,target_train)
best_rf = grid_search.best_estimator_
print(grid_search.best_score_)
print(best_rf)
best_rf.fit(data_train_tfidf, target_train)
# 在測試集上進(jìn)行預(yù)測
y_pred = best_rf.predict(data_test_tfidf)
# 計算準(zhǔn)確率
accuracy = accuracy_score(target_test, y_pred)
print('Accuracy:', accuracy)
"""
best_rf = RandomForestClassifier()
best_rf.fit(data_train_tfidf, target_train)
# 在測試集上進(jìn)行預(yù)測
y_pred = best_rf.predict(data_test_tfidf)
# 計算準(zhǔn)確率
accuracy = accuracy_score(target_test, y_pred)
print('Accuracy:', accuracy)
Accuracy: 0.7716409984067977
四、比較與選擇
在進(jìn)行文檔分類時,樸素貝葉斯算法、支持向量機(jī)(SVM)和隨機(jī)森林算法是常用的分類算法之一
- 樸素貝葉斯算法(Naive Bayes):
優(yōu)點(diǎn):簡單、易于實(shí)現(xiàn),對于高維數(shù)據(jù)和大規(guī)模數(shù)據(jù)集有較好的性能,適用于文本分類等任務(wù)。
缺點(diǎn):樸素貝葉斯算法假設(shè)特征之間相互獨(dú)立,這在實(shí)際情況下可能不成立,故在特征相關(guān)性較強(qiáng)的情況下,可能表現(xiàn)不佳。
- 支持向量機(jī):
優(yōu)點(diǎn):SVM在處理高維數(shù)據(jù)和小樣本數(shù)據(jù)時表現(xiàn)較好,具有較強(qiáng)的泛化能力,并且可以處理非線性問題。
缺點(diǎn):SVM對于大規(guī)模數(shù)據(jù)集的訓(xùn)練時間較長,且對于噪聲和缺失數(shù)據(jù)敏感,需要進(jìn)行特征縮放和調(diào)參。
- 隨機(jī)森林算法:
優(yōu)點(diǎn):通過多個決策樹的投票結(jié)果來進(jìn)行分類,具有較好的準(zhǔn)確性和魯棒性,對于高維數(shù)據(jù)和缺失數(shù)據(jù)有較好的處理能力。
缺點(diǎn):在處理大規(guī)模數(shù)據(jù)集時需要較多的計算資源,且對于高度相關(guān)的特征可能表現(xiàn)不佳。
在訓(xùn)練時間和計算資源有限的情況下,樸素貝葉斯算法是一個較快速的選擇,若充足,可考慮另外兩種算法(只能說相比之下,這兩種算法太慢了)
如果特征之間相互獨(dú)立或相關(guān)性較低,樸素貝葉斯算法可能表現(xiàn)較好
如果數(shù)據(jù)集規(guī)模較大或特征維度較低,可以考慮使用支持向量機(jī)或隨機(jī)森林算法,反之特征維度較高則用NB算法
如果對準(zhǔn)確性和魯棒性有較高要求,可以考慮使用隨機(jī)森林算法
總結(jié)
本文介紹了自然語言處理中的簡單算法,文本向量化的算法:TF-IDF算法以及計數(shù)器向量化;文本分類算法:樸素貝葉斯算法以及其它分類算法。最后對這些分類算法進(jìn)行了一定的比較。
流光容易把人拋, 紅了櫻桃 ,綠了芭蕉。文章來源:http://www.zghlxwxcb.cn/news/detail-701875.html
–2023-9-7 筑基篇文章來源地址http://www.zghlxwxcb.cn/news/detail-701875.html
到了這里,關(guān)于機(jī)器學(xué)習(xí)——自然語言處理(NLP)一的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!