10.新闻语料分类

# -*- coding: utf-8 -*-
"""
Created on Mon Oct  8 16:41:10 2018

@author: asus
"""
#10 新闻语料分类

#10.1 获取新闻文章
#本章将构建一个按照主题为最新的新闻报道分组的系统。你可以运行几周(或更长时间)以了解这
#段时间新闻趋势的变化。
#http://www.reddit.com/login

#找不到

#跳过

#10.3 新闻语料聚类
#无监督学习,聚类
#k-means
from sklearn.cluster import KMeans
#TfidfVectorizer这个向量化工具根据词语出现在多少篇文档中,对词语计数进行加权。出现在
#较多文档中的词语权重较低
from sklearn.feature_extraction.text import TfidfVectorizer
#创建数据分析流水线
from sklearn.pipeline import Pipeline
n_clusters = 10
pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),
                     ('clusterer', KMeans(n_cluster=n_clusters))])
#参数max_df设置了0.4,表示忽略出现在40%及以上的文档中的词语。
#训练算法,然后再用它来做预测。
pipeline.fit(documents)
labels = pipeline.predict(documents)
#我们可以使用Counter类来查看每个簇有多少数据点
from collections import Counter
c = Counter(labels)
for cluster_number in range(n_clusters):
    print("Cluster {} contains {} samples".format(cluster_number, 
          c[cluster_number]))

#103.2 评估结果
pipeline.named_steps['clusterer'].inertia_
#对于k-means算法,寻找新质点的标准是,最小化每个数据点到最近置信点的距离。这叫算法的惯
#性权重(inertia),它可以用来确定分多少簇合适。
#下面代码n_clusters依次取2到20之间的值,每取一个值,k-means算法运行10次,每次算法都
#记录惯性权重。
inertia_scores = []
n_cluster_values = list(range(2, 20))
for n_clusters in n_cluster_values:
    cur_inertia_scores = []
    X = TfidfVectorizer(max_df=0.4).fit_transform(documents)
    for i in range(10):
        km = KMeans(n_clusters=n_clusters).fit(X)
        cur_inertia_scores.append(km.inertia_)
    inertia_scores.append(cur_inertia_scores)
#变量inertia_scores存储了n_clusters取2到20每个值所对应的惯性权重。把惯性权重和簇的
#数量做出图。
#整体的趋势为某某时,惯性权重进行了最后一次大的调整随后惯性权重的改变很小。
n_clusters = 6
pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),
                     ('clusterer', KMeans(n_cluster=n_clusters))])
pipeline.fit(documents)
labels = pipeline.predict(documents)

#10.3.3 从簇中抽取主体信息
#从特征提取这一步抽取词表
terms = pipeline.named_steps['feature_extraction'].get_feature_names()
#计算每簇所包含的个体数量
c = Counter(labels)
#遍历所有的簇,输出每簇所包含的个体数量
for cluster_number in range(n_clusters):
    print("Cluster {} contains {} samples".format(cluster_number, 
          c[cluster_number]))
#接下来(在循环体内部),遍历该簇最重要的词语。首先,从质心点找出特征值最大的5个特征。
    print(" Most important terms")
    centroid = pipeline.named_steps['clusterer'].cluster_centers_[cluster_number]
    most_important = centroid.argsort()
    #依次输出这5个特征
    for i in range(5):
        term_index = most_important[-(i+1)]
        print(" {0}) {1} (score: {2:.4f})".format(i+1, terms[term_index],
             centroid[term_index]))

#10.3.4 用聚类算法做转换器
X = pipeline.transform(documents)

#10.4 聚类融合

#10.4.1 证据累积
#最基本的融合方法是对数据进行多次聚类,每次都记录各个数据点的簇标签。然后计算每两个数
#据点被分到同一个簇的次数。这就是证据累积算法(EAC)。

from scipy.sparse import csr_matrix   #稀疏矩阵
def create_coassociation_matrix(labels):
    rows = []
    cols = []
    unique_labels = set(labels)
    for label in unique_labels:
        indices = np.where(labels == label)[0]
        for index1 in indices:
            for index2 in indices:
                rows.append(index1)
                cols.append(index2)
    #在所有循环的外面创建数据集,两个数据点标签相同时,数据集中该位置的值为1。
    data = np.ones((len(rows),))
    return csr_matrix((data, (rows, cols)), dtype='float')
