参考:https://mp.weixin.qq.com/s/6vkz18Xw4USZ3fldd_wf5g
1、数据集下载地址
https://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531810/train_set.csv.zip
https://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531810/test_a.csv.zip
数据集来自天池比赛,训练集20w条样本,测试集A包括5w条样本。而且文本按照字符级别进行了匿名处理,处理后的数据为下:
这里就直接拆分训练集为训练集和测试集了。
在数据集中标签的对应的关系如下:
{'科技': 0, '股票': 1, '体育': 2, '娱乐': 3, '时政': 4, '社会': 5, '教育': 6, '财经': 7, '家居': 8, '游戏': 9, '房产': 10, '时尚': 11, '彩票': 12, '星座': 13}
评价指标:
2、导入相应包
代码语言:javascript复制import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
import matplotlib.pyplot as plt
from sklearn.metrics import f1_score
3、读取数据
代码语言:javascript复制train_path="/content/drive/My Drive/nlpdata/news/train_set.csv"
train_df = pd.read_csv(train_path, sep='t', nrows=15000)
train_df['text']
代码语言:javascript复制train_df['label']
4、进行文本分类
(1)n-gram 岭分类
代码语言:javascript复制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 岭分类
代码语言:javascript复制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.8719372173702
5、探究参数对模型的影响
取大小为5000的样本,保持其他参数不变,令阿尔法从0.15增加至1.5,画出F1关于阿尔法的图像
(1)针对于岭分类而言:阿尔法对模型的影响
代码语言:javascript复制sample = train_df[0:5000]
n = int(2*len(sample)/3)
tfidf = TfidfVectorizer(ngram_range=(2,3), max_features=2500)
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
f1 = []
for i in range(10):
clf = RidgeClassifier(alpha = 0.15*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
plt.plot([0.15*(i 1) for i in range(10)], f1)
plt.xlabel('alpha')
plt.ylabel('f1_score')
plt.show()
可以看出阿尔法不宜取的过大,也不宜过小。越小模型的拟合能力越强,泛化能力越弱,越大模型的拟合能力越差,泛化能力越强。
(2)max_features对模型的影响
分别取max_features的值为1000、2000、3000、4000,研究max_features对模型精度的影响
代码语言:javascript复制f1 = []
features = [1000,2000,3000,4000]
for i in range(4):
tfidf = TfidfVectorizer(ngram_range=(2,3), max_features=features[i])
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
clf = RidgeClassifier(alpha = 0.1*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
plt.plot(features, f1)
plt.xlabel('max_features')
plt.ylabel('f1_score')
plt.show()
可以看出max_features越大模型的精度越高,但是当max_features超过某个数之后,再增加max_features的值对模型精度的影响就不是很显著了。
(3) ngram_range对模型的影响
n-gram提取词语字符数的下边界和上边界,考虑到中文的用词习惯,ngram_range可以在(1,4)之间选取
代码语言:javascript复制f1 = []
for i in range(4):
tfidf = TfidfVectorizer(ngram_range=(1,1), max_features=2000)
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
clf = RidgeClassifier(alpha = 0.1*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
tfidf = TfidfVectorizer(ngram_range=(2,2), max_features=2000)
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
clf = RidgeClassifier(alpha = 0.1*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
tfidf = TfidfVectorizer(ngram_range=(3,3), max_features=2000)
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
clf = RidgeClassifier(alpha = 0.1*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=2000)
train_test = tfidf.fit_transform(sample['text'])
train_x = train_test[:n]
train_y = sample['label'].values[:n]
test_x = train_test[n:]
test_y = sample['label'].values[n:]
clf = RidgeClassifier(alpha = 0.1*(i 1), solver = 'sag')
clf.fit(train_x, train_y)
val_pred = clf.predict(test_x)
f1.append(f1_score(test_y, val_pred, average='macro'))
[0.7931919639413474, 0.7831242477075827, 0.6293265527038611, 0.8436709720083034, 0.8127288721306228, 0.791639726421815, 0.6425340629702662, 0.8512559206701422, 0.82151852494927, 0.7978544191527702, 0.6500441251723578, 0.8516726763849712, 0. 8275245575862662, 0.7963717190315031, 0.6577157272412916, 0.8485051384495732]
6、其它分类模型
均使用TF-IDF作为预处理方式。
(1)逻辑回归
代码语言:javascript复制from sklearn import linear_model
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=5000)
train_test = tfidf.fit_transform(train_df['text']) # 词向量 15000*max_features
reg = linear_model.LogisticRegression(penalty='l2', C=1.0,solver='liblinear')
reg.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = reg.predict(train_test[10000:])
print('预测结果中各类新闻数目')
print(pd.Series(val_pred).value_counts())
print('n F1 score为')
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
预测结果中各类新闻数 0 1032 1 1029 2 782 3 588 4 375 5 316 6 224 8 166 7 161 9 123 10 109 11 60 12 23 13 12 dtype: int64
F1 score为 0.8464704900433653
(2)SGDClassifier
代码语言:javascript复制tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=5000)
train_test = tfidf.fit_transform(train_df['text']) # 词向量 15000*max_features
reg = linear_model.SGDClassifier(loss="log", penalty='l2', alpha=0.0001,l1_ratio=0.15)
reg.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = reg.predict(train_test[10000:])
print('预测结果中各类新闻数目')
print(pd.Series(val_pred).value_counts())
print('n F1 score为')
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
(3)SVM
代码语言:javascript复制from sklearn import svm
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=5000)
train_test = tfidf.fit_transform(train_df['text']) # 词向量 15000*max_features
reg = svm.SVC(C=1.0, kernel='linear', degree=3, gamma='auto',decision_function_shape='ovr')
reg.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = reg.predict(train_test[10000:])
print('预测结果中各类新闻数目')
print(pd.Series(val_pred).value_counts())
print('n F1 score为')
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))