最近在学习sklearn,动手实现了一个根据名称分辨性别的模型。
感觉还是蛮有趣的。
这个是参考的链接(英文),Working with Text Data
仿照这个教程上的步骤一步步建立自己的模型。
Version1
1.准备训练数据
将csv中的record读入,使用pandas。为了在文本文档上执行机器学习,我们首先需要将文本内容转换为数字特征向量。
可以将名称分为单词袋(bag of words),如:
为训练集中任何文档中出现的每个词分配一个固定的整数id(例如,通过从单词到整数索引建立词典)。
对于每个文档#i,计算每个单词的出现次数w并将其存储为特征的值, 其中,单词在字典中的索引X[i, j]#jjw
单词袋通常使用高位稀疏矩阵(high-dimensional sparse matrix)表示。
在我自己的例子中,我将读入的数据分为特征集X和结果集Y。
# step1: prepare data, establish an iterable object,to use in CountVectorizer
# word_list, to be used as X
# gender_list, to be used as Y
word_list = []
gender_list = []
file = pd.read_csv('your_filename.csv')
df = pd.DataFrame(file)
for i in range(len(df)):
document = df[i:i + 1]
gender = document['Gender'][i]
if gender == 'men':
title = document['Title'][i]
if pd.isnull(title) == False:
word_list.append(title)
gender_list.append(0)
elif gender == 'women':
title = document['Title'][i]
if pd.isnull(title) == False:
word_list.append(title)
gender_list.append(1)
准备好两个大的数据集之后,使用train_test_split
将两个数据集划分为四个,分别为训练数据集,训练结果集,测试数据集和测试结果集。因为是supervised learning, 即有监督的学习模型,所以需要训练结果集,而两个测试数据集则用来测试模型的准确度。
这里有比较详细的train_test_split
介绍的链接,我的另一篇blog。sklearn.train_test_split
# split data set into train set and test set using train_test_split
# always use 70% for train data, 30% for test data
X_train, X_test, Y_train, Y_test = train_test_split(word_list, gender_list,
test_size=0.3,
random_state=42)
2. 使用sklearn进行文本标记
文本预处理、分割和停止词的过滤,包含在一个高级组件中,使用该组件能够建立特征的字典,并将文本转化为特征向量。
CountVectorizer
支持单词或连续字符的计数。一旦拟合,向量化器就构建了一个特征索引字典。
# step2: tokenize text
count_vect = CountVectorizer()
X_train_sparse_matrix = count_vect.fit_transform(X_train)
X_test_sparse_matrix = count_vect.transform(X_test)
dense_numpy_matrix = X_train_sparse_matrix.todense()
3.统计词频
统计词的个数尽管很有用,但存在一些问题,比如,即使谈论的主题是相同的,长文本也比短文本的平均计数更高。因此需要转化为频率。
我们首先使用fit
方法来将我们的估计量与数据拟合,其次将transform
方法转换为tf-idf
表示。 通过跳过冗余处理,可以将这两个步骤组合在一起,以更快地达到相同的最终结果,即使用fit_transform
。
# step3: get frequencies (features)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_sparse_matrix)
X_test_tfidf = tfidf_transformer.fit_transform(X_test_sparse_matrix
4. 培训分类器
这里先使用的是朴素贝叶斯
分类器。
# step4: training a classifier (after having features now)
clf = MultinomialNB().fit(X_train_tfidf, Y_train)
后续也有改进为其他方法,如SVM。
5.预测和评估
predicted = clf.predict(X_test_tfidf)
print(predicted)
accruacy = np.mean(predicted == Y_test)
print(accruacy)
最终的运行结果为:
[0 0 1 ... 1 1 1]
4621
0.9091105821250811
Version2
1. 使用Pipline简化过程
sklearn
提供了Pipline
来简化上述过程。
为了使vectorizer => transformer =>classifier
更易于使用,scikit-learn提供了一个Pipeline类似复合分类器的类。
# step2: using pipline as a compound classifier
text_clf = Pipeline([('vect',CountVectorizer()),
('tfidf',TfidfTransformer()),
('clf',SGDClassifier(loss='hinge',penalty='l2',
alpha=1e-3,random_state=42,
max_iter=5,tol=None)),
])
2.使用SVM模型
SVM即支持向量机模型,使用该模型,速度虽然比朴素贝叶斯慢一点,但是准确率更高。
上面的SDGClassifier
。
继续学习中…
备注:使用的训练数据集全部为英文材料。