#调用上述函数,传入所有的数据点标签,就能得到共协矩阵。
C = create_coassociation_matrix(labels)
#我们可以把这些矩阵的多个实例结合起来,多次运行k-means算法,把结果结合起来看。
#下一步对共协矩阵进行分级聚类。我们需要找到该矩阵的最小生成树,删除权重低于阈值的边。
#最小生成树(MST)即总权重最低的生成树。
from scipy.sparse.csgraph import minimum_spanning_tree #计算MST
mst = minimum_spanning_tree(C)
#然而,矩阵C中,值越高表示一组数据点被分到同一簇的次数越多——这个值表示相似度。相反,该
#函数的输入为距离,高的值表示相似度越小。因此,我们对C取反再计算最小生成树。
mst = minimum_spanning_tree(-C)
#然后我们删除其边的权重小于阈值的节点。仅对共协矩阵(值为1或0,没有什么可处理的)进行一
#次遍历无法完成上述任务。因此,我们创建额外的标签,创建一个新共协矩阵,然后把这两个矩
#阵相加。
pipeline.fit(documents)
labels2 = pipeline.predict(documents)
C2 = create_coassociation_matrix(labels2)
C_sum = (C + C2) / 2
#然后再计算MST,删除在这两个矩阵中都没有出现的边。
mst = minimum_spanning_tree(-C_sum)
mst.data[mst.data > -1] = 0
#最后,我们找到所有的连通分支,也就是寻找移除低权重的边以后仍然连接在一起的节点。返回
#的第一个值为连通分支的数量(也就是有多少个簇),第二个值为每个数据点的标签。
from scipy.sparse.csgraph import connected_components
number_of_clusters, labels = connected_components(mst)

#10.4.3 实现
#我们把前面的整合起来
from sklearn.base import BaseEstimator, ClusterMixin
class ECA(BaseEstimator, ClusterMixin):
    def __init__(self, n_clusterings=10, cut_threshold=0.5, n_clusters_range=(3, 10)):
        self.n_clusterings = n_clusterings
        self.cut_threshold = cut_threshold
        self.n_clusters_range = n_clusters_range
    def fit(self, X, y=None):
        C = sum((create_coassociation_matrix(self._single_clustering(X))for i in range(self.n_clusterings)))
        mst = minimum_spanning_tree(-C)
        mst.data[mst.data > -self.cut_threshold] = 0
        self.n_componments, self.labels_ = connected_components(mst)
        return self
    def _single_clustering(self, X):
        n_clusters = np.random.randint(*self.n_clusters_range)
        km = KMeans(n_clusters=n_clusters)
        return km.fit_predict(X)
pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),
                     ('clusterer', ECA())])
        
#10.5 线上学习
#线上学习指用新数据增量地改进模型,支持线上学习的算法可以先用一条或少量数据进行训练,
#随着更多新数据的添加,更新模型。相比之下,不支持线上学习的算法在开始训练之前需要一次
#性拿到所有数据。标准k-means算法以及前几章的绝大多数算法都不支持线上学习。
    
#10.5.2 实现
#从数据集中抽取特征,创建矩阵X
from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidVectorizer(max_df=0.4)
X = vec.fit_transform(documents)
#再导入MiniBatchKMeans,初始化一个实例。
from sklearn.cluster import MiniBatchKMeans
mbkm = MiniBatchKMeans(random_state=14, n_clusters=3)
#接着,随机从X矩阵中选择数据,模拟来自外部的新数据。每次去一些新数据,更新模型。
batch_size = 10
for iteration in range(int(X.shape[0] / batch_size)):
    start = batch_size * iteration
    end = batch_size * (iteration + 1)
    mbkm.partial_fit(X[start:end])
#在实例上电泳predict()方法,获取原始数据集的聚类结果
labels = mbkm.predict(X)

#创建自己的能够支持线上学习的流水线子类。
class PartialFitPipeline(Pipeline):
    def partial_fit(self, X, y=None):
        Xt = X
        for name, transform in self.steps[:-1]:
            Xt = transform.transform(Xt)
        return self.steps[-1][1].partial_fit(Xt, y=y)
pipeline = PartialFitPipeline([('feature_extraction', HashingVectorizer()),
                               ('clusterer', MiniBatchKMeans(random_state=14, 
                                                             n_clusters=3))])
batch_size = 10
for iteration in range(int(X.shape[0] / batch_size)):
    start = batch_size * iteration
    end = batch_size * (iteration + 1)
    pipeline.partial_fit(X[start:end])
labels = pipeline.predict(documents)


你可能感兴趣的:(10,新闻语料分类,python数据挖掘入门与实践)