机器学习07-(中文分词、样本类别均衡化、置信概率、k-means聚类算法、均值漂移聚类算法)

机器学习-07

中文分词(jieba)

https://github.com/fxsjy/jieba

样本类别均衡化

上采样与下采样处理样本类别均衡化

下采样:把样本数据量大的那一类样本减少到与数据量小的那一类样本数量相近。

上采样:把样本数据量小的那一类样本增加到与数据量大的那一类样本数量相近。

通过类别权重的均衡化,使所占比例较小的样本权重较高,而所占比例较大的样本权重较低,以此平均化不同类别样本对分类模型的贡献,提高模型性能。

样本类别均衡化相关API:

model = svm.SVC(kernel='linear', class_weight='balanced')
还可以这么写:class_weight={0:0.9, 1:0.1}


model.fit(train_x, train_y)

案例:修改线性核函数的支持向量机案例,基于样本类别均衡化读取imbalance.txt训练模型。

... ...
... ...
data = np.loadtxt('../data/imbalance.txt', delimiter=',', dtype='f8')
x = data[:, :-1]
y = data[:, -1]
train_x, test_x, train_y, test_y = \
    ms.train_test_split(x, y, test_size=0.25, random_state=5)
# 基于线性核函数的支持向量机分类器
model = svm.SVC(kernel='linear', class_weight='balanced')
model.fit(train_x, train_y)
... ...
... ...

LR  SVM  NB  Tree

置信概率

根据样本与分类边界的距离远近,对其预测类别的可信程度进行量化,离边界越近的样本,置信概率越低,反之,离边界越远的样本,置信概率高。

获取每个样本的置信概率相关API:

# 在获取模型时,给出超参数probability=True
model = svm.SVC(kernel='rbf', C=600, gamma=0.01, probability=True)
预测结果 = model.predict(输入样本矩阵)
# 调用model.predict_proba(样本矩阵)可以获取每个样本的置信概率矩阵
置信概率矩阵 = model.predict_proba(输入样本矩阵)

置信概率矩阵格式如下:

类别1类别2
样本10.80.2
样本20.90.1
样本30.50.5

聚类模型

分类(class)与聚类(cluster)不同,分类是有监督学习模型,聚类属于无监督学习模型。聚类讲究使用一些算法把样本划分为n个群落。一般情况下,这种算法都需要计算欧氏距离。

欧氏距离即欧几里得距离。
P ( x 1 ) − Q ( x 2 ) : ∣ x 1 − x 2 ∣ = ( x 1 − x 2 ) 2 P ( x 1 , y 1 ) − Q ( x 2 , y 2 ) : ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 P ( x 1 , y 1 , z 1 ) − Q ( x 2 , y 2 , z 2 ) : ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 + ( z 1 − z 2 ) 2 P(x_1) - Q(x_2): |x_1-x_2| = \sqrt{(x_1-x_2)^2} \\ P(x_1,y_1) - Q(x_2,y_2): \sqrt{(x_1-x_2)^2+(y_1-y_2)^2} \\ P(x_1,y_1,z_1) - Q(x_2,y_2,z_2): \sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2} \\ P(x1)Q(x2):x1x2=(x1x2)2 P(x1,y1)Q(x2,y2):(x1x2)2+(y1y2)2 P(x1,y1,z1)Q(x2,y2,z2):(x1x2)2+(y1y2)2+(z1z2)2
用两个样本对应特征值之差的平方和之平方根,即欧氏距离,来表示这两个样本的相似性。

K均值算法

第一步:随机选择k个样本作为k个聚类的中心,计算每个样本到各个聚类中心的欧氏距离,将该样本分配到与之距离最近的聚类中心所在的类别中。

第二步:根据第一步所得到的聚类划分,分别计算每个聚类的几何中心,将几何中心作为新的聚类中心,重复第一步,直到计算所得几何中心与聚类中心重合或接近重合为止。

注意:

  1. 聚类数k必须事先已知。借助某些评估指标,优选最好的聚类数。
  2. 聚类中心的初始选择会影响到最终聚类划分的结果。初始中心尽量选择距离较远的样本。
    在这里插入图片描述

K均值算法相关API:

import sklearn.cluster as sc
# n_clusters: 聚类数
model = sc.KMeans(n_clusters=4)
# 不断调整聚类中心,知道最终聚类中心稳定则聚类完成
model.fit(x)
# 获取训练结果的聚类中心
labels = model.labels_
centers = model.cluster_centers_
pred_y = model.predict(x)

