注:学习笔记基于文彤老师文本挖掘的系列课程

全文基于《射雕英雄传》语料库,下面是读入数据的一个基于Pandas的通用操作框架。

#准备工作,具体可参照学习笔记一,将处理的文章分章节
import pandas as pd
# 有的环境配置下read_table出错,也可用用read_csv
raw = pd.read_table("金庸-射雕英雄传txt精校版.txt",names = ['txt'],  encoding ="GBK")
# 章节判断用变量预处理
def m_head(tmpstr):return tmpstr[:1]def m_mid(tmpstr):return tmpstr.find("回 ")
#取出进行判断的变量
raw['head'] = raw.txt.apply(m_head)
raw['mid'] = raw.txt.apply(m_mid)
raw['len'] = raw.txt.apply(len)#防止特殊情况,设置长度
chapnum = 0
for i in range(len(raw)):if raw['head'][i] == "第" and raw['mid'][i] > 0 and raw['len'][i] < 30 :chapnum += 1if chapnum >= 40 and raw['txt'][i] == "附录一:成吉思汗家族" :chapnum = 0raw.loc[i, 'chap'] = chapnum
# 删除临时变量,这里必须删除,否则后续sum函数处会出错
del raw['head']
del raw['mid']
del raw['len']
rawgrp = raw.groupby('chap')
chapter = rawgrp.agg(sum) # 只有字符串列的情况下,sum函数自动转为合并字符串
chapter = chapter[chapter.index != 0]#排除前言和附录

1.文档相似度

计算两个词相似度的原理:简单的说,就是将每个词的向量在空间上进行余弦运算,当cos越接近0时候,两者越相似。

1.1词条相似度:word2vec

词袋模型不考虑词条之间的相关性,因此无法用于计算词条相似度。

分布式表达会考虑词条的上下文关联,因此能够提取出词条上下文中的相关性信息,而词条之间的相似度就可以直接利用此类信息加以计算。

目前主要使用gensim实现相应的算法。
gensim 通用格式list of list格式

gensim也提供了sklearn的API接口:sklearn_api.w2vmodel,可以在sklearn中直接使用。

1.1.1 设置word2vec模型

class gensim.models.word2vec.Word2Vec(

sentences = None : 类似list of list的格式,对于特别大的文本,尽量考虑流式处理
size = 100 : 词条向量的维度,数据量充足时,300/500的效果会更好
window = 5 : 上下文窗口大小
workers = 3 : 同时运行的线程数,多核系统可明显加速计算

其余细节参数设定:

min_count = 5 : 低频词过滤阈值,低于该词频的不纳入模型
max_vocab_size = None : 每1千万词条需要1G内存,必要时设定该参数以节约内存
sample=0.001 : 负例采样的比例设定
negative=5 : 一般为5-20,设为0时不进行负例采样
iter = 5 : 模型在语料库上的迭代次数,该参数将被取消

与神经网络模型有关的参数设定:

seed=1, alpha=0.025, min_alpha=0.0001, sg=0, hs=0

)

chapter.head()
txt
chap
1.0 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两...
2.0 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈...
3.0 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽...
4.0 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎...
5.0 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰...

生成list of list格式,注意方法,后面要用到

