一、賽題決議
【阿里云天池演算法挑戰賽】零基礎入門NLP - 新聞文本分類-Day1-賽題理解_202xxx的博客-CSDN博客
二、資料讀取與資料分析
【阿里云天池演算法挑戰賽】零基礎入門NLP - 新聞文本分類-Day2-資料讀取與資料分析_202xxx的博客-CSDN博客
三、機器學習提取文本特征方法
3.1 One-hot
將每一個單詞使用一個離散的向量表示,具體將每個字/詞編碼一個索引,然后根據索引進行賦值,
One-hot表示方法的例子如下:
句子1:我 愛 北 京 天 安 門
句子2:我 喜 歡 上 海
首先對所有句子的字進行索引,即將每個字確定一個編號:
{
'我': 1, '愛': 2, '北': 3, '京': 4, '天': 5,
'安': 6, '門': 7, '喜': 8, '歡': 9, '上': 10, '海': 11
}
在這里共包括11個字,因此每個字可以轉換為一個11維度稀疏向量:
我:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
愛:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
...
海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
3.2 Bag of Words
Bag of Words(詞袋表示),也稱為Count Vectors,每個檔案的字/詞可以使用其出現次數來進行表示,
句子1:我 愛 北 京 天 安 門
句子2:我 喜 歡 上 海
直接統計每個字出現的次數,并進行賦值:
句子1:我 愛 北 京 天 安 門
轉換為 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 歡 上 海
轉換為 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
在sklearn中可以直接CountVectorizer來實作這一步驟:
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()
3.3 N-gram
N-gram與Count Vectors類似,不過加入了相鄰單詞組合成為新的單詞,并進行計數,
如果N取值為2,則句子1和句子2就變為:
句子1:我愛 愛北 北京 京天 天安 安門
句子2:我喜 喜歡 歡上 上海
3.4 TF-IDF
TF-IDF 分數由兩部分組成:第一部分是詞語頻率(Term Frequency),第二部分是逆檔案頻率(Inverse Document Frequency),其中計算語料庫中檔案總數除以含有該詞語的檔案數量,然后再取對數就是逆檔案頻率,
TF(t)= 該詞語在當前檔案出現的次數 / 當前檔案中詞語的總數
IDF(t)= log_e(檔案總數 / 出現該詞語的檔案總數)
四、基于機器學習的文本分類
使用詞代模型構造3000維特征,用嶺回歸對特征進行分類,用f1_score計算分類的評分
# Count Vectors + RidgeClassifier
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
import os
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=15000)
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.74
使用TF-IDF構造3000維特征,ngram_range=(1,3)進行分詞,用嶺回歸對特征進行分類,用f1_score計算分類的評分
# TF-IDF + RidgeClassifier
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=15000)
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.87
四、作業思路
1. 嘗試改變TF-IDF的引數,并驗證精度
答:通過調整詞代模型生成的訓練集維度觀察最后打分的變化情況以及耗時
# 作業1 調整TFIDF向量特征
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
import time
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=15000)
for max_features in [30, 300, 3000, 30000]:
start = time.time()
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=max_features)
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(max_features, f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
print("耗時:", str(time.time()-start))
可以看出,特征隨著維度的增加,結果的精度會越高,但是耗時也會隨之增加,
30 0.2189540444476877
耗時: 33.73664093017578
300 0.6718911185943914
耗時: 33.80941700935364
3000 0.8721598830546126
耗時: 35.318426847457886
30000 0.8961640609998208
耗時: 38.89586901664734
通過控制特征為度為30000,調整n-gram分詞引數,觀察模型評分的變化情況
# 作業1 調整TFIDF的ngram_range引數
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
import time
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=15000)
for ngram_range in [1, 2, 3, 4]:
start = time.time()
tfidf = TfidfVectorizer(ngram_range=(1,ngram_range), max_features=30000)
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(ngram_range, f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
print("耗時:", str(time.time()-start))
可以看出隨著n-gram最大值的增加,評分逐步增加,但是耗時暴漲,并且到3之后隨著n-gram最大值的增加評分變化不大,
1 0.8603325900148268
耗時: 5.810247182846069
2 0.8955102528662253
耗時: 16.896533012390137
3 0.8961640609998208
耗時: 38.89586901664734
4 0.8957080944137796
耗時: 304.3434760570526
2. 嘗試使用其他機器學習模型,完成訓練和驗證
答:用隨機森林模型替換嶺回歸模型進行訓練
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score
import time
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=15000)
start = time.time()
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=30000)
train_test = tfidf.fit_transform(train_df['text'])
#隨機森林
clf = RandomForestClassifier(random_state = 100,
min_samples_split = 3,
n_estimators = 100,
oob_score = True,
verbose = 2,
class_weight = "balanced",
n_jobs = 10)#行程數
clf.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = clf.predict(train_test[10000:])
print"f1_score:", f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
print("耗時:", str(time.time()-start))
隨機森林耗時38秒,f1評分為0.849
f1_score: 0.8495898388161273
耗時: 38.263571977615356
切換所有資料進行訓練
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score
import time
data_dir = os.path.abspath("./").replace("competition", "competition_data")
train_df = pd.read_csv(os.path.join(data_dir, 'data/train_set.csv'), sep='\t', nrows=None)
start = time.time()
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=30000)
train_test = tfidf.fit_transform(train_df['text'])
#隨機森林
clf = RandomForestClassifier(random_state = 100,
min_samples_split = 3,
n_estimators = 100,
oob_score = True,
verbose = 2,
class_weight = "balanced",
n_jobs = 10)#行程數
clf.fit(train_test[:-10000], train_df['label'].values[:-10000])
val_pred = clf.predict(train_test[-10000:])
print("f1_score:", f1_score(train_df['label'].values[-10000:], val_pred, average='macro'))
print("耗時:", str(time.time()-start))
隨機森林耗時1947.7秒,f1評分為0.9098
f1_score: 0.8495898388161273
耗時: 38.263571977615356
五、總結

模型優化建議,通過調整特征提取模型TF-IDF的引數,或者替換更好的特征提取模型,或者替換更好的分類器,并對分類器的引數進行調優,
六、Reference
tianchi_competition/零基礎入門NLP - 新聞文本分類 at main · RxxxxR/tianchi_competition · GitHub
Datawhale零基礎入門NLP賽事 - Task2 資料讀取與資料分析-天池實驗室-實時在線的資料分析協作工具,享受免費計算資源
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/345626.html
標籤:AI