案例:加载multiple3.txt,基于K均值算法完成样本的聚类。

import numpy as np
import sklearn.cluster as sc
import matplotlib.pyplot as mp
x = np.loadtxt('../data/multiple3.txt', delimiter=',')
# K均值聚类器
model = sc.KMeans(n_clusters=4)
model.fit(x)
centers = model.cluster_centers_
n = 500
l, r = x[:, 0].min() - 1, x[:, 0].max() + 1
b, t = x[:, 1].min() - 1, x[:, 1].max() + 1
grid_x = np.meshgrid(np.linspace(l, r, n),
                     np.linspace(b, t, n))
flat_x = np.column_stack((grid_x[0].ravel(), grid_x[1].ravel()))    
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
pred_y = model.predict(x)
mp.figure('K-Means Cluster', facecolor='lightgray')
mp.title('K-Means Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y, cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=pred_y, cmap='brg', s=80)
mp.scatter(centers[:, 0], centers[:, 1], marker='+', c='gold', s=1000, linewidth=1)
mp.show()

均值漂移算法

首先假定样本空间中的每个聚类均服从某种已知的概率分布规则,然后用不同的概率密度函数拟合样本中的统计直方图,不断移动密度函数的中心(均值)的位置,直到获得最佳拟合效果为止。这些概率密度函数的峰值点就是聚类的中心,再根据每个样本距离各个中心的距离,选择最近聚类中心所属的类别作为该样本的类别。

均值漂移算法的特点:

  1. 聚类数不必事先已知,算法会自动识别出统计直方图的中心数量。
  2. 聚类中心不依据于最初假定,聚类划分的结果相对稳定。
  3. 样本空间应该服从某种概率分布规则,否则算法的准确性会大打折扣。
    在这里插入图片描述
    在这里插入图片描述

均值漂移算法相关API:

# 量化带宽,决定每次调整概率密度函数的步进量
# n_samples:样本数量
# quantile:量化宽度(直方图一条的宽度)
bw = sc.estimate_bandwidth(x, n_samples=len(x), quantile=0.1)
# 均值漂移聚类器
model = sc.MeanShift(bandwidth=bw, bin_seeding=True)
model.fit(x)

案例:加载multiple3.txt,使用均值漂移算法对样本完成聚类划分。

import numpy as np
import sklearn.cluster as sc
import matplotlib.pyplot as mp

x = np.loadtxt('../data/multiple3.txt', delimiter=',')
# 量化带宽,决定每次调整概率密度函数的步进量
bw = sc.estimate_bandwidth(x, n_samples=len(x), quantile=0.2)
# 均值漂移聚类器
model = sc.MeanShift(bandwidth=bw, bin_seeding=True)
model.fit(x)
centers = model.cluster_centers_
n = 500
l,  r = x[:, 0].min() - 1, x[:, 0].max() + 1
b,  t = x[:, 1].min() - 1, x[:, 1].max() + 1
grid_x = np.meshgrid(np.linspace(l, r, n),
                     np.linspace(b, t, n))
flat_x = np.column_stack((grid_x[0].ravel(), grid_x[1].ravel()))
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
pred_y = model.predict(x)
mp.figure('Mean Shift Cluster', facecolor='lightgray')
mp.title('Mean Shift Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y, cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=pred_y, cmap='brg', s=80)
mp.scatter(centers[:, 0], centers[:, 1], marker='+', c='gold', s=1000, linewidth=1)
mp.show()

轮廓系数

好的聚类:内密外疏,同一个聚类内部的样本要足够密集,不同聚类之间样本要足够疏远。

轮廓系数计算规则:针对样本空间中的一个特定样本,计算它与所在聚类其它样本的平均距离a,以及该样本与距离最近的另一个聚类中所有样本的平均距离b,该样本的轮廓系数为(b-a)/max(a, b),将整个样本空间中所有样本的轮廓系数取算数平均值,作为聚类划分的性能指标s。

轮廓系数的区间为:[-1, 1]。 -1代表分类效果差,1代表分类效果好。0代表聚类重叠,没有很好的划分聚类。

轮廓系数相关API:

import sklearn.metrics as sm
# v:平均轮廓系数
# metric:距离算法:使用欧几里得距离(euclidean)
v = sm.silhouette_score(输入集, 输出集, sample_size=样本数, metric=距离算法)

案例:输出KMeans算法聚类划分后的轮廓系数。

# 打印平均轮廓系数
print(sm.silhouette_score( x, pred_y, sample_size=len(x), metric='euclidean'))

DBSCAN算法

从样本空间中任意选择一个样本,以事先给定的半径做圆,凡被该圆圈中的样本都视为与该样本处于相同的聚类,以这些被圈中的样本为圆心继续做圆,重复以上过程,不断扩大被圈中样本的规模,直到再也没有新的样本加入为止,至此即得到一个聚类。于剩余样本中,重复以上过程,直到耗尽样本空间中的所有样本为止。

DBSCAN算法的特点:

  1. 事先给定的半径会影响最后的聚类效果,可以借助轮廓系数选择较优的方案。

  2. 根据聚类的形成过程,把样本细分为以下三类:

    外周样本:被其它样本聚集到某个聚类中,但无法再引入新样本的样本。

    孤立样本:聚类中的样本数低于所设定的下限,则不称其为聚类,反之称其为孤立样本。

    核心样本:除了外周样本和孤立样本以外的样本。
    在这里插入图片描述

DBSCAN聚类算法相关API:

# DBSCAN聚类器
# eps:半径
# min_samples:聚类样本数的下限,若低于该数值,则称为孤立样本
model = sc.DBSCAN(eps=epsilon, min_samples=5)
model.fit(x)

案例:修改凝聚层次聚类案例,基于DBSCAN聚类算法进行聚类划分,选择最优半径。

import numpy as np
import sklearn.cluster as sc
import sklearn.metrics as sm
import matplotlib.pyplot as mp

x = np.loadtxt('../data/perf.txt', delimiter=',')
epsilons, scores, models = np.linspace(0.3, 1.2, 10), [], []
for epsilon in epsilons:
    # DBSCAN聚类器
    model = sc.DBSCAN(eps=epsilon, min_samples=5)
    model.fit(x)
    score = sm.silhouette_score(
        x, model.labels_, sample_size=len(x), metric='euclidean')
    scores.append(score)
    models.append(model)
scores = np.array(scores)
best_index = scores.argmax()
best_epsilon = epsilons[best_index]
print(best_epsilon)
best_score = scores[best_index]
print(best_score)
best_model = models[best_index]

案例:获取核心样本、外周样本、孤立样本。并且使用不同的点型绘图。

best_model = models[best_index]
pred_y = best_model.fit_predict(x)
core_mask = np.zeros(len(x), dtype=bool)
core_mask[best_model.core_sample_indices_] = True
offset_mask = best_model.labels_ == -1
periphery_mask = ~(core_mask | offset_mask)
mp.figure('DBSCAN Cluster', facecolor='lightgray')
mp.title('DBSCAN Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
labels = best_model.labels_
mp.scatter(x[core_mask][:, 0], x[core_mask][:, 1], c=labels[core_mask], 
           cmap='brg', s=80, label='Core')
mp.scatter(x[periphery_mask][:, 0], x[periphery_mask][:, 1], alpha=0.5,
           c=labels[periphery_mask], cmap='brg', marker='s', s=80, label='Periphery')
mp.scatter(x[offset_mask][:, 0], x[offset_mask][:, 1],
           c=labels[offset_mask], cmap='brg', marker='x', s=80, label='Offset')
mp.legend()
mp.show()

推荐引擎

推荐引擎意在把最需要的推荐给用户。

在不同的机器学习场景中通常需要分析相似样本。而统计相似样本的方式可以基于欧氏距离分数,也可基于皮氏距离分数。

欧氏距离分数
欧 氏 距 离 分 数 = 1 1 + 欧 氏 距 离 欧氏距离分数 = \frac{1}{1+欧氏距离} =1+1
计算所得欧氏距离分数区间处于:[0, 1],越趋于0样本间的欧氏距离越远,样本越不相似;越趋于1,样本间的欧氏距离越近,越相似。

构建样本之间的欧氏距离得分矩阵:

[ a b c d . . a 1 0.2 0.3 0.4 . . b 0.2 1 x x . . c 0.3 x 1 x . . d 0.4 x x 1 . . . . . . . . . . . . . . ] \left[ \begin{array}{c} & a & b & c & d & .. \\ a & 1 & 0.2 & 0.3 & 0.4 & .. \\ b & 0.2 & 1 & x & x & .. \\ c & 0.3 & x & 1 & x & .. \\ d & 0.4 & x & x & 1 & .. \\ .. & .. & .. & .. & .. & .. \\ \end{array} \right] abcd..a10.20.30.4..b0.21xx..c0.3x1x..d0.4xx1..............
案例:解析ratings.json,根据每个用户对已观看电影的打分计算样本间的欧氏距离,输出欧氏距离得分矩阵。

import json
import numpy as np

with open('../data/ratings.json', 'r') as f:
    ratings = json.loads(f.read())
users, scmat = list(ratings.keys()), []
for user1 in users:
    scrow = []
    for user2 in users:
        movies = set()
        for movie in ratings[user1]:
            if movie in ratings[user2]:
                movies.add(movie)
        if len(movies) == 0:
            score = 0
        else:
            x, y = [], []
            for movie in movies:
                x.append(ratings[user1][movie])
                y.append(ratings[user2][movie])
            x = np.array(x)
            y = np.array(y)
            score = 1 / (1 + np.sqrt(((x - y) ** 2).sum()))
        scrow.append(score)
    scmat.append(scrow)
users = np.array(users)
scmat = np.array(scmat)
for scrow in scmat:
    print('  '.join('{:.2f}'.format(score) for score in scrow)) 

皮尔逊相关系数

A = [1,2,3,1,2] 
B = [3,4,5,3,4] 
m = np.corrcoef(A, B)

皮尔逊相关系数 = 协方差 / 标准差之积

相关系数处于[-1, 1]区间。越靠近-1代表两组样本反相关,越靠近1代表两组样本正相关。

案例:使用皮尔逊相关系数计算两用户对一组电影评分的相关性。

score = np.corrcoef(x, y)[0, 1]

按照相似度从高到低排列每个用户的相似用户

# scmat矩阵中每一行为 每一个用户对所有用户的皮尔逊相关系数
for i, user in enumerate(users):
    # 拿到所有相似用户与相似用户所对应的皮尔逊相关系数
    sorted_indices = scmat[i].argsort()[::-1]
    sorted_indices = sorted_indices[sorted_indices != i]
    similar_users = users[sorted_indices]
    similar_scores = scmat[i, sorted_indices]
    print(user, similar_users, similar_scores, sep='\n')

生成推荐清单

  1. 找到所有皮尔逊系数正相关的用户
  2. 遍历当前用户的每个相似用户,拿到相似用户看过但是当前用户没有看过的电影作为推荐电影
  3. 多个相似用户有可能推荐同一部电影,则取每个相似用户对该电影的评分得均值作为推荐度。
  4. 可以把相似用户的皮尔逊系数作为权重,皮尔逊系数越大,推荐度越高。
    # 找到所有皮尔逊系数正相关的用户
    positive_mask = similar_scores > 0
    similar_users = similar_users[positive_mask]
    # 相似用户对应的皮尔逊相关系数
    similar_scores = similar_scores[positive_mask]
    #存储对于当前用户所推荐的电影以及电影的推荐度(推荐电影的平均分)
    recomm_movies = {}
    #遍历当前用户的每个相似用户
    for i, similar_user in enumerate(similar_users):
        #拿到相似用户看过但是当前用户没有看过的电影
        for movie, score in ratings[similar_user].items():
            if (movie not in ratings[user].keys()):
                if movie not in recomm_movies:
                    recomm_movies[movie] = []
                else:
                    recomm_movies[movie].append(score)
                    
    print(user)
    movie_list = sorted(recomm_movies.items(), key=lambda x:np.average(x[1]), reverse=True)
    print(movie_list)

代码总结

结巴分词

import jieba


strs=["我来到北京清华大学","乒乓球拍卖完了","中国科学技术大学"]
for str in strs:
    seg_list = jieba.cut(str)
    print("Paddle Mode: " + '/'.join(list(seg_list)))

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut("他来到了网易杭研大厦")  # 默认是精确模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))
Paddle Mode: 我/来到/北京/清华大学
Paddle Mode: 乒乓球/拍卖/完/了
Paddle Mode: 中国/科学技术/大学
Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
Default Mode: 我/ 来到/ 北京/ 清华大学
他, 来到, 了, 网易, 杭研, 大厦
小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
text = '韩国首尔市长朴元淳9日失联,其女儿报警称父亲留下类似遗言的信息后离家,警方随后展开搜索。目前已确认其死亡。'
seg_list = jieba.cut(text)
print(", ".join(seg_list))
韩国, 首尔, 市长, 朴元淳, 9, 日, 失联, ,, 其, 女儿, 报警, 称, 父亲, 留下, 类似, 遗言, 的, 信息, 后, 离家, ,, 警方, 随后, 展开, 搜索, 。, 目前, 已, 确认, 其, 死亡, 。
jieba.load_userdict('my.dict')
text = '张平平安全到家了'
seg_list = jieba.cut(text)
print(", ".join(seg_list))
张平平, 安全, 到家, 了
text = "距离川沙公路较近,但是公交指示不对,如果是""蔡陆线""的话,会非常麻烦.建议用别的路线.房间较为简单."
text = '商务大床房,房间很大,床有2M宽,整体感觉经济实惠不错!'
text = '早餐太差,无论去多少人,那边也不加食品的。酒店应该重视一下这个问题了。房间本身很好。'
seg_list = jieba.cut(text)
print(", ".join(seg_list))
早餐, 太, 差, ,, 无论, 去, 多少, 人, ,, 那边, 也, 不加, 食品, 的, 。, 酒店, 应该, 重视, 一下, 这个, 问题, 了, 。, 房间, 本身, 很, 好, 。
import jieba.analyse as ja
text = '清晨6点多钟,在公鸡的啼鸣声中,西藏拉萨市尼木县卡如乡干部冯虎已经动身前往鸡舍,开始了添料、拾蛋、打扫鸡舍等工作。西藏拉萨尼木县卡如乡加纳日农牧民专业合作社藏鸡标准化养殖基地一期项目,于2019年4月份开始投入运营。当年7月份,冯虎作为尼木县“点对点”抓产业干部来到了基地,带领群众开展藏鸡养殖工作。“贫困群众要致富得靠产业项目,虽然在援藏资金帮助下建设了扶贫藏鸡养殖基地,但群众没有规模化饲养过藏鸡,缺乏经验,需要有人带动,我就申请来当‘鸡司令’了。”冯虎乐呵呵地说。在尼木县,像冯虎这样变身种植养殖“土”专家的各级党员干部一共有153名。尼木县委副书记孙先龙介绍,尼木县十分注重在项目一线检验干部落实能力,专门制定了《中共尼木县委员会关于干部“点对点”抓产业发展的实施方案》,以党的建设为最大抓手,把干部群众作为当前尼木经济社会发展的最大资源,坚持抓党建促提升、正风纪、鼓干劲,坚持干部带头、党员先行、群众参与。在干部“点对点”帮扶下,困难群众的生活面貌焕然一新。总是旷工的18岁建档立卡困难群众多吉,被身边的榜样力量感动,看到尼木县人大常委会副主任张世杰蹲在菜苗旁修枝打叉,他深受触动,从此不再旷工,安心在温室大棚里打工学起了技术;群众冲多拉姆跟着尼木县自然资源局干部德吉,学习了一年车厘子种植管理技术,今年首批成熟的车厘子引得大家争相采摘购买,坚定了她学好这门种植技艺的决心;群众嘎玛跟着冯虎养殖藏鸡,每个月能拿到3600元的工资,年底还能有分红,这让曾经一贫如洗的嘎玛过上了好日子。“‘点对点’干部,到项目一线之前也不会种不会养,不懂市场不懂经营,但他们首先带头认真学习产业发展知识,掌握产业发展相关技能,主动深入并带着农牧民群众到田间地头、养殖车间手把手教技术,帮助搞好种养、对接市场,做群众致富路上的贴心人和领路人。”孙先龙说。如今,在产业项目“点对点”干部带动下,有劳动能力的尼木县建档立卡贫困群众都找到了适合自己的工作,并在实践中学得一技之长,致富奔小康的道路越走越宽广。孙先龙介绍:“尼木县通过落实‘党组织+龙头企业+合作社+贫困户’的专业化运营和带贫机制,把项目区所辖贫困户全部吸纳为合作社社员,由干部‘点对点’帮带。2019年,全县153名党员干部‘点对点’抓82个产业项目,带动1029户3324名脱贫群众户均增收8000多元。”(经济日报-中国经济网记者 贺建明)'
ja.extract_tags(text, topK=20)
ja.textrank(text, topK=20)
['群众',
 '尼木县',
 '干部',
 '产业',
 '养殖',
 '点对点',
 '项目',
 '发展',
 '技术',
 '基地',
 '工作',
 '贫困户',
 '运营',
 '帮助',
 '西藏',
 '打叉',
 '带动',
 '种植',
 '作为',
 '鸡舍']

htl.dict:
在这里插入图片描述

酒店评论舆情分析

import numpy as np
import pandas as pd
import jieba
import sklearn.model_selection as ms
import sklearn.naive_bayes as nb
import sklearn.metrics as sm
import sklearn.feature_extraction.text as ft
# 加载数据集  
data = pd.read_csv('../data/htl_all.csv', encoding='utf-8')
# 加载自定义jieba词典
jieba.load_userdict('htl.dict')

# 基于jieba分词对每一个样本进行分词,整理成  " 单词 单词 单词 单词 ..."
def func(item):
    seg_list = jieba.cut(item)
    return ' '.join(seg_list)
data['review'] = data['review'].apply(func)

# 基于tfidf训练模型
size0 = (data['label']==0).sum()
data = data.tail(size0 * 2)
data['label'].value_counts()
1    2443
0    2443
Name: label, dtype: int64
# 把所有的样本输入转成TFIDF矩阵
cv = ft.CountVectorizer()
bow = cv.fit_transform(data['review'])
tt = ft.TfidfTransformer()
tfidf = tt.fit_transform(bow)
# 整理输入集输出集,拆分训练集测试集
x, y = tfidf, data['label']
train_x, test_x, train_y, test_y = \
    ms.train_test_split(x, y, test_size=0.2, random_state=7, stratify=y)

# 使用朴素贝叶斯
import sklearn.naive_bayes as nb
model = nb.MultinomialNB()
model.fit(train_x, train_y)

# 测试评估模型
pred_test_y = model.predict(test_x)
print(sm.classification_report(test_y, pred_test_y))
             precision    recall  f1-score   support

          0       0.85      0.87      0.86       489
          1       0.87      0.85      0.86       489

avg / total       0.86      0.86      0.86       978

针对测试样本进行测试

test_data = ['地板很脏,电视没信号,不太好,不建议入住。', 
             '厕所漏水,空调还坏了,真差劲,再也不来了!',
             '虽然有种种不满意,但是早餐还不错,晚上挺安静的,还是给一个好评吧。',
             '挺喜欢的。',
             '不喜欢。',
             '一点都不满意。',
             '地板脏,空调漏水,早餐不错,厕所干净。'] 
test_data = pd.Series(test_data)
test_data = test_data.apply(func)
# 重新组织tfidf
bow = cv.transform(test_data)
tfidf = tt.transform(bow)
pred_y = model.predict(tfidf)
# 输出每个样本的置信概率
prob_y = model.predict_proba(tfidf)
for d, y, p in zip(test_data, pred_y, prob_y.max(axis=1)):
    print(d, ' -> ', y, ' : ', p)

地板 很脏 , 电视 没 信号 , 不太好 , 不 建议 入住 。  ->  0  :  0.783572951108166
厕所 漏水 , 空调 还坏 了 , 真 差劲 , 再也 不来 了 !  ->  0  :  0.9075941289694525
虽然 有 种种 不满意 , 但是 早餐 还 不错 , 晚上 挺 安静 的 , 还是 给 一个 好评 吧 。  ->  1  :  0.6412416420055634
挺 喜欢 的 。  ->  1  :  0.8308116162831367
不喜欢 。  ->  0  :  0.5217390249440543
一点 都 不满意 。  ->  0  :  0.5341385770887528
地板 脏 , 空调 漏水 , 早餐 不错 , 厕所 干净 。  ->  0  :  0.5968765877702141

聚类模型

import numpy as np
import pandas as pd
import sklearn.metrics as sm

kMeans

data = pd.read_csv('../data/multiple3.txt', header=None, names=['x1', 'x2'])
# data.plot.scatter(x='x1', y='x2', s=40)

# 使用kmeans聚类 得到4类样本
import sklearn.cluster as sc
model = sc.KMeans(n_clusters=5)
model.fit(data)
labels = model.labels_
data['labels'] = labels
# 聚类中心
centers = model.cluster_centers_
# print(centers)
ax=data.plot.scatter(x='x1', y='x2', s=30, c='labels', cmap='brg')
# 绘制聚类中心
centers = pd.DataFrame(centers, columns=['x1', 'x2'])
centers.plot.scatter(x='x1', y='x2', s=500, marker='+', color='red', ax=ax)

# 计算轮廓系数
sm.silhouette_score(data, labels, sample_size=len(data), metric='euclidean')

0.6428703627047203

在这里插入图片描述

均值漂移

data = pd.read_csv('../data/multiple3.txt', header=None, names=['x1', 'x2'])
# data.plot.scatter(x='x1', y='x2', s=40)

# 使用kmeans聚类 得到4类样本
import sklearn.cluster as sc
bw = sc.estimate_bandwidth(data, n_samples=len(data), quantile=0.1)
model = sc.MeanShift(bandwidth=bw, bin_seeding=True)
model.fit(data)
labels = model.labels_
data['labels'] = labels
# 聚类中心
centers = model.cluster_centers_
print(centers)
ax=data.plot.scatter(x='x1', y='x2', s=30, c='labels', cmap='brg')
# 绘制聚类中心
centers = pd.DataFrame(centers, columns=['x1', 'x2'])
centers.plot.scatter(x='x1', y='x2', s=500, marker='+', color='red', ax=ax)
# 计算轮廓系数
sm.silhouette_score(data, labels, sample_size=len(data), metric='euclidean')

[[1.86416667 2.03333333]
 [6.87444444 5.57638889]
 [3.45088235 5.27323529]
 [5.90964286 2.40357143]]





0.6372478144801144

在这里插入图片描述

DBSCAN

data = pd.read_csv('../data/perf.txt', header=None, names=['x1', 'x2'])
# data.plot.scatter(x='x1', y='x2', s=40)
# 使用轮廓系数优选最优半径
epsilons = np.arange(0.3, 1.2, 0.1)
best_eps = 0
best_model = 0
best_score = 0
for ep in epsilons:
    model = sc.DBSCAN(eps=ep, min_samples=3)
    model.fit(data)
    labels = model.labels_
    score = sm.silhouette_score(
        data, labels, sample_size=len(data), metric='euclidean')
    if score > best_score:
        best_score = score
        best_eps = ep
        best_model = model

print(best_eps, best_score, best_model)
# 可视化聚类效果
labels = best_model.labels_

# 获取核心样本
core_mask = best_model.core_sample_indices_
core_samples = data.iloc[core_mask]
ax = core_samples.plot.scatter(
    x='x1', y='x2', s=30, c=labels[core_mask], cmap='brg')
# 获取孤立样本
offset_mask = labels==-1
offset_samples = data[offset_mask]
offset_samples.plot.scatter(x='x1', y='x2', s=40, color='lightgray', ax=ax)
# 获取外周样本
core_bool_mask = np.zeros(len(labels), dtype='bool')
core_bool_mask[core_mask] = True
p_mask = ~(core_bool_mask | offset_mask)
p_samples = data[p_mask]
p_samples.plot.scatter(x='x1', y='x2', s=50, marker='s', color='gray', ax=ax)
0.7000000000000002 0.6370987100971658 DBSCAN(algorithm='auto', eps=0.7000000000000002, leaf_size=30,
    metric='euclidean', metric_params=None, min_samples=3, n_jobs=1,
    p=None)





<matplotlib.axes._subplots.AxesSubplot at 0x1fec576ecc0>

在这里插入图片描述

data.plot.scatter(x='x1', y='x2', c=labels, cmap='brg')
<matplotlib.axes._subplots.AxesSubplot at 0x1fec5234be0>

在这里插入图片描述

eq_data = pd.read_csv('../data/Earthquakes.csv', 
                      usecols=['Latitude', 'Longitude', 'Magnitude'])
eq_data = eq_data[eq_data['Magnitude']>6]
eq_data.plot.scatter(x='Latitude',y='Longitude', c='Magnitude', cmap='jet')
<matplotlib.axes._subplots.AxesSubplot at 0x1fec53eb400>

在这里插入图片描述

posted @ 2023-02-03 21:35  野哥李  阅读(30)  评论(0编辑  收藏  举报  来源