Datawhale零基础入门NLP-Task01-day 3
引用学习资料:https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.12.6406111aIKCSLV&postId=118254
TF-IDF + RidgeClassifier
一. 基础知识:
文本表示方法 Part1
在机器学习算法的训练过程中,假设给定N个样本,每个样本有M个特征,这样组成了N×M的样本矩阵,然后完成算法的训练和预测。同样的在计算机视觉中可以将图片的像素看作特征,每张图片看作hight×width×3的特征图,一个三维的矩阵来进入计算机进行计算。
但是在自然语言领域,上述方法却不可行:文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。
One-hot
这里的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]
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()
N-gram
N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。
如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海
TF-IDF
TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
Tfidf:
https://blog.csdn.net/zrc199021/article/details/53728499
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)
二. 具体步骤
1. 事例
# 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
train_df = pd.read_csv('../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 + RidgeClassifier
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
train_df = pd.read_csv('../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
2. 实操
a. 读取,合并数据:
concat、append、merge、join、combine_first
Pandas DataFrame数据的增、删、改、查
concat:
import pandas as pd
# 两个feture之间是 \t,在不确定的时候,.head()看下或者 直接输出 df[199999:] 查看
train_df=pd.read_csv('../NLP/train_set.csv', sep='\t') #Datafram格式
test_df=pd.read_csv('../NLP/test_a.csv')
df=pd.concat([train_df,test_df])
print(type(df))
df[199999:] #index 信息分明
label | text | |
---|---|---|
199999 | 3.0 | 4350 3878 3268 1699 6909 5505 2376 2465 6088 2… |
0 | NaN | 5399 3117 1070 4321 4568 2621 5466 3772 4516 2… |
1 | NaN | 2491 4109 1757 7539 648 3695 3038 4490 23 7019… |
2 | NaN | 2673 5076 6835 2835 5948 5677 3247 4124 2465 5… |
3 | NaN | 4562 4893 2210 4761 3659 1324 2595 5949 4583 2… |
… | … | … |
49995 | NaN | 3725 4498 2282 1647 6293 4245 4498 3615 1141 2… |
49996 | NaN | 4811 465 3800 1394 3038 2376 2327 5165 3070 57… |
49997 | NaN | 5338 1952 3117 4109 299 6656 6654 3792 6831 21… |
49998 | NaN | 893 3469 5775 584 2490 4223 6569 6663 2124 168… |
49999 | NaN | 2400 4409 4412 2210 5122 4464 7186 2465 1327 9… |
50001 rows × 2 columns
train_df.head()
label | text | |
---|---|---|
0 | 2 | 2967 6758 339 2021 1854 3731 4109 3792 4149 15… |
1 | 11 | 4464 486 6352 5619 2465 4802 1452 3137 5778 54… |
2 | 3 | 7346 4068 5074 3747 5681 6093 1777 2226 7354 6… |
3 | 2 | 7159 948 4866 2109 5520 2490 211 3956 5520 549… |
4 | 3 | 3646 3055 3055 2490 4659 6065 3370 5814 2465 5… |
test_df.head()
text | |
---|---|
0 | 5399 3117 1070 4321 4568 2621 5466 3772 4516 2… |
1 | 2491 4109 1757 7539 648 3695 3038 4490 23 7019… |
2 | 2673 5076 6835 2835 5948 5677 3247 4124 2465 5… |
3 | 4562 4893 2210 4761 3659 1324 2595 5949 4583 2… |
4 | 4269 7134 2614 1724 4464 1324 3370 3370 2106 2… |
append:
df_text = train_df['text'].append(test_df['text']).reset_index(drop=True)
#如果不加reset 会有冲突
df_text[199999:]
199999 4350 3878 3268 1699 6909 5505 2376 2465 6088 2...
200000 5399 3117 1070 4321 4568 2621 5466 3772 4516 2...
200001 2491 4109 1757 7539 648 3695 3038 4490 23 7019...
200002 2673 5076 6835 2835 5948 5677 3247 4124 2465 5...
200003 4562 4893 2210 4761 3659 1324 2595 5949 4583 2...
...
249995 3725 4498 2282 1647 6293 4245 4498 3615 1141 2...
249996 4811 465 3800 1394 3038 2376 2327 5165 3070 57...
249997 5338 1952 3117 4109 299 6656 6654 3792 6831 21...
249998 893 3469 5775 584 2490 4223 6569 6663 2124 168...
249999 2400 4409 4412 2210 5122 4464 7186 2465 1327 9...
Name: text, Length: 50001, dtype: object
df_text.head()
0 2967 6758 339 2021 1854 3731 4109 3792 4149 15...
1 4464 486 6352 5619 2465 4802 1452 3137 5778 54...
2 7346 4068 5074 3747 5681 6093 1777 2226 7354 6...
3 7159 948 4866 2109 5520 2490 211 3956 5520 549...
4 3646 3055 3055 2490 4659 6065 3370 5814 2465 5...
Name: text, dtype: object
b. TF-IDF
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(ngram_range=(1,2), max_features=10000)
tfidf_vector = tfidf.fit_transform(df_text) #df_text['text']contact 可以用
tfidf_vector
<250000x10000 sparse matrix of type '<class 'numpy.float64'>'
with 137212981 stored elements in Compressed Sparse Row format>
c. TF-IDF和ngram进行gridsearch
d. 分类器
RidgeClassifier(岭回归分类器)
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
from sklearn.model_selection import train_test_split
# X 的输入为训练集的tfidf 的特征值,对应每篇文的每个词的ifidf值,输出y 为训练集的label
X_train,X_test, y_train, y_test = train_test_split(tfidf_train, train_df['label'], test_size = 0.2, random_state= 3077066)
clf = RidgeClassifier()
clf.fit(X_train, y_train.values) # X_train; .values
val_pred = clf.predict(X_test)# model.predict(test_set)
print(f1_score(y_test.values, val_pred, average='macro'))
0.9177555876149023
测试并预测结果:
pred_clf = clf.predict(tfidf_test)
print(pred_clf)
pred_clf1 = pd.DataFrame({'label':pred_clf}) # https://blog.csdn.net/weixin_39223665/article/details/79935467
pred_clf1.to_csv('../NLP/pred_clf.csv',index = False)
检查数据:
xx = pd.read_csv('../NLP/pred_clf.csv')
xx.info
LinearSVC
from sklearn.svm import LinearSVC, SVC
lsvc=LinearSVC()
# fit https://zhuanlan.zhihu.com/p/42297868
# https://zhuanlan.zhihu.com/p/29957294
lsvc.fit(X_train, y_train.values)
pred_LSVC=lsvc.predict(X_test)
print(f1_score(y_test.values, pred_LSVC, average='macro'))
0.9305798921632542
pred_LSVC1=lsvc.predict(tfidf_test)
print(pred_clf)
# Pandas中把dataframe和np.array的相互转换
# https://blog.csdn.net/weixin_39223665/article/details/79935467
pred_res_LSVC1 = pd.DataFrame({'label':pred_LSVC1})
#加个标题,见pands的添加删除
pred_res_LSVC1.to_csv('../NLP/pred_LSVC.csv',index = False)
[1 2 8 ... 1 3 1]