导入python包
import pandas as pd
from pandas import Series, DataFrame
导入非名人数据
notCelebrity=[]
for each in 'ABCDEFGHIJKLMNOPQRSTUVWYZ':
dataCSV = pd.read_csv('baidubaike_noCelebrity/{}_notCelebrity.csv'.format(each), sep='|', header=None)
notCelebrity.extend(dataCSV[4])
data_1 = {'content':notCelebrity}
dataFrame_1=DataFrame(data_1)
dataFrame_1['values']='1'
导入名人数据
Celebrity=[]
dataCSV = pd.read_csv('baidubaike_celebrity.csv', sep='|')
for each in dataCSV['Celebrity'].values:
if each==each:
Celebrity.append(each)
data_2 = {'content':Celebrity}
dataFrame_2=DataFrame(data_2)
dataFrame_2['values']='0'
合并名人数据与非名人数据
dataFrame = dataFrame_1.append(dataFrame_2)
dataFrame=dataFrame.dropna(axis=0,how='any')
进行分词
import jieba
dataFrame['分词']=dataFrame['content'].apply(lambda x:' '.join(jieba.cut(x)))
X=dataFrame['分词']
y=dataFrame['values']
k折交叉切分
from sklearn.model_selection import StratifiedKFold,KFold
from sklearn import preprocessing
from sklearn.feature_extraction.text import TfidfTransformer,CountVectorizer
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.naive_bayes import GaussianNB,MultinomialNB
from sklearn.metrics import accuracy_score
skf = StratifiedKFold(n_splits=10, random_state=1, shuffle=False)
for train_index, test_index in skf.split(X, y):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
#提取文本特征
vectorizer = CountVectorizer()
X_train_termcounts = vectorizer.fit_transform(X_train.astype('U'))
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_termcounts)
#获取词袋中所有文本的关键字
feature_name = vectorizer.get_feature_names()
#建立朴素贝叶斯分类器进行训练
classifier = MultinomialNB().fit(X_train_tfidf, y_train.astype('str'))
#模型测试
X_input_termcounts = vectorizer.transform(X_test.astype('str'))
X_input_tfidf = tfidf_transformer.transform(X_input_termcounts)
#模型预测
predicted_categories = classifier.predict(X_input_tfidf)
print(accuracy_score(y_test.astype('str'),predicted_categories))
生成的预测结果:
0.9666283084004603
0.9700115340253749
0.9619377162629758
0.9676674364896074
0.9688221709006929
0.9711316397228638
0.9688221709006929
0.9653579676674365
0.9745958429561201
0.964203233256351
我遇到的错误
把自己在这个过程中遇到的问题做一个记录
- TypeError: a bytes-like object is required, not ‘str’
- AttributeError: ‘NoneType’ object has no attribute ‘get_text’
- RandomForestClassfier.fit(): ValueError: could not convert string to float
- ValueError: Expected 2D array, got 1D array instead
- TypeError: ‘<’ not supported between instances of ‘float’ and ‘str’
- Label encoding across multiple columns in scikit-learn
- ValueError: np.nan is an invalid document, expected byte or unicode string
1.TypeError: a bytes-like object is required, not ‘str’
像错误提示说的那样需要的是字节类型而不是字符串类型,需要注意一下的是bytes-like翻译为字节。
2.AttributeError: ‘NoneType’ object has no attribute ‘get_text’
空对象(空类型)没有get_text()方法,这里注意的是NoneType代表的是空None,这个在爬虫里面应该算是常见的错误了吧。
3.RandomForestClassfier.fit(): ValueError: could not convert string to float
无法见字符串转换为浮点型,在机器学习过程中遇到的一个问题,stackoverflow上提供的解决方案是LabelEncoder与OneHotEncoder,参考链接
4.ValueError: Expected 2D array, got 1D array instead
期待的是2维的排列,而得到的却是一维的,解决办法是reshape(-1,1),对于reshape()这个函数有必要了解一下,它个作用就是改变数据的排列方式。
5.TypeError: ‘<’ not supported between instances of ‘float’ and ‘str’
这是一个由于数据类型不对而引起的错误,看一下这个例子 我相信就一目了然了。我们需要用到astype(“str”)这个函数来解决问题
6.Label encoding across multiple columns in scikit-learn
在机器学习过程中把数据数字化可以解决很多不必要的麻烦,如何实现2D(2维)的数字化可以参照这个
7.ValueError: np.nan is an invalid document, expected byte or unicode string
看最后一句它期待的是byte或者unicode,显然可以用astype()解决问题。
StratifiedKFold与KFold
k折交叉验证的过程,第一步我们使用不重复抽样将原始数据随机分为k份,第二步 k-1份数据用于模型训练,剩下那一份数据用于测试模型。然后重复第二步k次,我们就得到了k个模型和他的评估结果(译者注:为了减小由于数据分割引入的误差,通常k折交叉验证要随机使用不同的划分方法重复p次,常见的有10次10折交叉验证)。
然后我们计算k折交叉验证结果的平均值作为参数/模型的性能评估。使用k折交叉验证来寻找最优参数要比holdout方法更稳定。一旦我们找到最优参数,要使用这组参数在原始数据集上训练模型作为最终的模型。
StratifiedKFold采用的是分层采样随机采样,KFold相当于StratifiedKFold的低配版只是实现了随机这一性质。
CountVectorizer()与TfidfTransformer()
1.词袋模型
这里可能需要先了解一下词袋模型(Bag of words,简称 BoW )
词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。
词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用 TF-IDF 进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习模型中计算。
词袋模型的三部曲:分词(tokenizing),统计修订词特征值(counting)与标准化(normalizing)。
词袋模型有很大的局限性,因为它仅仅考虑了词频,没有考虑上下文的关系,因此会丢失一部分文本的语义。
在词袋模型统计词频的时候,可以使用 sklearn 中的 CountVectorizer 来完成。
2.词频向量化
CountVectorizer 类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素a[i][j],它表示j词在i类文本下的词频。它通过 fit_transform 函数计算各个词语出现的次数,通过get_feature_names()可获取词袋中所有文本的关键字,通过 toarray()可看到词频矩阵的结果。
3.TF-IDF处理
F-IDF(Term Frequency–Inverse Document Frequency)是一种用于资讯检索与文本挖掘的常用加权技术。TF-IDF是一种统计方法,用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。
TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF。
(1)词频(Term Frequency,TF)指的是某一个给定的词语在该文件中出现的频率。即词w在文档d中出现的次数count(w, d)和文档d中总词数size(d)的比值。
这个数字是对词数 (term count) 的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)
(2)逆向文件频率(Inverse Document Frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。即文档总数n与词w所出现文件数docs(w, D)比值的对数。
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
4.用sklearn进行TF-IDF预处理
#提取文本特征
vectorizer = CountVectorizer()
X_train_termcounts = vectorizer.fit_transform(X_train.astype('U'))
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_termcounts)
参考文档:
https://blog.csdn.net/m0_37324740/article/details/79411651
https://ljalphabeta.gitbooks.io/python-/content/kfold.html