文本分析
1.停用词--航大、百度等停用词表
例如
符号类: !@#¥%……{} 等等
一些 一个 一切 一直 一旦 一来
- 语料中大量出现
- 没啥大用
- 留着过年吗?
2.Tf-idf:关键词提取
词频(Term Frequency,缩写为TF)统计
以《中国的蜜蜂养殖》为例
出现次数最多的词是------------‘的’,‘是’,‘在’等等常用的停用词
“中国”、“蜜蜂”、“养殖”这三个词的出现次数一样多,重要性是一样的吗?
“中国”是很常见的词,相对而言,“蜜蜂”和“养殖”不那么常见
3. 逆文档频率(Inverse Document Frequency, IDF)
如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性
词频(TF) = 某个词在文章中的出现次数 / 该文出现词的总量
逆文档频率(IDF) = log(语料库的文档总数/包含盖茨的文档数+1)
之所以+1,是为了防止分母为0 。
带有这个词的文章越稀有的情况下,IDF越大。
4.TF-IDF:关键词提取
TF-IDF = 词频(TF)X逆文档频率(IDF)
例子-数字随便举例的只是为了方便理解:
《中国的蜜蜂养殖》:假定该文长度为1000个词,“中国”、“蜜蜂”、“养殖”各出现20次,则这三个词的词频(TF)都为0.02
搜索Google发现,包含“的”字的网页共有250亿张,假定这就是中文网页总数。
包含“中国”的网页共有62.3亿张,
包含“蜜蜂”的网页为0.484亿张,
包含“养殖”的网页为0.973亿张
对比可以看出:
词组 | 包含该词的文档数(亿) | IDF | TF-IDF |
---|---|---|---|
中国 | 62.3 | 0.603 | 0.0121 |
蜜蜂 | 0.484 | 2.713 | 0.0543 |
养殖 | 0.973 | 2.410 | 0.0482 |
可以看出,TF-IDF来看,蜜蜂和养殖重要程度明显增加
5. 相似度
句子A: 我喜欢看电视,不喜欢看电影
句子B: 我不喜欢看电视,也不喜欢看电影
分词:
句子A: 我/喜欢/看/电视,不/喜欢/看/电影
句子B: 我/不/喜欢/看/电视,也/不/喜欢/看/电影
语料库:我,喜欢,看,电视,电影,不,也。
组成了一个合集
统计词频:
句子A: 我 1,喜欢2,看2,电视1,电影1,不1,也0.
句子B: 我 1,喜欢2,看2,电视1,电影1,不2,也1.
词频向量:
句子A:[1,2,2,1,1,1,0]
句子B:[1,2,2,1,1,2,1]
相似度分析:余弦相似度分析。
以上面这个为例:
结果为:
流程:
第一步:进行语料清洗,数据清洗。去掉停用词,筛选重复的话。例如:赞啊,楼主好人,留邮箱,经常出现,但是没意义。
第二步:构造向量,本文是利用词频构造向量,(太简单了,一般都是word2vec,包括Gensim这个库,词转向量的准确度是非常高的。)
第三步:调用模型,调参。
贝叶斯算法概述
贝叶斯方法源于解决一个“逆概”问题。
正向概率:假设袋子里有N个白球,M个黑球,你伸手进去摸一把,摸出黑球的概率是多大?
逆向概率: 如果我们事先并不知道袋子里黑白求的比例,而是闭着眼睛先摸球,通过观察这些取出来的球的颜色之后,我们来对袋子里面黑白求的比例来进行推测(实际生活中:事情已经发生了,我们来推测原因。)
简单来说,
现实世界本身是不确定的,人类的观察能力有局限性。
我们日常所观察到的只是事物表面上的结果,因此我们需要提供一个猜测。
拼写纠正的实例:
问题是我们看到用户输入了一个不在字典的单词,我们需要去猜测:“这个家伙到底真正想输入的单侧是什么呢?”
P(我们猜测他想输入的单词|他实际输入的单词)
假设:
用户实际输入的单词为D(D代表Data,即观测数据)
猜测1:P(h1 | D),猜测2:P(h2 | D), 猜测3: P(h3 |D)....
统一为:P(h|D)
P(h | D) = P(h)*P(D\h) |P(D)
对于不同的具体猜测h1h2h3.。,P(D)都是一样的,所以在比较P(h1 | D) 和 P(h2 | D)的时候我们可以忽略这个常数。
对于给定观测数据,一个猜测是好是坏,取决于“这个猜测本身独立的可能性大小”(先验概率,Prior) 和“这个猜测生成我们观测到数据的可能性大小。”
比如,键盘上两个字母之间的距离等。。
先验概率(人的经验):
比如用户输入了tlp,那么到底是top还是tip?这个时候,如果最大似然不能做出决定性的判断是,先验概率就可以起决定性作用。
top的出现程度比较高,所以更可能他想打的是top
(简单来说,先验概率就是,你之前是怎么做这件事,你下一次还是很大可能性任然用同样的方法。)
模型比较理论
最大似然:最符合观测数据的最具有优势。
比如:
扔一个硬币,观察到的是"正",根据最大似然估计,我们猜测这个硬币扔出“正”的概率是1.
奥卡姆剃刀: 越是高阶的多项式越是不常见。(这块是和过拟合结合起来。)
实例:新闻数据分析
数据源:搜狗实验室当中找来的。
新闻数据中的全网数据
http://www.sogou.com/labs/resource/ca.php
import pandas as pd
import jieba
#jieba分词够用了,学习用。
df_news = pd.read_table('/home/tianchi/myspace/机器学习经典算法/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna() ##把所有的缺失值去除掉。
df_news.head()
##发现里面全是广告
第一步:分词 使用结巴分词器
#jieba分词器要求的list格式,先做转换。
content = df_news.content.values.tolist()
#看一下里面都是什么内容
content[999]
#进行分词
#这个list里面存放分词后的结果
content_S =[]
for line in content:
current_segment = jieba.lcut(line) #遍历的时候进行分词
if len(current_segment)> 1 and current_segment != '\r\n': #换行符
content_S.append(current_segment)
content_S[999] #查看一下
df_content = pd.DataFrame({'content_S' : content_S})
df_content.head()
2.数据清洗,去掉停用词
停用词表随便百度一下就有,在本文最后我也会附上链接。
stopwords = pd.read_csv('/home/tianchi/myspace/机器学习经典算法/中文停用词表.txt',index_col=False, sep="\t" ,quoting=3, names=['stopword'],encoding='utf-8')
stopwords.head()
后续的方法分为很多种,当然,最简单的就是遍历,原因是因为本文重点不在于算法效率,而且data集很mini
#最简单的就是遍历
def drop_stopwords(contents,stopwords):
contents_clean = []
all_words = []
for line in contents:
line_clean = []
for word in line:
if word in stopwords:
continue
line_clean.append(word)
all_words.append(str(word))
contents_clean.append(line_clean)
return contents_clean,all_words
#print (contents_clean)
contents = df_content.content_S.values.tolist()
stopwords = stopwords.stopword.values.tolist()
contents_clean,all_words = drop_stopwords(contents,stopwords)
df_content=pd.DataFrame({'contents_clean':contents_clean})
df_content.head()
TF-IDF:提取关键词
作为学习和研究,jieba分词已经够用了,使用起来也相对比较简单。
import jieba.analyse
index = 2400
print(df_news['content'][index])
str = ''.join(content_S[index])
print(" ".join(jieba.analyse.extract_tags(str, topK=5,withWeight=False))) #topK就是返回几个关键字
topk决定了你返回几个关键词。
本段话提取了:耐克 阿迪欧洲杯 球衣 西班牙
说实话这个效果并不好,我希望的是能够提取出key值,我们不用阅读大段文字就可以获得这段文本的意思。
(这玩意可能需要后续的深度学习,这个坑暂时留在这里。)
LDA:主题模型
格式要求: list of list 形式,分词好的库作用会很大。
这里我们使用gensim这个库,非常好用。
具体的大家自行百度。
这块内容,我尽量把代码和结果附上来,以注释的形式描述自己的一些看法。
如下:
from gensim import corpora, models, similarities
import gensim
#http://radimrehurek.com/gensim/
#做映射,相当于词袋
dictionary = corpora.Dictionary(contents_clean)
corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean]
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #类似Kmeans自己指定K值
#一号分类结果
print (lda.print_topic(1, topn=5))
我们可以看到分类的结果和权重,这块几个关键词“观众”,“赛区”,大概是个比赛吧,,(效果不是很好,,我们希望能直接得出有价值的key words)
看看其他的
for topic in lda.print_topics(num_topics=20, num_words=5):
print (topic[1])
就那样吧。。。
还是得进行进一步处理
我们需要把数据处理成为sklearn能用的数据,在这里label用到了先验理论,可以参考KNN, K值能确定,我们的结果越准确。。
比如这里分类:汽车,财经,科技,,,
同时需要把这个转化。。类似one-hot。。对应成为计算机可以理解的语言。
代码如下:
df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
df_train.tail()
df_train.label.unique()
label_mapping = {"汽车": 1, "财经": 2, "科技": 3, "健康": 4, "体育":5, "教育": 6,"文化": 7,"军事": 8,"娱乐": 9,"时尚": 0}
df_train['label'] = df_train['label'].map(label_mapping)
df_train.head()
接下来,我们使用sklearn进行模型计算
第一步:划分测试集和训练集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)
##listoflist的格式,需要list转str
words = []
for line_index in range(len(x_train)):
try:
#x_train[line_index][word_index] = str(x_train[line_index][word_index])
words.append(' '.join(x_train[line_index]))
except:
print (line_index,word_index)
words[0]
注意的是,这块因为库的格式问题,需要添加一步,list转str
第二步,导入sklearn中的TFIDF库
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(analyzer='word', max_features=4000, lowercase = False)
vectorizer.fit(words)
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words), y_train)
classifier.score(vectorizer.transform(test_words), y_test)
0.81的准确率,其实并不高,但是作为这块模型介绍。已经够用了。
后面我还会对这块进行优化。
也欢迎各位读者留下您宝贵的建议和想法。
祝好!
Panbo
26082019