# 分词和预处理,生成list of list格式
import jieba
chapter['cut'] = chapter.txt.apply(jieba.lcut)
chapter.head()
txt cut
chap
1.0 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两... [第一回, , 风雪, 惊变,  ,  ,  ,  ,  ,  , 那, 说话, 人, 五...
2.0 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈... [第二回, , 江南七怪,  ,  ,  ,  , 颜烈, 跨出, 房门, ,, 过道, ...
3.0 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽... [第三回, , 黄沙, 莽莽,  ,  ,  ,  , 寺里, 僧众, 见, 焦木, 圆寂...
4.0 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎... [第四回, , 黑风双, 煞,  ,  ,  ,  , 完颜洪熙, 笑, 道, :, “,...
5.0 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰... [第五回, , 弯弓, 射雕,  ,  ,  ,  , 一行, 人下, 得, 山来, ,,...
# 初始化word2vec模型和词表
from gensim.models.word2vec import Word2Vec
n_dim = 300 # 指定向量维度,大样本量时300~500较好
w2vmodel = Word2Vec(size = n_dim, min_count = 10)
w2vmodel.build_vocab(chapter.cut) # 生成词表
w2vmodel#这是生成的模型
<gensim.models.word2vec.Word2Vec at 0x230bb928da0>

1.1.2 对word2vec模型进行训练

word2vecmodel.train(

sentences : iterable of iterables格式,对于特别大量的文本,尽量考虑流式处理
total_examples = None : 句子总数,int,可直接使用model.corpus_count指定
total_words = None : 句中词条总数,int,该参数和total_examples至少要指定一个
epochs = None : 模型迭代次数,需要指定

其他带默认值的参数设定:

start_alpha=None, end_alpha=None, word_count=0, queue_factor=2,
report_delay=1.0, compute_loss=False, callbacks=()

)

# 在评论训练集上建模(大数据集时可能会花费几分钟)
# 本例消耗内存较少,w2vmodel.corpus_count是模型可以直接返回的值
w2vmodel.train(chapter.cut, \total_examples = w2vmodel.corpus_count, epochs = 10)
(3444321, 6113050)
# 训练完毕的模型实质
print(w2vmodel.wv["郭靖"].shape)#因为前面规定了是300
w2vmodel.wv["郭靖"]
(300,)
array([-5.71486771e-01, -6.11459553e-01,  9.88356650e-01, -2.19969201e+00,-6.24286681e-02, -2.08215073e-01, -4.94846284e-01,  4.11184639e-01,3.51217866e-01, -7.16320872e-01,  2.41676435e-01, -5.17797768e-01,......           -5.74352980e-01,  3.34270656e-01, -8.82370621e-02, -2.53521979e-01,6.62185490e-01, -1.17333210e+00, -5.62149405e-01, -1.21558267e-04,-1.54235452e-01,  4.67433631e-01, -3.35694969e-01, -1.63811371e-01],dtype=float32)

w2v模型的保存和复用:
w2vmodel.save(存盘路径及文件名称)

w2vmodel.load(存盘路径及文件名称)

1.1.3 词向量间的相似度

w2vmodel.wv.most_similar(词条)

w2vmodel.wv.most_similar("郭靖",topn = 20)#又结果可以看出和黄蓉相似度最高
[('黄蓉', 0.932035505771637),('欧阳克', 0.8728183507919312),('穆念慈', 0.7740538120269775),('梅超风', 0.7715764045715332),('李萍', 0.7549037337303162),('完颜康', 0.7546292543411255),('黄药师', 0.7424267530441284),('陆冠英', 0.7395749688148499),('杨康', 0.7385720014572144),('鲁有脚', 0.7347890138626099),('周伯通', 0.7241591811180115),('裘千仞', 0.722597599029541),('欧阳锋', 0.7211623787879944),('华筝', 0.7194427847862244),('洪七公', 0.7096649408340454),('程瑶迦', 0.7055790424346924),('穆易', 0.7018767595291138),('那公子', 0.6987137198448181),('那道人', 0.6943396329879761),('一灯', 0.6929605007171631)]
# 寻找对应关系
w2vmodel.wv.most_similar(positive=['郭靖', '小红马'], \negative=['黄药师'], topn = 5)#positive negative可以省
#意思为由'郭靖'和'小红马'的关系,寻找'黄药师'的对应关系
[('奔', 0.8444687128067017),('过去', 0.7988641858100891),('晕', 0.7967531681060791),('刚', 0.7961419224739075),('几步', 0.7911766767501831)]
# 计算两个词的相似度/相关程度
print(w2vmodel.wv.similarity("郭靖", "黄蓉"))
print(w2vmodel.wv.similarity("郭靖", "杨康"))
print(w2vmodel.wv.similarity("郭靖", "杨铁心"))
0.93203545
0.73857194
0.6454911
# 寻找不合群的词
w2vmodel.wv.doesnt_match("小红马 黄药师 鲁有脚".split())
'小红马'

1.2文档相似度

1.2.1 基于词袋模型计算

1.sklearn实现

sklearn.metrics.pairwise.pairwise_distances(

X : 用于计算距离的数组

[n_samples_a, n_samples_a] if metric == 'precomputed'[n_samples_a, n_features] otherwise

Y = None : 用于计算距离的第二数组,当metric != 'precomputed’时可用

metric = ‘euclidean’ : 空间距离计算方式

scikit-learn原生支持 : ['cityblock', 'cosine', 'euclidean', 'l1', 'l2', 'manhattan'],可直接使用稀疏矩阵格式
来自scipy.spatial.distance : ['braycurtis', 'canberra', 'chebyshev', 'correlation', 'dice', 'hamming', 'jaccard','kulsinski', 'mahalanobis', 'matching', 'minkowski','rogerstanimoto', 'russellrao', 'seuclidean', 'sokalmichener','sokalsneath', 'sqeuclidean', 'yule'] 不支持稀疏矩阵格式

n_jobs = 1 : 用于计算的线程数,为-1时,所有CPU内核都用于计算

)

#得出词频矩阵
cleanchap = [ " ".join(m_cut(w)) for w in chapter.txt.iloc[:5]] from sklearn.feature_extraction.text import CountVectorizercountvec = CountVectorizer() resmtx = countvec.fit_transform(cleanchap)
resmtx
<5x11623 sparse matrix of type '<class 'numpy.int64'>'with 16884 stored elements in Compressed Sparse Row format>
from sklearn.metrics.pairwise import pairwise_distancespairwise_distances(resmtx, metric = 'cosine')#得出两两的关联度
#结果阅读竖着和横着都表示第几章,同理,对角线看一半即可
array([[0.        , 0.63104216, 0.77665559, 0.78745025, 0.82985512],[0.63104216, 0.        , 0.62572437, 0.61666388, 0.73192845],[0.77665559, 0.62572437, 0.        , 0.51645443, 0.5299046 ],[0.78745025, 0.61666388, 0.51645443, 0.        , 0.42108002],[0.82985512, 0.73192845, 0.5299046 , 0.42108002, 0.        ]])
pairwise_distances(resmtx) # 默认值为euclidean,欧式距离,得出词条的空间直线距离
array([[  0.        , 290.85391522, 312.60678176, 315.54872841,311.46267834],[290.85391522,   0.        , 266.95130642, 265.77622166,277.24898557],[312.60678176, 266.95130642,   0.        , 233.9615353 ,226.09290126],[315.54872841, 265.77622166, 233.9615353 ,   0.        ,202.57344347],[311.46267834, 277.24898557, 226.09290126, 202.57344347,0.        ]])
# 使用TF-IDF矩阵进行相似度计算
from sklearn.feature_extraction.text import TfidfTransformer
txtlist = [ " ".join(m_cut(w)) for w in chapter.txt.iloc[:5]]
vectorizer = CountVectorizer() #构造一个实例,联想C语言
X = vectorizer.fit_transform(txtlist) # 将文本中的词语转换为词频矩阵
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(X)  #基于词频矩阵X计算TF-IDF值
tfidf#结果是一个稀疏矩阵,较大,压缩存储,所以结果没有展示出来
pairwise_distances(tfidf[:5], metric = 'cosine')
array([[0.        , 0.69112864, 0.84741572, 0.85725434, 0.89178365],[0.69112864, 0.        , 0.74381846, 0.70586805, 0.81759092],[0.84741572, 0.74381846, 0.        , 0.60083695, 0.63539482],[0.85725434, 0.70586805, 0.60083695, 0.        , 0.54123168],[0.89178365, 0.81759092, 0.63539482, 0.54123168, 0.        ]])

2.gensim实现

主要是用于基于LDA计算余弦相似度
需要使用的信息:

拟合完毕的lda模型
按照拟合模型时矩阵种类转换的需检索文本
需检索的文本
建模时使用的字典
#计算相似矩阵,不过很难使用
from gensim import similarities
simmtx = similarities.MatrixSimilarity(corpus)
simmtx
<gensim.similarities.docsim.MatrixSimilarity at 0x230bb8ec550>

检索和第1章内容最相似(所属主题相同)的章节

simmtx = similarities.MatrixSimilarity(corpus) # 使用的矩阵种类需要和拟合模型时相同
simmtx
<gensim.similarities.docsim.MatrixSimilarity at 0x230bb8ec438>
simmtx.index[:2]#一列为一章节,内容为其相应词条在空间的坐标值
array([[0.00370857, 0.11125696, 0.00370857, ..., 0.        , 0.        ,0.        ],[0.        , 0.15784042, 0.        , ..., 0.        , 0.        ,0.        ]], dtype=float32)
# 使用gensim的LDA拟合结果进行演示
query = chapter.txt[1]
query_bow = dictionary.doc2bow(m_cut(query))#转化为bow向量lda_vec = ldamodel[query_bow] # 转换为lda模型下的向量
sims = simmtx[lda_vec] # 进行矩阵内向量和所提供向量的余弦相似度查询
sims = sorted(enumerate(sims), key=lambda item: -item[1])#进行排序
sims#有结果可以看出,和第一章相似度最的就是第一章
#有于数据量等问题,较好的拟合后的模型应该是接近于1的
[(38, 0.011200049),(1, 0.009635941),(26, 0.0077462136),......    (20, 0.0016734296),(19, 0.0012708347),(13, 0.0012344222)]

1.2.2 doc2vec(应多使用词袋模型的方式)

doc2vec建议多大量文本时候使用

word2vec用来计算词条相似度非常合适。

较短的文档如果希望计算文本相似度,可以将各自内部的word2vec向量分别进行平均,用平均后的向量作为文本向量,从而用于计算相似度。

但是对于长文档,这种平均的方式显然过于粗糙。

doc2vec是word2vec的拓展,它可以直接获得sentences/paragraphs/documents的向量表达,从而可以进一步通过计算距离来得到sentences/paragraphs/documents之间的相似性。

模型概况

分析目的:获得文档的一个固定长度的向量表达。
数据:多个文档,以及它们的标签,一般可以用标题作为标签。
影响模型准确率的因素:语料的大小,文档的数量,越多越高;文档的相似性,越相似越好。
import jieba
import gensim
from gensim.models import doc2vecdef m_doc(doclist):reslist = []for i, doc in enumerate(doclist):reslist.append(doc2vec.TaggedDocument(jieba.lcut(doc), [i]))#添加每个文档的标题return reslistcorp = m_doc(chapter.txt)
corp[:2]
[TaggedDocument(words=['第一回', ' ', '风雪', '惊变', '那', '说话', '人', '五十', '来', '岁', '年纪', ',', '一件', '青布', '长袍', '早洗', '得', '褪成', '了', '蓝灰', '带白', '。', '只',...... '听', '他', '两片', '梨花', '木, '过', '了', '一会', ',', '颜烈', '道', ':', '“', '娘子', '请', '自', '宽', '便', ',', '小人', '出去', '买', '了', '物品', '就', '回', '。', '”', '包惜弱', '点', '了', '点头', ',', '道', ':', '“', '相公', '可别', '太多', '花费', '了', '。', '”', '颜烈', '微笑', '道', ':', '“', '就', '可惜', '娘子', '在', '服丧', ',', '不能', '戴用', '珠宝', ',', '要', '多花钱', '也', '花', '不了', '。', '”', '], tags=[0]),TaggedDocument(words=['第二回', ' ', '江南七怪', '颜烈', '跨出', '房门', ',', '过道', '中', '一个', ......'中年', '士人', '拖', '着', '鞋', '皮', ',', '踢', '跶', '踢', '跶', '的', '直响', ',', '一路打', '着', '哈欠', '迎面', '过来', ',', '那', '士人', '似笑非笑', ',', '挤眉弄眼', ',', ''没', '洗脸', '了', ',', '拿', '着', '一', '柄', '破烂', '的', '油纸', '黑扇', ',', '边摇边行', '。段天德', '吓', '得', '魂不附体', ',', '哪里', '还敢', '停留', ',', '拉', '了', '李萍', ',', '急奔', '而出', '。', '李萍大', '叫', ':', '“', '救命', '啊', ',', '我', '不', '去', ',', '救命', '啊', '!', '”', '终于', '声音', '越来越', '远', '。], tags=[1])]
#进行模型的设定与拟合
d2vmodel = gensim.models.Doc2Vec(vector_size = 300, window = 20, min_count = 5)#300维,窗口为20
%time d2vmodel.build_vocab(corp)#进行拟合
Wall time: 1.88 s
d2vmodel.wv.vocab#查看生成的结果,为每一个词都生成一个向量
{' ': <gensim.models.keyedvectors.Vocab at 0x230b88bef98>,'风雪': <gensim.models.keyedvectors.Vocab at 0x230b88bedd8>,'那': <gensim.models.keyedvectors.Vocab at 0x230c4fea780>,'说话': <gensim.models.keyedvectors.Vocab at 0x230c4fea828>,......'曲三': <gensim.models.keyedvectors.Vocab at 0x230c7f9f470>,'掘': <gensim.models.keyedvectors.Vocab at 0x230c7fb49e8>,'最后': <gensim.models.keyedvectors.Vocab at 0x230c7fb4a20>,'一具': <gensim.models.keyedvectors.Vocab at 0x230c7fb4a58>,...}
# 如果有个新文本想要呈现的话,将新文本转换为相应维度空间下的向量
newvec = d2vmodel.infer_vector(jieba.lcut(chapter.txt[1]))
#检索出和新文本相比最相似的章节
d2vmodel.docvecs.most_similar([newvec], topn = 10)#如果只有一个list,需要打上[]
[(33, 0.17437607049942017),(36, 0.10029015690088272),(22, 0.07945042848587036),(18, 0.04506886377930641),(14, 0.03940583020448685),(23, 0.035881608724594116),(6, 0.03350480645895004),(31, 0.03314536064863205),(16, 0.028236132115125656),(13, 0.022862425073981285)]

1.3文档聚类

在得到文档相似度的计算结果后,文档聚类问题在本质上已经和普通的聚类分析没有区别。

注意:最常用的Kmeans使用的是平方欧氏距离,这在文本聚类中很可能无法得到最佳结果。

算法的速度和效果同样重要。

# 为章节增加名称标签
chapter.index = [raw.txt[raw.chap == i].iloc[0] for i in chapter.index]
chapter.head()
txt cut
第一回 风雪惊变 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两... [第一回, , 风雪, 惊变,  ,  ,  ,  ,  ,  , 那, 说话, 人, 五...
第二回 江南七怪 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈... [第二回, , 江南七怪,  ,  ,  ,  , 颜烈, 跨出, 房门, ,, 过道, ...
第三回 黄沙莽莽 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽... [第三回, , 黄沙, 莽莽,  ,  ,  ,  , 寺里, 僧众, 见, 焦木, 圆寂...
第四回 黑风双煞 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎... [第四回, , 黑风双, 煞,  ,  ,  ,  , 完颜洪熙, 笑, 道, :, “,...
第五回 弯弓射雕 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰... [第五回, , 弯弓, 射雕,  ,  ,  ,  , 一行, 人下, 得, 山来, ,,...
#进行文本清理
import jieba
cuttxt = lambda x: " ".join(m_cut(x)) #循环
cleanchap = chapter.txt.apply(cuttxt)
cleanchap[:2]
第一回 风雪惊变    第一回 风雪 惊变 说话 五十 年纪 一件 青布 长袍 早洗 褪成 蓝灰 带白 两片 梨花 ...
第二回 江南七怪    第二回 江南七怪 颜烈 跨出 房门 过道 一个 中年 士人 直响 一路打 哈欠 迎面 士人 ...
Name: txt, dtype: object
# 计算TF-IDF矩阵
from sklearn.feature_extraction.text import TfidfTransformervectorizer = CountVectorizer()
wordmtx = vectorizer.fit_transform(cleanchap) # 将文本中的词语转换为词频矩阵  transformer = TfidfTransformer()
tfidf = transformer.fit_transform(wordmtx)  #基于词频矩阵计算TF-IDF值
tfidf
<40x43931 sparse matrix of type '<class 'numpy.float64'>'with 129387 stored elements in Compressed Sparse Row format>
# 进行聚类分析
#kmeas用词频矩阵不合适,因此使用tfidf比较合适
from sklearn.cluster import KMeans  clf = KMeans(n_clusters = 5)  #聚为5类,即:原来分40个章节,现在聚为4大类
s = clf.fit(tfidf)
print(s)
clf.cluster_centers_ #把中心的情况打印出来
KMeans(n_clusters=5)array([[0.        , 0.        , 0.        , ..., 0.        , 0.00281383,0.        ],[0.00048249, 0.        , 0.        , ..., 0.00098597, 0.        ,0.00048249],[0.        , 0.        , 0.        , ..., 0.        , 0.        ,0.        ],[0.        , 0.        , 0.        , ..., 0.        , 0.        ,0.        ],[0.        , 0.00080214, 0.00080214, ..., 0.        , 0.        ,0.        ]])
clf.cluster_centers_.shape
(5, 43931)
clf.labels_#分别看下每个章节都被归为哪一类
array([2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 1, 4, 1, 1, 1, 1, 1, 1, 1,1, 4, 1, 1, 1, 1, 0, 0, 0, 1, 4, 1, 1, 1, 1, 1, 1, 1])
#为了便于阅读,直接把类别情况加入数据框中
chapter['clsres'] = clf.labels_
chapter.head()
txt cut clsres
第一回 风雪惊变 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两... [第一回, , 风雪, 惊变,  ,  ,  ,  ,  ,  , 那, 说话, 人, 五... 2
第二回 江南七怪 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈... [第二回, , 江南七怪,  ,  ,  ,  , 颜烈, 跨出, 房门, ,, 过道, ... 2
第三回 黄沙莽莽 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽... [第三回, , 黄沙, 莽莽,  ,  ,  ,  , 寺里, 僧众, 见, 焦木, 圆寂... 3
第四回 黑风双煞 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎... [第四回, , 黑风双, 煞,  ,  ,  ,  , 完颜洪熙, 笑, 道, :, “,... 3
第五回 弯弓射雕 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰... [第五回, , 弯弓, 射雕,  ,  ,  ,  , 一行, 人下, 得, 山来, ,,... 3
chapter.sort_values('clsres').clsres#进行排序
第三十回 一灯大师      0
第三十一回 鸳鸯锦帕     0
第二十九回 黑沼隐女     0
......
第十三回 五湖废人      4
第九回 铁枪破犁       4
Name: clsres, dtype: int32
#把对应类别的文档归为一个大文档在进行处理
chapgrp = chapter.groupby('clsres')
chapcls = chapgrp.agg(sum) # 只有字符串列的情况下,sum函数自动转为合并字符串cuttxt = lambda x: " ".join(m_cut(x))
chapclsres = chapcls.txt.apply(cuttxt)
chapclsres
clsres
0    第二十九回 黑沼 隐女 郭靖 呼叫 召唤 小红马 地下 转眼之间 双雕 飞出 老远 雌雄 双...
1    第十四回 桃花 岛主 五男一女 走进 厅来 却是 江南 六怪 北南 故乡 日近 这天 太湖 ...
2    第一回 风雪 惊变 说话 五十 年纪 一件 青布 长袍 早洗 褪成 蓝灰 带白 两片 梨花 ...
3    第三回 黄沙 莽莽 寺里 僧众 焦木 圆寂 悲哭 伤者 包扎 伤处 抬入 客舍 巨钟 缸内 ...
4    第七回 比武招亲 江南 六怪 郭靖 晓行夜宿 东南 进发 非止 一日 大漠 草原 这天 张家...
Name: txt, dtype: object
# 列出关键词以刻画类别特征
import jieba.analyse as anaana.set_stop_words('停用词.txt')
#为了方便,直接使用jieba分词里面列关键词的功能
for item in chapclsres:print(ana.extract_tags(item, topK = 10))
['黄蓉', '郭靖', '一灯', '黄蓉道', '那书生', '渔人', '一灯大师', '农夫', '段皇爷', '郭靖道']
['郭靖', '黄蓉', '欧阳锋', '黄药师', '洪七公', '周伯通', '裘千仞', '武功', '郭靖道', '欧阳克']
['丘处机', '杨铁心', '包惜弱', '郭啸天', '段天德', '颜烈', '完颜洪烈', '柯镇恶', '金兵', '道长']
['郭靖', '铁木真', '柯镇恶', '韩小莹', '梅超风', '哲别', '朱聪', '韩宝驹', '拖雷', '华筝']
['郭靖', '黄蓉', '洪七公', '完颜康', '师父', '彭连虎', '陆冠英', '梁子翁', '欧阳克', '穆念慈']

实战练习

在计算词条相似度时进行停用词清理,然后再进行拟合,思考为什么会有这样的结果出现。

在基于词袋模型,使用原始词频计算文本余弦相似度时,比较清理停用词前后的结果。

#第一题进行停用词清理,在计算词条相似度
import jieba
import pandas as pd
tmpdf = pd.read_table('停用词.txt',names = ['w'], encoding = 'utf-8')
chapter['cut'] = chapter.txt.apply(jieba.lcut)
chapter['cut'] =[ w for w in chapter['cut']  if w not in list(tmpdf.w) ]
chapter.head()
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\A\AppData\Local\Temp\jieba.cache
Loading model cost 0.557 seconds.
Prefix dict has been built successfully.
txt cut
chap
1.0 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两... [第一回, , 风雪, 惊变,  ,  ,  ,  ,  ,  , 那, 说话, 人, 五...
2.0 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈... [第二回, , 江南七怪,  ,  ,  ,  , 颜烈, 跨出, 房门, ,, 过道, ...
3.0 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽... [第三回, , 黄沙, 莽莽,  ,  ,  ,  , 寺里, 僧众, 见, 焦木, 圆寂...
4.0 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎... [第四回, , 黑风双, 煞,  ,  ,  ,  , 完颜洪熙, 笑, 道, :, “,...
5.0 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰... [第五回, , 弯弓, 射雕,  ,  ,  ,  , 一行, 人下, 得, 山来, ,,...
# 初始化word2vec模型和词表
from gensim.models.word2vec import Word2Vec
n_dim = 300 # 指定向量维度,大样本量时300~500较好
w2vmodel = Word2Vec(size = n_dim, min_count = 10)
w2vmodel.build_vocab(chapter.cut) # 生成词表# 在评论训练集上建模(大数据集时可能会花费几分钟)
w2vmodel.train(chapter.cut, \total_examples = w2vmodel.corpus_count, epochs = 10)# 训练完毕的模型实质
print(w2vmodel.wv["郭靖"].shape)
w2vmodel.wv["郭靖"]
(300,)array([ 0.34924605,  0.21265522,  0.5632632 ,  0.3580753 ,  0.17115285,0.48449898,  0.11169011,  0.33496168,  0.8114401 ,  0.6040344 ,0.27803087, -0.56468904, -0.05460463, -0.11949269, -0.08181898,......0.2831581 ,  0.60918677, -0.17329499,  0.11961225, -0.30500183,-0.31079102, -0.64060545,  0.03041249,  0.66229236,  0.88437986],dtype=float32)
#基于词袋模型计算文本余弦相似度时,比较清理停用词前后的结果
#实例给出了加入停用词前的,基于前面的现在计算停用词后的
import jieba
import pandas as pd
tmpdf = pd.read_table('停用词.txt',names = ['w'], encoding = 'utf-8')
chapter['cut'].iloc[:5]= [ " ".join(m_cut(w)) for w in chapter.txt.iloc[:5] ]
chapter['cut'].iloc[:5]=[ w for w in chapter['cut'].iloc[:5] if w not in list(tmpdf.w) ] from sklearn.feature_extraction.text import CountVectorizercountvec = CountVectorizer() resmtx = countvec.fit_transform(chapter['cut'].iloc[:5])
resmtx
<5x11623 sparse matrix of type '<class 'numpy.int64'>'with 16884 stored elements in Compressed Sparse Row format>
from sklearn.metrics.pairwise import pairwise_distancespairwise_distances(resmtx, metric = 'cosine')
#根据结果,停用词前后结果相同
array([[0.        , 0.63104216, 0.77665559, 0.78745025, 0.82985512],[0.63104216, 0.        , 0.62572437, 0.61666388, 0.73192845],[0.77665559, 0.62572437, 0.        , 0.51645443, 0.5299046 ],[0.78745025, 0.61666388, 0.51645443, 0.        , 0.42108002],[0.82985512, 0.73192845, 0.5299046 , 0.42108002, 0.        ]])

2.文档分类

朴素贝叶斯算法(优先考虑使用)

2.1 sklearn实现

sklearn是标准的数据挖掘建模工具包,在语料转换为d2m矩阵结构之后,就可以使用所有标准的DM建模手段在sklearn中进行分析。

在sklearn中也实现了朴素贝叶斯算法,使用方式上也和其他模型非常相似。

2.1.1 使用贝叶斯进行分类

生成D2M矩阵

# 从原始语料df中提取出所需的前两章段落
raw12 = raw[raw.chap.isin([1,2])]
raw12ana = raw12.iloc[list(raw12.txt.apply(len) > 50), :] # 只使用超过50字的段落
raw12ana.reset_index(drop = True, inplace = True)#对索引再排序
print(len(raw12ana))
raw12ana.head()
376
txt chap
0 那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两片梨花木板碰了几下,左手... 1.0
1 那说话人将木板敲了几下,说道:“这首七言诗,说的是兵火过后,原来的家家户户,都变成了断墙... 1.0
2 “叶老汉和叶妈妈吓得呆了,扑将上去,搂住了儿子的尸体,放声大哭。那长官提起狼牙棒,一棒一... 1.0
3 “可是那金兵占了我大宋天下,杀人放火,奸淫掳掠,无恶不作,却又不见他遭到什么报应。只怪我... 1.0
4 村民中走出一个二十来岁的大汉,说道:“张先生,你可是从北方来吗?”说的是北方口音。张十五... 1.0
import jieba
cuttxt = lambda x: " ".join(jieba.lcut(x)) # 这里不做任何清理工作,以保留情感词
raw12ana["cleantxt"] = raw12ana.txt.apply(cuttxt)
raw12ana.head()
<ipython-input-12-b42f436ca4f7>:3: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copyraw12ana["cleantxt"] = raw12ana.txt.apply(cuttxt)
txt chap cleantxt
0 那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两片梨花木板碰了几下,左手... 1.0 那 说话 人 五十 来 岁 年纪 , 一件 青布 长袍 早洗 得 褪成 了 蓝灰 带...
1 那说话人将木板敲了几下,说道:“这首七言诗,说的是兵火过后,原来的家家户户,都变成了断墙... 1.0 那 说话 人 将 木板 敲 了 几下 , 说道 : “ 这首 七言诗 , 说 的 是...
2 “叶老汉和叶妈妈吓得呆了,扑将上去,搂住了儿子的尸体,放声大哭。那长官提起狼牙棒,一棒一... 1.0 “ 叶老汉 和 叶 妈妈 吓 得 呆 了 , 扑 将 上去 , 搂住 了 儿子 的 ...
3 “可是那金兵占了我大宋天下,杀人放火,奸淫掳掠,无恶不作,却又不见他遭到什么报应。只怪我... 1.0 “ 可是 那金兵 占 了 我 大宋 天下 , 杀人放火 , 奸淫掳掠 , 无恶不作 ...
4 村民中走出一个二十来岁的大汉,说道:“张先生,你可是从北方来吗?”说的是北方口音。张十五... 1.0 村民 中 走出 一个二十 来 岁 的 大汉 , 说道 : “ 张 先生 , 你 可是...
#转换为词频矩阵
from sklearn.feature_extraction.text import CountVectorizer
countvec = CountVectorizer()
wordmtx = countvec.fit_transform(raw12ana.cleantxt)
wordmtx
<376x6724 sparse matrix of type '<class 'numpy.int64'>'with 13642 stored elements in Compressed Sparse Row format>
# 作用:将数据集划分为 训练集和测试集
from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(wordmtx, raw12ana.chap, test_size = 0.3, random_state = 111)
#要训练的矩阵,期待的结果,测试集的比例(30%),随机数(相同则相同结果重现)
#拟合朴素贝叶斯模型from sklearn import naive_bayes#导入贝叶斯
NBmodel = naive_bayes.MultinomialNB()
# 拟合模型
NBmodel.fit(x_train, y_train)
# 进行验证集预测
x_test
<113x6724 sparse matrix of type '<class 'numpy.int64'>'with 4127 stored elements in Compressed Sparse Row format>
NBmodel.predict(x_test)#查看预测结果
array([2., 2., 1., 2., 1., 2., 1., 1., 2., 1., 2., 1., 2., 2., 1., 2., 1.,2., 1., 1., 2., 2., 1., 1., 2., 1., 2., 1., 1., 2., 1., 2., 1., 1.,2., 1., 1., 1., 1., 1., 1., 2., 1., 1., 2., 2., 2., 1., 1., 1., 2.,1., 1., 1., 2., 1., 2., 1., 2., 2., 2., 2., 1., 1., 1., 1., 1., 1.,1., 1., 2., 2., 1., 1., 1., 1., 1., 2., 1., 2., 1., 1., 2., 2., 2.,1., 1., 1., 2., 1., 1., 2., 1., 1., 1., 2., 2., 2., 2., 2., 1., 1.,2., 1., 1., 2., 2., 2., 2., 1., 1., 2., 2.])
# 预测准确率(给模型打分)
print('训练集:', NBmodel.score(x_train, y_train), ',验证集:', NBmodel.score(x_test, y_test))
训练集: 1.0 ,验证集: 0.9557522123893806
#做出更详细的验证报告
from sklearn.metrics import classification_reportprint(classification_report(y_test, NBmodel.predict(x_test)))#验证集的实测结果与验证集的预测结果相比较
              precision    recall  f1-score   support1.0       0.94      0.98      0.96        612.0       0.98      0.92      0.95        52accuracy                           0.96       113macro avg       0.96      0.95      0.96       113
weighted avg       0.96      0.96      0.96       113

模型预测

将需要预测的文本转换为和建模时格式完全对应的d2m矩阵格式,随后即可进行预测。

countvec.vocabulary_#查看转换的时候的字典
{'说话': 5703,'五十': 765,'年纪': 2855,......'握住': 3565,'猎叉': 4588,'随即': 6438,...}
string = "杨铁心和包惜弱收养穆念慈"
words = " ".join(jieba.lcut(string))
words_vecs = countvec.transform([words]) #需要用[] 转换为可迭代的list格式
words_vecs
<1x6724 sparse matrix of type '<class 'numpy.int64'>'with 2 stored elements in Compressed Sparse Row format>
NBmodel.predict(words_vecs)
array([1.])

2.1.2 使用Logistic回归模型进行分类

from sklearn.linear_model import LogisticRegressionlogitmodel = LogisticRegression() # 定义Logistic回归模型
# 拟合模型
logitmodel.fit(x_train, y_train)
print(classification_report(y_test, logitmodel.predict(x_test)))
              precision    recall  f1-score   support1.0       0.94      0.98      0.96        612.0       0.98      0.92      0.95        52accuracy                           0.96       113macro avg       0.96      0.95      0.96       113
weighted avg       0.96      0.96      0.96       113

2.2 NLTK实现

NLTK中内置了朴素贝叶斯算法,可直接实现文档分类。

数据集中语料的格式
用于训练的语料必须是分词完毕的字典形式,词条为键名,键值则可以是数值、字符、或者T/F

{‘张三’ : True, ‘李四’ : True, ‘王五’ : False}

{‘张三’ : 1, ‘李四’ : 1, ‘王五’ : 0}

{‘张三’ : ‘有’, ‘李四’ : ‘有’, ‘王五’ : ‘无’}

训练用数据集的格式

训练用数据集为list of list格式,每个成员为list[语料字典, 结果变量]

[

[{‘张三’ : 1, ‘李四’ : 1, ‘王五’ : 0}, ‘合格’],

[{‘张三’ : 0, ‘李四’ : 1, ‘王五’ : 0}, ‘不合格’]

]

构建模型

考虑到过拟合问题,此处需要先拆分好训练集和测试集

model = NaiveBayesClassifier.train(training_data)

# 这里直接以章节为一个单元进行分析,以简化程序结构
import nltk
from nltk import FreqDist# 生成完整的词条频数字典,这部分也可以用遍历方式实现
fdist1 = FreqDist(m_cut(chapter.txt[1]))
fdist2 = FreqDist(m_cut(chapter.txt[2]))
fdist3 = FreqDist(m_cut(chapter.txt[3]))
fdist1
FreqDist({'第一回': 1,'风雪': 3,'惊变': 1,'说话': 9,......'一具': 1,'黑色': 1,'盘形': 1,...})
#导入贝叶斯
from nltk.classify import NaiveBayesClassifier#分别引入第一二三章,生成训练数据
training_data = [ [fdist1, 'chap1'], [fdist2, 'chap2'], [fdist3, 'chap3'] ]
# 训练分类模型
NLTKmodel = NaiveBayesClassifier.train(training_data)
#进行预测
print(NLTKmodel.classify(FreqDist(m_cut("杨铁心收养穆念慈"))))
print(NLTKmodel.classify(FreqDist(m_cut("钱塘江 日日夜夜 包惜弱 颜烈 使出杨家枪"))))
chap3
chap2
#模型拟合效果的考察
nltk.classify.accuracy(NLTKmodel, training_data) # 准确度评价
#参数:哪个模型、相应的数据集
1.0
#显示出最有价值的词条特征
NLTKmodel.show_most_informative_features(5)#得到似然比,检测对于哪些特征有用
Most Informative Features飞将 = None            chap3 : chap2  =      1.0 : 1.0几茎 = None            chap2 : chap1  =      1.0 : 1.0

实战作业

对射雕的前两个章节提取关键字,然后使用关键字而不是原始文本进行文档分类,比较这样两种方式的分类效果有何变化。

减少用于训练的样本量,考察使用朴素贝叶斯算法或者其他标准分类算法时,模型效果的变化趋势。

自行实现基于NLTK的按段落为单位进行章节分类的程序。

import jieba
import jieba.analyse
import jieba
chapter['cut'] = chapter.txt.apply(jieba.lcut)
chapter.head()
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\A\AppData\Local\Temp\jieba.cache
Loading model cost 0.555 seconds.
Prefix dict has been built successfully.
txt cut
chap
1.0 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两... [第一回, , 风雪, 惊变,  ,  ,  ,  ,  ,  , 那, 说话, 人, 五...
2.0 第二回 江南七怪    颜烈跨出房门,过道中一个中年士人拖着鞋皮,踢跶踢跶的直响,一路打着哈... [第二回, , 江南七怪,  ,  ,  ,  , 颜烈, 跨出, 房门, ,, 过道, ...
3.0 第三回 黄沙莽莽    寺里僧众见焦木圆寂,尽皆悲哭。有的便为伤者包扎伤处,抬入客舍。  忽... [第三回, , 黄沙, 莽莽,  ,  ,  ,  , 寺里, 僧众, 见, 焦木, 圆寂...
4.0 第四回 黑风双煞    完颜洪熙笑道:“好,再打他个痛快。”蒙古兵前哨报来:“王罕亲自前来迎... [第四回, , 黑风双, 煞,  ,  ,  ,  , 完颜洪熙, 笑, 道, :, “,...
5.0 第五回 弯弓射雕    一行人下得山来,走不多时,忽听前面猛兽大吼声一阵阵传来。韩宝驹一提缰... [第五回, , 弯弓, 射雕,  ,  ,  ,  , 一行, 人下, 得, 山来, ,,...
#对前两章提取关键词
key1=jieba.analyse.extract_tags(chapter.txt[1])
key2=jieba.analyse.extract_tags(chapter.txt[2])
key=key1+key2
key
['杨铁心','包惜弱','郭啸天','颜烈','丘处机','杨二人',......'金兵','武功','道长','南希仁','全金发','李萍']
# 转为D2M矩阵
from sklearn.feature_extraction.text import CountVectorizer
countvec = CountVectorizer()
wordmtx = countvec.fit_transform(key)
wordmtx
<40x34 sparse matrix of type '<class 'numpy.int64'>'with 40 stored elements in Compressed Sparse Row format>
# 作用:将数据集划分为 训练集和测试集
from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(wordmtx, raw12ana.chap[:40], test_size = 0.3, random_state = 1)
#测试图片(train_images)和测试标签(train_labels)的长度必须一致
from sklearn import naive_bayesNBmodel = naive_bayes.MultinomialNB()
# 拟合模型
NBmodel.fit(x_train, y_train)
# 进行验证集预测
x_test
# 预测准确率(给模型打分)
print('训练集:', NBmodel.score(x_train, y_train), ',验证集:', NBmodel.score(x_test, y_test))
训练集: 1.0 ,验证集: 1.0
#减少用于训练的样本量
from sklearn.feature_extraction.text import CountVectorizer
countvec = CountVectorizer() wordmtx = countvec.fit_transform(raw12ana.cleantxt)
wordmtx
<376x6724 sparse matrix of type '<class 'numpy.int64'>'with 13642 stored elements in Compressed Sparse Row format>
# 作用:将数据集划分为 训练集和测试集,训练样本量改为20%
from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(wordmtx, raw12ana.chap, test_size = 0.8, random_state = 111)
from sklearn import naive_bayesNBmodel = naive_bayes.MultinomialNB()
# 拟合模型
NBmodel.fit(x_train, y_train)
#模型评估
from sklearn.metrics import classification_reportprint(classification_report(y_test, NBmodel.predict(x_test)))
              precision    recall  f1-score   support1.0       0.84      0.96      0.89       1562.0       0.94      0.81      0.87       145accuracy                           0.88       301macro avg       0.89      0.88      0.88       301
weighted avg       0.89      0.88      0.88       301

可见训练集过少会直接影响训练的效果

3. 情感分析

情感分析概述

3.1 基于词袋模型的分析

数据概况:

取自购物网站的正向、负向评价各约1万条。

# 读入原始数据集
import pandas as pddfpos = pd.read_excel("购物评论.xlsx", sheet_name = "正向", header=None)
dfpos['y'] = 1
dfneg = pd.read_excel("购物评论.xlsx", sheet_name = "负向", header=None)
dfneg['y'] = 0
df0 = dfpos.append(dfneg, ignore_index = True)#两个表格接到一起
df0.head()
0 y
0 感觉用这个手机下载MP3听很方便,用T-Flash卡装上歌,就可以当一个小MP3用了,很不错... 1
1 外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。... 1
2 我刚拿到书,也没有仔细阅读,就是粗粗的翻了点,觉得还行。里面是蓝黑两种颜色的,有些单词的下面... 1
3 对于二胡曲的精选,应该出版一个系列套装,可分别出售,单独购买。精品二胡曲是有年代和阶段性的,... 1
4 用了一年半的 e680 终于送小偷了。刚刚买了一台e850,用了三天,说说我自己的感受。1:... 1
# 分词和预处理
import jiebacuttxt = lambda x: " ".join(jieba.lcut(x)) # 这里不去停用词,以保留情感词
df0["cleantxt"] = df0[0].apply(cuttxt)
df0.tail()
0 y cleantxt
20577 服务员太差,房间很吵,隔音不好,房间味道很重,很一般,不如稀土国际大酒店好,收费有低,还是四... 0 服务员 太 差 , 房间 很 吵 , 隔音 不好 , 房间 味道 很 重 , 很 一般 , ...
20578 很早我就说等“爱氏晨曦”吃进蒙牛股份后,对蒙牛的质疑就会停止,如今已应验。想知道单是这一笔... 0 很早 我 就 说 等 “ 爱氏 晨曦 ” 吃进 蒙牛 股份 后 , 对 蒙牛 的 质疑 ...
20579 2——10岁是什么意思?我不认为有一本书可以覆盖这样的范围,事实上,我两岁的女儿不能理解这套... 0 2 — — 10 岁 是 什么 意思 ? 我 不 认为 有 一 本书 可以 覆盖 这样 的 ...
20580 刚住过这里,感觉不好,房间味道太大,一股子霉味,房间各种设施都很陈旧,我所预订的大床间,却没... 0 刚住 过 这里 , 感觉不好 , 房间 味道 太 大 , 一股 子 霉味 , 房间 各种 设...
20581 一本书200页,综合一下只有3页可看 却要花200页的钱 唉 唉 0 一 本书 200 页 , 综合 一下 只有 3 页 可 看 却 要 花 200 页 ...
#构建矩阵
from sklearn.feature_extraction.text import CountVectorizer
countvec = CountVectorizer(min_df = 5) # 出现5次以上的才纳入wordmtx = countvec.fit_transform(df0.cleantxt)
wordmtx
<20582x12014 sparse matrix of type '<class 'numpy.int64'>'with 513919 stored elements in Compressed Sparse Row format>
# 按照7:3的比例生成训练集和测试集
from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(wordmtx, df0.y, test_size=0.3) # 这里可以直接使用稀疏矩阵格式
x_train[0]
<1x12014 sparse matrix of type '<class 'numpy.int64'>'with 14 stored elements in Compressed Sparse Row format>
# 使用SVM进行建模,也可考虑多个建模方法
from sklearn.svm import SVCclf=SVC(kernel = 'rbf', verbose = True)#常规设定
clf.fit(x_train, y_train) # 内存占用可能较高
clf.score(x_train, y_train)#得出模型的评分
[LibSVM]
0.9535642396057472
# 对模型效果进行评估
from sklearn.metrics import classification_reportprint(classification_report(y_test, clf.predict(x_test)))
              precision    recall  f1-score   support0       0.87      0.90      0.88      30551       0.89      0.86      0.88      3120accuracy                           0.88      6175macro avg       0.88      0.88      0.88      6175
weighted avg       0.88      0.88      0.88      6175
#将相应的数据集转为向量,进行预测。下面的函数更为清晰
clf.predict(countvec.transform([df0.cleantxt[0]]))[0]
1
# 模型预测,书写函数,使结果易读
import jiebadef m_pred(string, countvec, model) : words = " ".join(jieba.lcut(string))words_vecs = countvec.transform([words]) # 数据需要转换为可迭代格式result = model.predict(words_vecs)if int(result[0]) == 1:print(string, ":正向")else:print(string, ":负向")comment = "外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。风扇噪音也不大。"
m_pred(comment, countvec, clf)
外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。风扇噪音也不大。 :正向
comment = "作为女儿6.1的礼物。虽然晚到了几天。等拿到的时候,女儿爱不释手,上洗手间也看,告知不好。上周末,告诉我她把火鞋和风鞋拿到学校,好多同学羡慕她。呵呵,我也看了其中的人鸦,只可惜没有看完就在老公的催促下睡了。说了这么多,归纳为一句:这套书买的值。"
m_pred(comment, countvec, clf)
作为女儿6.1的礼物。虽然晚到了几天。等拿到的时候,女儿爱不释手,上洗手间也看,告知不好。上周末,告诉我她把火鞋和风鞋拿到学校,好多同学羡慕她。呵呵,我也看了其中的人鸦,只可惜没有看完就在老公的催促下睡了。说了这么多,归纳为一句:这套书买的值。 :正向

3.2 基于分布式表达的分析(对于短文本来说,效果更优)

和词袋模型相比,分布式表达主要是改变了文本信息的提取方式。

目前主要使用gensim实现相应的算法。

注意:由于矩阵不再是频数值(正负想间),因此不能使用朴素贝叶斯算法来进行拟合。

# 读入原始数据集,和上面完全相同
import pandas as pddfpos = pd.read_excel("购物评论.xlsx", sheet_name = "正向", header=None)
dfpos['y'] = 1
dfneg = pd.read_excel("购物评论.xlsx", sheet_name = "负向", header=None)
dfneg['y'] = 0
df0 = dfpos.append(dfneg, ignore_index = True)
df0.head()
0 y
0 感觉用这个手机下载MP3听很方便,用T-Flash卡装上歌,就可以当一个小MP3用了,很不错... 1
1 外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。... 1
2 我刚拿到书,也没有仔细阅读,就是粗粗的翻了点,觉得还行。里面是蓝黑两种颜色的,有些单词的下面... 1
3 对于二胡曲的精选,应该出版一个系列套装,可分别出售,单独购买。精品二胡曲是有年代和阶段性的,... 1
4 用了一年半的 e680 终于送小偷了。刚刚买了一台e850,用了三天,说说我自己的感受。1:... 1
# 分词和预处理,生成list of list格式
import jiebadf0['cut'] = df0[0].apply(jieba.lcut)
df0.head()
0 y cut
0 感觉用这个手机下载MP3听很方便,用T-Flash卡装上歌,就可以当一个小MP3用了,很不错... 1 [感觉, 用, 这个, 手机, 下载, MP3, 听, 很, 方便, ,, 用, T, -,...
1 外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。... 1 [外观, 美观, ,, 速度, 也, 不错, 。, 上面, 一排, 触摸, 键, 挺, 实用...
2 我刚拿到书,也没有仔细阅读,就是粗粗的翻了点,觉得还行。里面是蓝黑两种颜色的,有些单词的下面... 1 [我刚, 拿到, 书, ,, 也, 没有, 仔细阅读, ,, 就是, 粗粗, 的, 翻, 了...
3 对于二胡曲的精选,应该出版一个系列套装,可分别出售,单独购买。精品二胡曲是有年代和阶段性的,... 1 [对于, 二胡曲, 的, 精选, ,, 应该, 出版, 一个系列, 套装, ,, 可, 分别...
4 用了一年半的 e680 终于送小偷了。刚刚买了一台e850,用了三天,说说我自己的感受。1:... 1 [用, 了, 一年, 半, 的, , e680, , 终于, 送, 小偷, 了, 。, ...
 # 按照7:3的比例生成训练集和测试集
from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(df0.cut, df0.y, test_size=0.3)
x_train[:2]
10965    [儿子, 1, 年, 7, 个, 月, ,, 虽然, 好多, 都, 不是, 很, 懂, ,,...
17209    [这家, 酒店, 绝对, 没有, 四星级, ,, 而且, 房间, 的, 隔音, 太, 差, ...
Name: cut, dtype: object
# 初始化word2vec模型和词表
from gensim.models.word2vec import Word2Vec
n_dim = 300 # 指定向量维度,大样本量时300~500较好
w2vmodel = Word2Vec(vector_size = n_dim, min_count = 10)
w2vmodel.build_vocab(x_train) # 生成词表
# 在评论训练集上建模(大数据集时可能会花费几分钟)
# 本例消耗内存较少
%time w2vmodel.train(x_train, \total_examples = w2vmodel.corpus_count, epochs = 10)
Wall time: 4.67 s(6346434, 9495160)
# 情感词向量间的相似度
w2vmodel.wv.most_similar("不错")
[('好', 0.6664835810661316),('行', 0.6593450903892517),('挺不错', 0.658033549785614),('比较满意', 0.6418668627738953),('很漂亮', 0.5996091365814209),('还行', 0.5758983492851257),('很快', 0.5542255640029907),('整体', 0.5516241788864136),('漂亮', 0.5488754510879517),('说得过去', 0.5477145910263062)]
w2vmodel.wv.most_similar("失望")
[('遗憾', 0.7359662652015686),('不爽', 0.6579391360282898),('气愤', 0.647860586643219),('后悔', 0.6342949271202087),('不满', 0.6023170351982117),('生气', 0.5882432460784912),('上当', 0.5846213698387146),('难得', 0.5696483254432678),('糟糕', 0.5675068497657776),('浅', 0.5560178756713867)]

生成整句向量用于情感分值预测

对购物评论、微博等短文本而言,一般是将所有词向量的平均值作为分类算法的输入值。

    # 生成整句所对应的所有词条的词向量矩阵
pd.DataFrame([w2vmodel.wv[w] for w in df0.cut[0] if w in w2vmodel.wv]).head()
0 1 2 3 4 5 6 7 8 9 ... 290 291 292 293 294 295 296 297 298 299
0 -0.911332 2.487151 -0.445355 0.959004 -0.077999 -0.157231 -0.511012 0.636210 0.123468 -1.307333 ... -0.798626 -0.133126 2.084686 0.084197 0.662218 -0.711858 1.772625 1.529452 -0.640140 -0.091147
1 0.046230 -0.035792 1.241354 -1.354366 0.447580 -0.560420 1.272424 1.154507 -0.583416 -0.777637 ... -1.028960 0.141009 -0.139010 -0.353615 -0.938453 0.084964 0.510275 -0.698084 0.632293 -0.493197
2 0.588286 0.292953 -0.215384 -0.420847 -0.803060 -0.033820 0.018333 0.384169 -0.659887 -0.146808 ... 0.277545 1.046261 0.742007 0.230653 0.011729 -1.664741 0.118631 0.510197 -0.013587 -0.138566
3 0.191487 -0.297445 -0.385975 -1.030350 -1.255563 -1.214032 0.616230 0.202745 -1.133247 0.830488 ... 1.589015 -0.153522 -0.118775 -1.095460 -0.661065 -1.319211 0.029742 -0.847319 -0.723597 1.276379
4 -0.704394 -0.071939 0.100993 0.326895 -0.685714 -0.722568 -0.205036 0.934630 -0.240266 0.022127 ... 0.595830 -0.101508 -0.191669 -0.558731 -0.897231 -0.376409 -0.159503 -0.568233 0.471685 0.287301

5 rows × 300 columns

# 用各个词向量直接平均的方式生成整句对应的向量
def m_avgvec(words, w2vmodel):return pd.DataFrame([w2vmodel.wv[w] for w in words if w in w2vmodel.wv]).agg("mean")
# 生成建模用矩阵,耗时较长
%time train_vecs = pd.DataFrame([m_avgvec(s, w2vmodel) for s in x_train])
train_vecs.head()
Wall time: 2min 55s
0 1 2 3 4 5 6 7 8 9 ... 290 291 292 293 294 295 296 297 298 299
0 -0.138882 0.243906 0.155527 -0.057517 -0.243359 0.038505 0.123457 -0.029797 -0.251002 0.130891 ... -0.158522 0.328610 0.468559 0.006440 -0.071326 0.046429 0.262878 -0.073597 0.083408 -0.133627
1 0.123953 0.249146 0.031028 -0.103072 -0.012683 -0.061241 0.016736 0.236264 -0.238410 -0.349272 ... -0.094874 0.316148 0.283809 0.035215 0.100668 -0.150388 0.151585 0.202299 0.011277 -0.346626
2 0.009675 0.063508 0.298085 -0.113564 -0.394117 -0.197484 -0.143916 -0.264382 -0.165245 0.044551 ... -0.077013 0.219353 0.319499 -0.054280 -0.017593 0.068092 -0.043105 -0.314632 0.061136 -0.315324
3 -0.201478 0.054600 -0.197219 0.132496 -0.130859 0.059931 0.090897 0.447195 -0.066142 -0.080050 ... 0.216520 0.336789 0.242757 0.192332 0.255502 -0.000268 0.000050 -0.100486 0.013850 -0.163652
4 0.012418 0.231921 -0.169535 -0.027108 0.162233 0.089345 0.123997 0.351209 -0.036844 -0.328844 ... 0.154105 0.471911 0.131034 0.205431 -0.007795 0.122620 0.165309 0.214215 -0.148311 -0.170526

5 rows × 300 columns

%time train_vecs_t = pd.DataFrame([m_avgvec(x, w2vmodel) for x in x_test])
train_vecs_t
Wall time: 1min 14s
0 1 2 3 4 5 6 7 8 9 ... 290 291 292 293 294 295 296 297 298 299
0 -0.360456 -0.168126 -0.187902 0.139328 -0.580499 -0.476809 0.382865 0.896478 0.004519 0.060998 ... 0.337908 0.313125 -0.248374 -0.192784 0.191395 -0.003297 0.034540 -0.024345 0.307705 0.060049
1 -0.006573 0.364138 0.056596 0.062842 -0.164288 -0.038841 0.004568 0.271801 -0.263575 -0.250043 ... -0.107846 0.247452 0.225257 0.020039 0.135461 -0.112377 0.059987 -0.093346 0.092084 -0.338679
2 -0.342170 -0.107518 0.150887 -0.012432 -0.119799 -0.151469 0.062810 0.317839 -0.264509 -0.119258 ... -0.146024 0.251700 0.428559 0.112363 0.088508 0.010839 0.133946 0.158355 -0.091741 -0.333099
3 -0.036196 0.323747 0.038649 -0.041602 -0.247251 -0.055818 -0.080103 0.083953 -0.244907 -0.281211 ... -0.227069 0.363051 0.472190 0.076083 0.067558 -0.141818 0.051008 -0.112334 -0.019767 -0.421210
4 0.085083 0.189793 0.049033 0.066349 -0.216909 -0.071397 0.010042 0.301876 -0.342764 -0.218100 ... -0.164497 0.430071 0.122870 0.071452 0.140936 -0.096815 -0.089997 -0.006523 0.104536 -0.479253
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6170 -0.264900 0.084384 0.011239 0.049277 -0.141444 0.100749 0.315126 0.146341 -0.133169 -0.027791 ... 0.147190 0.336536 0.451692 0.175938 0.192036 0.165460 0.162585 0.089151 -0.057888 -0.233666
6171 0.026205 -0.071874 0.270545 -0.027888 -0.195445 -0.299105 -0.079034 0.288189 -0.127330 -0.068026 ... -0.192192 0.248696 0.323543 0.067723 -0.030734 0.041797 0.171027 -0.015046 0.115095 -0.231721
6172 -0.405061 0.005883 0.037920 0.075662 -0.039078 0.162015 0.093300 0.189479 -0.148963 -0.012335 ... 0.210263 0.391104 0.387380 0.136165 0.423261 0.131836 0.346203 -0.070695 0.047509 -0.027406
6173 -0.062726 -0.054550 -0.029740 -0.169576 -0.004502 -0.092310 0.181026 0.379483 -0.213536 -0.264653 ... 0.060071 0.408561 0.300502 0.174386 0.060165 0.039983 0.138749 0.112043 0.105036 -0.180624
6174 -0.122603 0.116725 0.177533 -0.111880 -0.154657 -0.210409 -0.083918 0.100732 -0.164870 0.042741 ... -0.196023 0.122320 0.098776 -0.089089 -0.085931 -0.149250 -0.006701 -0.196286 0.078928 -0.180735

6175 rows × 300 columns

train_vecs_t.isnull().any()
0      True
1      True
2      True
3      True
4      True...
295    True
296    True
297    True
298    True
299    True
Length: 300, dtype: bool

情感分析模型拟合

# 用转换后的矩阵拟合SVM模型
from sklearn.svm import SVCclf2 = SVC(kernel = 'rbf', verbose = True)
clf2.fit(train_vecs, y_train) # 占用内存小于1G
clf2.score(train_vecs, y_train)
[LibSVM]
0.8899146248351496
from sklearn.metrics import classification_reportprint(classification_report(y_train, clf2.predict(train_vecs)))
              precision    recall  f1-score   support0       0.89      0.89      0.89      71291       0.89      0.89      0.89      7278accuracy                           0.89     14407macro avg       0.89      0.89      0.89     14407
weighted avg       0.89      0.89      0.89     14407
# 模型预测
import jiebadef m_pred(string, model):words = jieba.lcut(string)words_vecs = pd.DataFrame(m_avgvec(words, w2vmodel)).Tresult = model.predict(words_vecs)if int(result[0]) == 1:print(string, ":正向")else:print(string, ":负向")comment = "作为女儿6.1的礼物。虽然晚到了几天。等拿到的时候,女儿爱不释手,上洗手间也看,告知不好。上周末,告诉我她把火鞋和风鞋拿到学校,好多同学羡慕她。呵呵,我也看了其中的人鸦,只可惜没有看完就在老公的催促下睡了。说了这么多,归纳为一句:这套书买的值。"
m_pred(comment, clf2)
作为女儿6.1的礼物。虽然晚到了几天。等拿到的时候,女儿爱不释手,上洗手间也看,告知不好。上周末,告诉我她把火鞋和风鞋拿到学校,好多同学羡慕她。呵呵,我也看了其中的人鸦,只可惜没有看完就在老公的催促下睡了。说了这么多,归纳为一句:这套书买的值。 :正向

实战作业

在本章所用数据中,各抽取1千条正向、负向评论,重新拟合基于词袋的和基于分布式表达的模型,比较前两种模型效果的改变情况。

# 只需在读入原始数据集时增加nrows属性,然后在进行训练,训练集减少,模型的效果会变差
import pandas as pddfpos = pd.read_excel("购物评论.xlsx", sheet_name = "正向", header=None,nrows=1000)
dfpos['y'] = 1
dfneg = pd.read_excel("购物评论.xlsx", sheet_name = "负向", header=None,nrows=1000)
dfneg['y'] = 0
df0 = dfpos.append(dfneg, ignore_index = True)#两个表格接到一起
df0.head()
0 y
0 感觉用这个手机下载MP3听很方便,用T-Flash卡装上歌,就可以当一个小MP3用了,很不错... 1
1 外观美观,速度也不错。上面一排触摸键挺实用。应该对得起这个价格。当然再降点大家肯定也不反对。... 1
2 我刚拿到书,也没有仔细阅读,就是粗粗的翻了点,觉得还行。里面是蓝黑两种颜色的,有些单词的下面... 1
3 对于二胡曲的精选,应该出版一个系列套装,可分别出售,单独购买。精品二胡曲是有年代和阶段性的,... 1
4 用了一年半的 e680 终于送小偷了。刚刚买了一台e850,用了三天,说说我自己的感受。1:... 1

4. 文档自动摘要

4.1 自动摘要的python实现

chapter.txt[1]
'第一回 风雪惊变那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。只听他两片梨花木板碰了几下,左手中竹棒在一面小羯鼓上敲起得得连声。唱道:“小桃无主自开花,烟草茫茫带晚鸦。几处败垣围故井,向来一一是人家。”那说话人将木板敲了几下,说道:“这首七言诗,,.......”颜烈道:“既有姓”包惜弱点了点头,道:“相公可别太多花费了。”颜烈微笑道:“就可惜娘子在服丧,不能戴用珠宝,要多花钱也花不了。’
#将句子以。!?分开,并转化为表格
def cut_sentence(intxt):  delimiters = frozenset('。!?')  buf = []  for ch in intxt:  buf.append(ch)  if delimiters.__contains__(ch):  yield ''.join(buf)  buf = []  if buf:  yield ''.join(buf)
sentdf = pd.DataFrame(cut_sentence(chapter.txt[1]))
sentdf
0
0 第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。
1 只听他两片梨花木板碰了几下,左手中竹棒在一面小羯鼓上敲起得得连声。
2 唱道:“小桃无主自开花,烟草茫茫带晚鸦。
3 几处败垣围故井,向来一一是人家。
4 ”  那说话人将木板敲了几下,说道:“这首七言诗,说的是兵火过后,原来的家家户户,都变成了断...
... ...
908 包惜弱想要他另要一间客房,却又不知如何启齿才好,脸上一阵红一阵白,心事重重。
909 过了一会,颜烈道:“娘子请自宽便,小人出去买了物品就回。
910 ”包惜弱点了点头,道:“相公可别太多花费了。
911 ”颜烈微笑道:“就可惜娘子在服丧,不能戴用珠宝,要多花钱也花不了。
912

913 rows × 1 columns

# 去除过短的句子,避免摘要出现无意义的内容
sentdf['txtlen'] = sentdf[0].apply(len)
sentlist = sentdf[0][sentdf.txtlen > 20]
print(len(sentlist))
sentlist
5830             第一回 风雪惊变      那说话人五十来岁年纪,一件青布长袍早洗得褪成了蓝灰带白。
1                      只听他两片梨花木板碰了几下,左手中竹棒在一面小羯鼓上敲起得得连声。
4      ”  那说话人将木板敲了几下,说道:“这首七言诗,说的是兵火过后,原来的家家户户,都变成了断...
5                         小人刚才说到那叶老汉一家四口,悲欢离合,聚了又散,散了又聚。
6      他四人给金兵冲散,好容易又再团聚,欢天喜地地回到故乡卫州,却见房屋已给金兵烧得干干净净,无可......
907                          漱洗罢,颜烈与包惜弱一起吃了些点心,两人相对坐在房中。
908               包惜弱想要他另要一间客房,却又不知如何启齿才好,脸上一阵红一阵白,心事重重。
909                         过了一会,颜烈道:“娘子请自宽便,小人出去买了物品就回。
910                               ”包惜弱点了点头,道:“相公可别太多花费了。
911                    ”颜烈微笑道:“就可惜娘子在服丧,不能戴用珠宝,要多花钱也花不了。
Name: 0, Length: 583, dtype: object
 # 将文本中的词语转换为词频矩阵
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformertxtlist = [ " ".join(jieba.lcut(w)) for w in sentlist]vectorizer = CountVectorizer()
X = vectorizer.fit_transform(txtlist)
Building prefix dict from the default dictionary ...
Dumping model to file cache C:\Users\lenovo\AppData\Local\Temp\jieba.cache
Loading model cost 0.758 seconds.
Prefix dict has been built successfully.
#转为tfidf矩阵
tfidf_matrix = TfidfTransformer().fit_transform(X)
# 利用nx包实现pagerank算法
import networkx as nx  similarity = nx.from_scipy_sparse_matrix(tfidf_matrix * tfidf_matrix.T)
scores = nx.pagerank(similarity)
scores#算出每个句子的分值,越大,越适合做摘要
{0: 0.0010912193346531665,1: 0.0010514692451123236,2: 0.0016169794514779936,3: 0.0013256313810434896,......579: 0.0022975642232750905,580: 0.0027147294491056168,581: 0.0016757809711476844,582: 0.0017710726716536757}
#按得分值进行由高到低排序
tops = sorted(scores.items(), key = lambda x: x[1], reverse = True)
tops[:3]
[(104, 0.003887937743683278),(440, 0.0035158614971836305),(442, 0.0034495123422054637)]
#显示出分值最高的前3列的内容
print(sentlist.iloc[tops[0][0]])
print(sentlist.iloc[tops[1][0]])
sentlist.iloc[tops[2][0]]
”郭啸天道:“自己兄弟,说什么还请不还请?
杨铁心再是一箭,射死了武官,抢将过去,只见那女子在地下挣扎着坐起身来,正是自己妻子。'”包惜弱道:“在前面,给……给官兵捉去啦!'
#取出前五列,按照......将其拼接
topn = 5
topsent = sorted(tops[:topn])abstract = ''
for item in topsent:abstract = abstract + sentlist.iloc[item[0]] + "......"
abstract[:-6]#去除最后六个字符的省略号
'”郭啸天道:“自己兄弟,说什么还请不还请?......杨铁心提起铁枪要出屋助战,郭啸天一把拉住,低声道:“道长叫咱们别出去。......杨铁心再是一箭,射死了武官,抢将过去,只见那女子在地下挣扎着坐起身来,正是自己妻子。......”包惜弱道:“在前面,给……给官兵捉去啦!......这时颜烈已走出房去,包惜弱问道:“这是什么?'

文本挖掘系列已经更完,还有一些地方需要后续更新完善。

文本挖掘学习笔记(三):文档相似度、文档分类和情感分析相关推荐

  1. Mongodb使用学习笔记(三)

    文章目录 Mongodb使用学习笔记(三) 1. MongoDB 更新文档 1.1 update() 1.2 save() Mongodb使用学习笔记(三) 1. MongoDB 更新文档 参考:Mo ...

  2. Spring框架学习笔记(三)(AOP,事务管理)

    Spring框架学习笔记(三) 九.AOP 9.1 AOP的注解配置 (1) 新建计算器核心功能(模拟:不能在改动核心代码) (2) 建立一个普通的Java类写增强代码(面向切面编程),使用Sprin ...

  3. 【AngularJs学习笔记三】Grunt任务管理器

    为什么80%的码农都做不了架构师?>>>    #0 系列目录# AngularJs学习笔记 [AngularJs学习笔记一]Bower解决js的依赖管理 [AngularJs学习笔 ...

  4. java学习笔记(三):前端miniUI控件库入门

    java学习笔记(三):前端miniUI控件库入门 最近在一家公司实习学习,一上来就需要学习了解相关的前端内容--miniUI.而这个内容自己本身并没有了解学习过,上手也是遇到了不少的问题,于是想把自 ...

  5. Hive学习笔记三之函数操作

    文章目录 5 函数 5.1 系统内置函数 5.2 常用内置函数 5.2.1 空字段赋值 5.2.2 CASE WHEN THEN ELSE END(类似于java中的switch case) 5.2. ...

  6. J2EE学习笔记三:EJB基础概念和知识 收藏

    J2EE学习笔记三:EJB基础概念和知识 收藏 EJB正是J2EE的旗舰技术,因此俺直接跳到这一章来了,前面的几章都是讲Servlet和JSP以及JDBC的,俺都懂一些.那么EJB和通常我们所说的Ja ...

  7. tensorflow学习笔记(三十二):conv2d_transpose (解卷积)

    tensorflow学习笔记(三十二):conv2d_transpose ("解卷积") deconv解卷积,实际是叫做conv_transpose, conv_transpose ...

  8. Ethernet/IP 学习笔记三

    Ethernet/IP 学习笔记三 原文为硕士论文: 工业以太网Ethernet/IP扫描器的研发 知网网址: http://kns.cnki.net/KCMS/detail/detail.aspx? ...

  9. iView学习笔记(三):表格搜索,过滤及隐藏列操作

    iView学习笔记(三):表格搜索,过滤及隐藏某列操作 1.后端准备工作 环境说明 python版本:3.6.6 Django版本:1.11.8 数据库:MariaDB 5.5.60 新建Django ...

  10. 吴恩达《机器学习》学习笔记三——多变量线性回归

    吴恩达<机器学习>学习笔记三--多变量线性回归 一. 多元线性回归问题介绍 1.一些定义 2.假设函数 二. 多元梯度下降法 1. 梯度下降法实用技巧:特征缩放 2. 梯度下降法的学习率 ...

最新文章

  1. 计算机教授技术追踪劫匪,打脸 911警察
  2. redis(19)--事务
  3. Python 算法之递归与尾递归,斐波那契数列以及汉诺塔的实现
  4. 结构体变量和结构体指针变量作为函数参数传递问题
  5. 解决宿主机Ping不通虚拟机的问题
  6. postgresql如何让主键自增
  7. python画科赫雪花
  8. maven-3.5.3通过eclipse打包问题(1)
  9. 【LeetCode】【字符串】题号:*537. 复数乘法
  10. Ubuntu16.04 安装国内版火狐浏览器,同步标签
  11. 超出部分点点点,并修改点点点颜色
  12. 开源硕士毕业论文算法
  13. html页分割线最简单的实现方式
  14. css代码文字破碎js特效
  15. 关于音频情感分类的随笔(5)
  16. Win系统 - Windows10 该内存不能为 read
  17. Home Assistant系列 -- 接入手机摄像头做实时监控和人脸识别
  18. Content Delivery Networks CDN 内容分发网络
  19. 多线程与 “锁”
  20. java中stu是啥,Java 面试:对象克隆

热门文章

  1. 计算机科学与技术到底学什么?
  2. Proteus 8.6 SP2 Pro 汉化破解版(附破解文件+汉化包+安装教程) 兼容win10
  3. 40家重污染行业上市公司进“黑名单”
  4. Matlab数据拟合-----使用polyfit 和polyval函数
  5. 锁卡,每插入一张新卡都需要进行解锁
  6. B03 - 037、cd
  7. 淘宝直通车补单方法技巧 短期打造爆款
  8. python图像识别教程pdf_如何使用Python进行PDF图片识别OCR
  9. Helix QAC 2021.1
  10. linux的pcan驱动安装