马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
第2关:基于 K-Means 算法的文本聚类
任务描述
本关任务:根据本关所学有关文本聚类的知识,编写基于 K-Means 算法的文本聚类并通过所有测试用例。
相关知识
为了完本钱关任务,你必要掌握:
文本聚类的思想;
使用 K-Means 算法举行文本聚类。
机器学习与 NLP
机器学习是一门多范畴交织学科,涉及概率论、统计学、迫近论等多门学科,专门研究盘算机怎样模拟或实现人类的学习举动,以获取新的知识或技能,重新构造已有的知识布局使之不断改善自身的性能。
而天然语言处理作为人工智能范畴的一部分,机器学习算法在人工智能范畴得到了很好的应用。此中,文本聚类即使一个很典型的例子,本实训将以文本聚类为例,先容机器学习在天然语言处理范畴的现实应用。
文本聚类
聚类又称群分析,是数据挖掘的一种紧张的思想,聚类分析是由若干模式构成的,通常,模式是一个度量的向量,或者是多维空间中的一个点。聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性。
文本聚类则聚类是在文本方向上的应用,首先我们要把一个个文档的天然语言转换成数学信息,这样形成高维空间点之后再去盘算点与点之间的隔断,然后将这些隔断比较近的聚成一个簇,这些簇的中央成为簇心。而我们做的就是包管簇内点的隔断足够近,簇与簇的隔断足够远。
1、分词处理
我们要把中文文章要举行分词,这一点中文文章和英文文章有一些区别,由于英文单词是单个构成的,也就不必要分词了,而中文是必要分词的,并且中文之间有一些词尽管大量出现,但是对于文章的分类布局起不到太大的意义,比如“的”、“了”等等,因此,首先我们就加入一个停用词表,在举行分词的时间举行去掉。
2、分词后将分词转换为词向量
关于词向量我们有一些比较常用的模型,比如 BOW 词袋模型,一连词袋模型( CBOW )和 Skip-Gram 模型等等,在本实训中我们使用的是 BOW 词袋模型,在转换为词向量值时,我们要将其转换成 tf-idf 矩阵, tf-idf 其实可以看作是对提取的特性的一次加权,是根据一个单词在当前文章中出现的频率和该单词在所有语料中出现的频率评估一个单词的紧张性,当一个单词在这篇文章中出现的次数很多的时间,这个词语更加紧张;但假如它在所有文章中出现的次数都很多,那么它就显得不那么紧张。
3、选择聚类算法
常用的聚类算法有 K-means 、 DBSCAN 和 LDA ,这几种算法用的最多,但在高维空间里中 K-means 并不是很好,究其原因是由于维度太高,簇与簇之间的隔断太小了,假如直接去聚类,这一部分似乎效果不太好,这时间就必要用到主成分分析 PCA ,大致的思路是大致意思就是取这个高维向量中方差最大的方向颠末一些数学变换将有效的部分生存,没用的部分舍弃,这种办法同样适合分类算法中寻找最大的特性。
- import jieba
- from sklearn.feature_extraction.text import CountVectorizer
- from sklearn.feature_extraction.text import TfidfTransformer
- from sklearn.cluster import KMeans
- class KmeansClustering():
- def __init__(self, stopwords_path=None):
- self.stopwords = self.load_stopwords(stopwords_path)
- self.vectorizer = CountVectorizer()
- self.transformer = TfidfTransformer()
- def load_stopwords(self, stopwords=None):
- # 加载停用词
- if stopwords:
- with open(stopwords, 'r', encoding='utf-8') as f:
- return [line.strip() for line in f]
- else:
- return []
- def preprocess_data(self, corpus_path):
- # 文本预处理,每行一个文本
- corpus = []
- with open(corpus_path, 'r', encoding='utf-8') as f:
- for line in f:
- corpus.append(' '.join([word for word in jieba.lcut(line.strip()) if word not in self.stopwords]))
- return corpus
- def get_text_tfidf_matrix(self, corpus):
- # 获取tfidf矩阵
- tfidf = self.transformer.fit_transform(self.vectorizer.fit_transform(corpus))
- # 获取tfidf矩阵中权重
- weights = tfidf.toarray()
- return weights
- def kmeans(self, corpus_path, n_clusters=2):
- """
- KMeans文本聚类
- :param corpus_path: 语料路径(每行一篇),文章id从0开始
- :param n_clusters: :聚类类别数目
- :return: {cluster_id1:[text_id1, text_id2]}
- """
- corpus = self.preprocess_data(corpus_path)
- weights = self.get_text_tfidf_matrix(corpus)
- result = {}
- #任务:完成基于K-Means算法的文本聚类,并将结果保存到result变量中。
- # ********** Begin *********#
- clf = KMeans(n_clusters=n_clusters)
- result = clf.fit_predict(weights)
- # ********** End **********#
- return result
复制代码 第3关:基于 DBSCAN 的文本聚类
任务描述
本关任务:根据本关所学有关 DBSCAN 文本聚类的知识,编写基于 DBSCAN 算法的文本聚类并通过所有测试用例。
相关知识
为了完本钱关任务,你必要掌握:
DBSCAN 聚类的思想;
使用 DBSCAN 算法举行文本聚类。
DBSCAN 聚类简介
DBSCAN 属于密度聚类算法,该算法通过在样本空间中不断搜索最大聚集完成聚类,能够在带有噪点的样本空间中发现任意外形的聚类并清除噪点。DBSCAN 算法不必要预先指定聚类数目,但对用户设定的参数非常敏感。当空间聚类的密度不均匀、聚类间距差相差很大时,聚类质量较差。
DBSCAN 的基本假设是一个集群的密度要明显高于噪声点的密度。因此,其基本思想是对于集群中的每一个点,在给定的半径范围内,相邻点的数目必须凌驾预先设定的某一个阈值。DBSCAN 算法中包含两个紧张的参数:
eps:聚类类别中样本的相似度衡量,与类别内样本相似度成反比。可以理解为同一个类别当中,对两个样本之间隔断的最大值限定;
min_samples:每个聚类类别中的最小样本数,会对未分类样本数目造成影响,与未分类样本数目成正比。当相似样本数目少于该参数时,不会聚到一起。
在现实应用过程中,根据样本的大小,以及样本的大致分布,相识聚类结果会随着这两个参数怎样变化之后,可以根据自己的经验对两个参数举行调整。只有两个模型参数必要调整,因此调参过程也不会太贫苦。
第4关:基于机器学习的情绪分析
任务描述
本关任务:根据所学知识,完成右侧对应的练习题。
相关知识
为了完本钱关任务,你必要掌握:
基于机器学习的情绪分析算法思想;
基于机器学习的情绪分析算法实现。
基于机器学习的情绪分析简介
现在,情绪倾向分析的方法主要分为两类:一种是基于情绪辞书的方法;一种是基于机器学习的方法,如基于大规模语料库的机器学习。前者必要用到标注好的情绪辞书,英文的辞书有很多,中文主要有知网整理的情绪辞书 Hownet 和台湾大学整理发布的 NTUSD 两个情绪辞书,还有哈工大信息检索研究室开源的《同义词词林》可以用于情绪辞书的扩充。基于机器学习的方法则必要大量的人工标注的语料作为练习集,通过提取文本特性,构建分类器来实现情绪的分类。
机器学习的方法精确度更高,由于辞书匹配会由于语义表达的丰富性而出现很大误差,而机器学习方法不会。而且 它可使用的场景更多样。无论是主客观分类还是正负面情绪分类,机器学习都可以完成任务。而无需像辞书匹配那 样要深入到词语、句子、语法这些层面。
而辞书方法适用的语料范围更广,无论是手机、电脑这些商品,还是书评、影评这些语料,都可以适用。但机器学 习则极度依赖语料,把手机语料练习出来的的分类器拿去给书评分类,那是注定要失败的。使用机器学习举行情绪分析,可以换一个类似意思的说法,就是用有监视的(必要人工标注类别)机器学习方法来 对文本举行分类。
这点与辞书匹配有着本质的区别。辞书匹配是直接盘算文本中的情绪词,得出它们的情绪倾向分值。而机器学习方法的思路是先选出一部分表达积极情绪的文本和一部分表达消极情绪的文本,用机器学习方法举行练习,获得一个情绪分类器。再通过这个情绪分类器对所有文本举行积极和消极的二分分类。终极的分类可以为文本给出0或1这样的类别,也可以给出一个概率值,比如这个文本的积极概率是90%,消极概率是10%。
基于机器学习的情绪分析算法实现
1、准备数据集
先以带有正向标签和负向标签的评论语料作为练习集用以练习分类器,剩余带有正向标签和负向标签的评论语料作为测试集测试差别分类算法、差别特性提取方法、差别维度的正确度。
最后选择正确度最高的方案,将上述带有正向标签和负向标签的评论语料作为练习集练习终极存储的分类器。
2、对语料举行分词
使用 python 步调包中文分词工具 python 对语料举行分词。
3、特性提取
提取语料中的文本特性。
4、特性选择
在盘算整个语料里面所有的信息量后,根据信息量举行倒序排序,选择排名靠前的信息量的词,把选出的这些词作为特性。
5、分割数据及赋予类标签
对数据集举行处理,给数据贴上标签。
6、练习模型
使用练习集用差别的分类算法练习分类器,用分类器对开发测试集里面的数据举行分类,给出分类预测的标签, 对比分类标签和人工标注的差别,盘算出正确度。
7、选择分类器并存储
在完成机器学习的练习后,我们必要将分类器举行存储,以便后续的使用。
- import xlwt
- import pickle
- import itertools
- import nltk
- import os
- import sklearn
- from nltk.collocations import BigramCollocationFinder
- from nltk.metrics import BigramAssocMeasures
- from nltk.probability import FreqDist, ConditionalFreqDist
- from nltk.classify.scikitlearn import SklearnClassifier
- from sklearn.svm import SVC, LinearSVC, NuSVC
- from sklearn.naive_bayes import MultinomialNB, BernoulliNB
- from sklearn.linear_model import LogisticRegression
- from sklearn.metrics import accuracy_score
- pos_f = 'src/step3/pkl_data/1000/pos_review.pkl'
- neg_f = 'src/step3/pkl_data/1000/neg_review.pkl'
- def load_data(): # 加载训练集数据
- global pos_review, neg_review
- pos_review = pickle.load(open(pos_f, 'rb'))
- neg_review = pickle.load(open(neg_f, 'rb'))
- def create_word_bigram_scores(): # 计算整个语料里面每个词和双词搭配的信息量
- posdata = pickle.load(open(pos_f, 'rb'))
- negdata = pickle.load(open(neg_f, 'rb'))
- posWords = list(itertools.chain(*posdata))
- negWords = list(itertools.chain(*negdata))
- bigram_finder = BigramCollocationFinder.from_words(posWords)
- posBigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 5000)
- bigram_finder = BigramCollocationFinder.from_words(negWords)
- negBigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 5000)
- pos = posWords + posBigrams # 词和双词搭配
- neg = negWords + negBigrams
- word_fd = FreqDist()
- cond_word_fd = ConditionalFreqDist()
- for word in pos:
- word_fd[word] += 1
- cond_word_fd["pos"][word] += 1
- for word in neg:
- word_fd[word] += 1
- cond_word_fd["neg"][word] += 1
- pos_word_count = cond_word_fd['pos'].N()
- neg_word_count = cond_word_fd['neg'].N()
- total_word_count = pos_word_count + neg_word_count
- word_scores = {}
- for word, freq in word_fd.items():
- pos_score = BigramAssocMeasures.chi_sq(cond_word_fd['pos'][word], (freq, pos_word_count), total_word_count) # 计算积极词的卡方统计量,这里也可以计算互信息等其它统计量
- neg_score = BigramAssocMeasures.chi_sq(cond_word_fd['neg'][word], (freq, neg_word_count), total_word_count)
- word_scores[word] = pos_score + neg_score
- return word_scores
- def find_best_words(word_scores, number): # 根据信息量进行倒序排序,选择排名靠前的信息量的词
- best_vals = sorted(word_scores.items(), key=lambda w_s: w_s[1], reverse=True)[:number] # 把词按信息量倒序排序。number是特征的维度,是可以不断调整直至最优的
- best_words = set([w for w, s in best_vals])
- return best_words
- def pos_features(feature_extraction_method): # 赋予积极的文本类标签
- posFeatures = []
- for i in pos_review:
- posWords = [feature_extraction_method(i), 'pos'] # 为积极文本赋予"pos"
- posFeatures.append(posWords)
- return posFeatures
- def neg_features(feature_extraction_method): # 赋予消极的文本类标签
- negFeatures = []
- for j in neg_review:
- negWords = [feature_extraction_method(j), 'neg'] # 为消极文本赋予"neg"
- negFeatures.append(negWords)
- return negFeatures
- def best_word_features(words): # 把选出的这些词作为特征(这就是选择了信息量丰富的特征)
- global best_words
- return dict([(word, True) for word in words if word in best_words])
- def score(classifier):
- # 任务:构建分类器模型并进行训练
- # ********** Begin *********#
- def store_classifier():
- load_data()
- word_scores = create_word_bigram_scores()
- global best_words
- best_words = find_best_words(word_scores, 7500)
- posFeatures = pos_features(best_word_features) # 选出积极的语料
- negFeatures = neg_features(best_word_features) # 选出负面的语料
- trainSet = posFeatures + negFeatures # 创建训练集
- MultinomialNB_classifier = SklearnClassifier(MultinomialNB()) # 构建分类器
- MultinomialNB_classifier.train(trainSet) # 训练分类器
- pickle.dump(MultinomialNB_classifier, open('../out/classifier.pkl', 'wb')) # 保存分类器
- # ********** End **********#
- pred = classifier.classify_many(dev) # 对开发测试集的数据进行分类,给出预测的标签
- return accuracy_score(tag_dev, pred) # 对比分类预测结果和人工标注的正确结果,给出分类器准确度
- # 使用测试集测试分类器的最终效果
- def use_the_best():
- word_scores = create_word_bigram_scores() # 使用词和双词搭配作为特征
- best_words = find_best_words(word_scores, 4000) # 特征维度1500
- load_data()
- posFeatures = pos_features(best_word_features, best_words)
- negFeatures = neg_features(best_word_features, best_words)
- cut_data(posFeatures, negFeatures)
- trainSet = posFeatures[1500:] + negFeatures[1500:] # 使用了更多数据
- testSet = posFeatures[:500] + negFeatures[:500]
- test, tag_test = zip(*testSet)
- # 存储分类器
- def final_score(classifier):
- classifier = SklearnClassifier(classifier)
- classifier.train(trainSet)
- pred = classifier.classify_many(test)
- return accuracy_score(tag_test, pred)
- print(final_score(MultinomialNB())) # 使用开发集中得出的最佳分类器
- # 把分类器存储下来(存储分类器和前面没有区别,只是使用了更多的训练数据以便分类器更为准确)
- def store_classifier():
- load_data()
- word_scores = create_word_bigram_scores()
- global best_words
- best_words = find_best_words(word_scores, 7500)
- posFeatures = pos_features(best_word_features)
- negFeatures = neg_features(best_word_features)
- trainSet = posFeatures + negFeatures
- MultinomialNB_classifier = SklearnClassifier(MultinomialNB())
- MultinomialNB_classifier.train(trainSet)
- pickle.dump(MultinomialNB_classifier, open('src/step3/out/classifier.pkl', 'wb'))
-
复制代码 以上内容仅供本人学习参考
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |