Datawhale-零基础入门NLP-新闻文本分类Task03
文本是不定長度的,文本表示成計算的能夠運算的數字或向量的方法稱為詞嵌入(Word Embedding)。詞嵌入是將不定長的文本轉換成定長的空間中。為了解決將原始文本轉成固定長度的特征向量問題,scikit-learn提供了以下方法:
-
令牌化(tokenizing):對每個可能的詞令牌分成字符串并賦予整數形的id,通過空格和標點符號作為令牌分隔符。
-
統計(counting)每個詞令牌在文檔中的出現次數。
-
標準化(normalizing)是減少重要的詞令牌的出現次數的權重。
使用傳統的機器學習方法進行文本分類,思路有Count Vectors + 分類算法(LR/SVM/XGBoost等等),TF-IDF+分類算法(LR/SVM/XGBoost等等)
1?Count Vectors + 分類算法
1.1?Count Vectors
類countVectorizer在但單類中實現了tokenization(詞語切分)和occurence counting(出現頻數統計):
函數為:
參數詳解:
input:string {‘filename’, ‘file’, ‘content’}, default=’content’
定義輸入數據的格式,如果是filename,讀取的文件名列表,以獲取要分析的原始內容;如果是‘file’,序列項必須有一個' read '方法(類文件的對象),該方法被調用來獲取內存中的字節;如果是‘content’,輸入應該是字符串或字節類型的序列項。
encoding:string,default='utf-8'
進行分析時,使用該類型進行解碼。
lowercase:bool,default=True
在進行tokenizing之前,將字符轉成小寫
ngram_range:tuple (min_n, max_n), default=(1, 1)
要提取的不同單詞n-gram或字符n-gram的n值范圍的上下邊界。
analyzer:string, {‘word’, ‘char’, ‘char_wb’} or callable, default=’word’
分析是由單詞n-gram還是字符n-gram組成,‘char_wb’是一個混合狀態。
max_df:float in range [0.0, 1.0] or int, default=1.0
當構建詞匯表時,忽略文檔頻率嚴格高于給定閾值的術語(特定于語料庫的停止詞)。如果為float,該參數表示文檔的比例,整數絕對計數。如果詞匯不是none,則忽略此參數。
min_df:float in range [0.0, 1.0] or int, default=1
構建詞匯表時,忽略文檔頻率嚴格低于給定閾值的術語。這個值在文獻中也被稱為截止值。如果為float,該參數表示文檔的比例,整數絕對計數。如果詞匯不是none,則忽略此參數。
例子:
from sklearn.feature_extraction.text import CountVectorizercorpus = ['This is the first document.','This document is the second document.','And this is the third one.','Is this the first document?']vectorizer = CountVectorizer() X = vectorizer.fit_transform(corpus) print(vectorizer.get_feature_names())print(X.toarray())vectorizer2 = CountVectorizer(analyzer='word', ngram_range=(2, 2)) X2 = vectorizer2.fit_transform(corpus) print(vectorizer2.get_feature_names())print(X2.toarray())?
1.2 分類算法
這里選用了線性模型里邊的嶺回歸做分類,還可以選用SVM,LR,XGBoost等分類算法模型,后邊用網格搜索(GridSearchCV)進行參數遍歷的會用到。
綜合分析:
import pandas as pd import xgboost as xgb import lightgbm as lgb import catboost as cat from sklearn.feature_extraction.text import CountVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC from sklearn.metrics import f1_score from sklearn.pipeline import Pipelinetrain_df = pd.read_csv('data/data45216/train_set.csv',sep='\t',nrows=15000) print(train_df.shape)vectorizer = CountVectorizer(max_features=3000) train_test = vectorizer.fit_transform(train_df['text'])clf = RidgeClassifier() clf.fit(train_test[:10000],train_df['label'].values[:10000]) val_pred = clf.predict(train_test[10000:]) print(f1_score(train_df['label'].values[10000:],val_pred,average='macro'))輸出結果為:0.65441877581244
2 TF-IDF+分類算法
2.1 TF-IDF
TF-IDF是詞頻-逆文檔頻率,含義是如果某個詞或短語在一篇文章中出現的頻率TF高,并且在其他文章中很少出現,則認為這個詞或短語具有很好的類別區分能力,適合用來分類。TF-IDF的假設是,高頻率詞應該具有高權重,除非它也是高文檔頻率。逆文檔怕頻率是使用詞條的文檔頻率來抵消該詞的詞頻對權重的影響,而得到一個較低的權重。
詞頻(Term Frequency,TF)是指某一個給定的詞語在該文件中出現的頻率。這個數字是對詞數(Term Count)的歸一化,以防止它偏向長的文件,對于在某個特定文件中的詞語來說,它的重要性可表示為:
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
其中,分子是該詞在文件中的出現次數,而分母是在文件中所有字詞出現的次數之和。
逆向文件頻率(Inverse Document Frequency,IDF)是一個詞語普遍重要性的度量。某一特定詞語的IDF,可以由總文件數除以包含該詞語之文件的數目,再將得到的商取對數得到:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
其中,:語料庫中的文件總數;j:包含詞語的文件數目,如果該詞語不在語料庫則導致分母為0,因此,常用作為分母,然后在計算TF和IDF的乘積。
函數為:
?
參數詳解:
input:string {‘filename’, ‘file’, ‘content’}, default=’content’
定義輸入數據的格式,如果是filename,讀取的文件名列表,以獲取要分析的原始內容;如果是‘file’,序列項必須有一個' read '方法(類文件的對象),該方法被調用來獲取內存中的字節;如果是‘content’,輸入應該是字符串或字節類型的序列項。
encoding:string,default='utf-8'
進行分析時,使用該類型進行解碼。
lowercase:bool,default=True
在進行tokenizing之前,將字符轉成小寫
ngram_range:tuple (min_n, max_n), default=(1, 1)
要提取的不同單詞n-gram或字符n-gram的n值范圍的上下邊界。
analyzer:string, {‘word’, ‘char’, ‘char_wb’} or callable, default=’word’
分析是由單詞n-gram還是字符n-gram組成,‘char_wb’是一個混合狀態。
max_df:float in range [0.0, 1.0] or int, default=1.0
當構建詞匯表時,忽略文檔頻率嚴格高于給定閾值的術語(特定于語料庫的停止詞)。如果為float,該參數表示文檔的比例,整數絕對計數。如果詞匯不是none,則忽略此參數。
min_df:float in range [0.0, 1.0] or int, default=1
構建詞匯表時,忽略文檔頻率嚴格低于給定閾值的術語。這個值在文獻中也被稱為截止值。如果為float,該參數表示文檔的比例,整數絕對計數。如果詞匯不是none,則忽略此參數。
norm:{‘l1’, ‘l2’}, default=’l2’
正則化,‘l2’是平方值,‘l1’是絕對值
use_idf:bool, default=True
啟用反向文檔頻率重新加權
smooth_idf:bool, default=True
通過在文檔頻率上增加一個來平滑idf權重,就好像一個額外的文檔恰好包含集合中的每個術語一次。防止零除法
sublinear_tf:bool, default=False
應用 sublinear tf scaling, i.e. 取代 tf 在with 1 + log(tf).
例子:
from sklearn.feature_extraction.text import TfidfVectorizercorpus = ['This is the first document.','This document is the second document.','And this is the third one.','Is this the first document?']vectorizer = TfidfVectorizer() x = vectorizer.fit_transform(corpus) print(vectorizer.get_feature_names)2.2 分類算法
這里選用了線性模型里邊的嶺回歸做分類,還可以選用SVM,LR,XGBoost等分類算法模型,后邊用網格搜索(GridSearchCV)進行參數遍歷的會用到。
綜合分析:
tfidf = TfidfVectorizer(ngram_range=(1,3),max_features=3000) train_test = tfidf.fit_transform(train_df['text'])clf = RidgeClassifier() clf.fit(train_test[:10000],train_df['label'].values[:10000]) val_pred = clf.predict(train_test[10000:]) print(f1_score(train_df['label'].values[10000:],val_pred,average='macro'))輸出結果為:0.8719098297954606
本章作業:
調整參數可以考慮用網格搜索進行超參數遍歷,分別對文本處理方式和分類算法進行遍歷。超參數是不直接在估計器內學習的參數,它們作為估計器類中構造函數的參數進行傳遞,搜索超參數空間以便能獲得最好的“交叉驗證”,搜索包括:
- 估計器(回歸器或分類器)
- 參數空間
- 搜尋或采樣候選的方法
- 交叉驗證方案
- 計分函數
scikit-learn包中提供了兩種采樣搜索候選的通用方法,GridSearchCV考慮了所有參數組合,RandomizedSearchCV可以從具有指定分布的參數空間中抽取給定數量的候選,這里選用GridSearchCV舉例:
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC from sklearn.metrics import f1_score from sklearn.pipeline import Pipeline#遍歷TF-IDF的參數 pipeline = Pipeline([('tfidf', TfidfVectorizer()),('clf', SGDClassifier()), ])parameters = {#'tfidf__max_df': (0.5, 0.75, 1.0),'tfidf__max_features': (None, 5000, 10000, 50000),'tfidf__ngram_range': ((1, 1), (1, 2),(1,3)), # unigrams or bigrams'tfidf__norm': ('l1', 'l2'),'clf__max_iter': (20,),'clf__alpha': (0.00001, 0.000001),'clf__penalty': ('l2', 'elasticnet'),# 'clf__max_iter': (10, 50, 80), }grid_search = GridSearchCV(pipeline, parameters, verbose=1) print("Performing grid search...") print("pipeline:", [name for name, _ in pipeline.steps]) print("parameters:") pprint(parameters) grid_search.fit(train_df['text'].tolist()[:10000],train_df['label'].values[:10000])print("Best score: %0.3f" % grid_search.best_score_) print("Best parameters set:") best_parameters = grid_search.best_estimator_.get_params() for param_name in sorted(parameters.keys()):print("\t%s: %r" % (param_name, best_parameters[param_name]))遍歷分類器:
import pandas as pd import xgboost as xgb import lightgbm as lgb import catboost as cat from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC from sklearn.metrics import f1_score from sklearn.pipeline import Pipelinetfidf = TfidfVectorizer(ngram_range=(1,3),max_features=3000) train_test = tfidf.fit_transform(train_df['text'])#定義多個分類函數 classifiers = [('xgb',xgb.XGBClassifier(),{'max_depth': [5, 10, 15, 20, 25],'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],'n_estimators': [50, 100, 200, 300, 500], }),('lgb',lgb.LGBMClassifier(),{'max_depth': [5, 10, 15, 20, 25],'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],'n_estimators': [50, 100, 200, 300, 500], }),('cat',cat.CatBoostClassifier(),{'max_depth': [5, 10, 15, 20, 25],'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],'n_estimators': [50, 100, 200, 300, 500], }),('svc',SVC(),{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],'C': [1, 10, 100, 1000]})]for name,clf,params in classifiers:grid_search = GridSearchCV(clf,params,n_jobs=1,verbose=1)grid_search.fit(train_test[:10000],train_df['label'].values[:10000])?
思考:我用TF-IDF+分類器的驗證結果為0.87,提交結果為0.1773,用了Fasttext的驗證結果為0.82,提交結果為0.833,產生的原因是什么?
總結
以上是生活随笔為你收集整理的Datawhale-零基础入门NLP-新闻文本分类Task03的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转载]Coursera课程批量下载(保
- 下一篇: mysql双重分组没有值也要显示_mys