无监督学习:利用无标签的数据学习数据的分布或数据与数据之间的关系,常用于聚类、降维。与有监督学习最大区别在于数据是否有标签
1. 聚类
聚类(clustering):根据数据的相似性将数据分为多类的过程
聚类方法 | 加载模块 | 聚类方法 | 加载模块 |
---|---|---|---|
K-means | cluster.KMeans | AP聚类 | cluster.AffinityPropagation |
均值漂移 | cluster.MeanShift | 层次聚类 | cluster.AgglomerativeClustering |
BIRCH | cluster.Birch | 谱聚类 | cluster.SpectralClustering |
DBSCAN | cluster.DBSCAN |
2个样本的相似性:计算2个样本之间的距离
使用不同方法计算样本间距离会关系到聚类结果的好坏
1.1 距离算法
欧氏距离:最常用的一种距离度量方法,源于欧式空间中2点的距离
曼哈顿距离:也称“城市街区距离”,类似于在城市之中驾车行驶,从一个十字路口到另外一个十字路口的距离
马氏距离:数据的协方差距离,是一种尺度无关的度量方式,即会将样本各个属性标准化,再计算样本间距离
夹角余弦:余弦相似度用向量空间中2个向量夹角余弦值作为衡量2个样本样差异大小。值越接近1,表明越相相似
1.2 sklearn.cluster模块
sklearn库提供常用的聚类算法函数包含在sklearn.cluster
模块中
同样数据,不同算法,结果不同,耗时不同,这些由算法特性决定
标准数据输入格式:[样本个数,特征个数]定义的矩阵形式
相似性矩阵输入格式:由[样本数目]定义的矩阵形式,矩阵中每一个元素为2个样本的相似度。如DBSCAN、AffinityPropagation接受这种输入。如果以余弦相似度为例,则对角线的数值都为1,其他每个元素取值范围为[0,1]
算法 | 参数 | 可扩展性 | 相似性度量 |
---|---|---|---|
K-means | 聚类个数 | 大规模数据 | 点间距离 |
DBSCAN | 邻域大小 | 大规模数据 | 点间距离 |
Gaussian Mixtures | 聚类个数及其他超参 | 复杂度高,不适合处理大规模数据 | 马氏距离 |
Birch | 分支因子、阈值等其他超参 | 大规模数据 | 欧氏距离 |
1.3 K-means方法
K-means算法:以k为参数,把n个对象分成k个簇,使簇内具有较高的相似度,而簇间相似度较低
1.随机选择k个点作为初始的聚类中心
2.剩下的点,根据与中心的距离将其归入最近的簇
3.对每个簇,计算所有点的均值作为新的聚类中心
4.重复2、3直到聚类中心不再发生变化
K-means.png
明日方舟掉落情况聚类
# 导入sklearn相关包
import numpy as np
from sklearn.cluster import KMeans
'''调试加载文件代码'''
with open('111.txt') as fr:
# 逐行读取,并存储
contents = fr.readlines()
print(contents) # 【输出结果】
# 存储名字和数据
RetData = []
RetName = []
for content in contents:
print(content) # 扭转醇 3 3 54【部分数据】
# strip()删除字符串前后空格;split()以空格为分隔符将字符串拆分成多个部分,并将这些存储到一个列表中
a = content.strip().split()
print(a) # ['扭转醇', '3', '3', '54']【部分数据】
print(len(a)) # 4
RetName.append(a[0])
print(RetName) # ['扭转醇']【部分数据】
RetData.append([float(a[i]) for i in range(1, len(a))])
print(RetData) # [[3.0, 3.0, 54.0]]【部分数据】
加载数据模块,被加载的文件数据格式如下:
关卡1 3 3 54 ······
关卡2 10 3.33 60 ······
······
def LoadData(FilePath):
'''加载数据文件'''
with open(FilePath) as fr:
contents = fr.readlines()
RetData = []
RetName = []
for content in contents:
a = content.strip().split()
RetName.append(a[0])
RetData.append([float(a[i]) for i in range(1, len(a))])
return RetName, RetData
# 调用
LoadData(r'C:\Users\Administrator\Desktop\111.txt') #【能成功打印数据】
调用K-means方法所需要参数:
- n_clusters:用于指定聚类中心的个数
- init:初始聚类中心的初始化方法,默认是k-means++
- max_iter:最大的迭代次数,默认是300
- data:加载的数据
- label:聚类后各数据所属的标签
- fit_predict():计算簇中心以及为簇分配序号
if __name__ == '__main__':
'''Kmeans聚类算法'''
import numpy as np
from sklearn.cluster import KMeans
# 读取数据,分别存储到data和name中
name, data = LoadData(r'C:\Users\Administrator\Desktop\111.txt')
# 调用KMeans()和fit_predict()进行聚类计算
km = KMeans(n_clusters=3)
label = km.fit_predict(data)
# expense:聚类中心点的数值加和
expenses = np.sum(km.cluster_centers_, axis = 1)
# 设定变量,接收关卡label的分簇
NameCluster = [[], [], []]
# 将关卡按照簇分别存储
for i in range(len(name)):
NameCluster[label[i]].append(name[i])
# 将每个簇的聚类中心点的数值加和进行输出
for i in range(len(NameCluster)):
print('聚类中心点的数值加和: %.2f'% expenses[i])
print(NameCluster[i])
修改 km = KMeans(n_clusters=3)中的数值,可以分层不同簇
相应的NameCluster = [[], [], []]需要改变
计算2条数据相似性是,Sklearn的K-Means默认用的是欧氏距离
1.4 DBSCAN方法
DBSCAN密度聚类,是一种基于面膜度的距离算法
- 不需要预先指定簇的个数
- 最终的簇个数不定
DBSCAN算法将数据分为3类:
- 核心点:在半径Eps内含有超过MinPts数目点
- 边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域 内
-
噪音点:既不是核心点也不是边界点的点
DBACAN 1.png
其核心点中邻域内的点是图片中黄色的点,超过5个
DBSCAN算法流程
- 将所有点标记为核心点、边界点或噪音点
- 删除噪声点
- 为距离在Eps内的所核心点之间赋予一条边
- 每组连通的核心点形参一个簇
- 将每个边界点指派到一个与之关联的核心点的簇中
DBSCAN主要参数:
-
eps
:2个样本被看做邻居点的最大距离 -
min_samples
:簇的样本数 -
metric
:距离的计算方式
import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt
# 定义一个字典
mac2id=dict()
# 定义一个列表
onlinetimes=[]
f=open(r'E:\TDRDIS Book\编程\Python应用\DBSCAN算法实例数据\DBSCAN.txt')
# 遍历f,获得mac地址,开始上网时间,上网时长
for line in f:
# 定义一个变量,接收以逗号分隔的第3个数据(具体数据格式如下显示)
mac=line.split(',')[2]
onlinetime=int(line.split(',')[6])
starttime=int(line.split(',')[4].split(' ')[1].split(':')[0])
if mac not in mac2id:
mac2id[mac]=len(onlinetimes)
onlinetimes.append((starttime,onlinetime))
else:
onlinetimes[mac2id[mac]]=[(starttime,onlinetime)]
real_X=np.array(onlinetimes).reshape((-1,2))
# 定义上网时间,用于聚类分析的变量,
X=real_X[:,0:1]
# 开始上网时间聚类
db=skc.DBSCAN(eps=0.01,min_samples=20).fit(X)
# labels为每个数据的簇标签
labels = db.labels_
print('Labels:')
print(labels)
# -1为噪声数据,定义噪声数据的比例
raito=len(labels[labels[:] == -1]) / len(labels)
print('Noise raito:',format(raito, '.2%'))
# 计算簇的个数
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print('Estimated number of clusters: %d' % n_clusters_)
# 评价聚类效果
print("Silhouette Coefficient: %0.3f"% metrics.silhouette_score(X, labels))
# 打印各簇标号,及其数据
for i in range(n_clusters_):
print('Cluster ',i,':')
print(list(X[labels == i].flatten()))
# 根据上网时间,绘制直方图
plt.hist(X,24)
数据格式如下:
2c929293466b97a6014754607e457d68,U201215025,A417314EEA7B,10.12.49.26,2014-07-20 22:44:18.540000000,2014-07-20 23:10:16.540000000,1558,15,本科生动态IP模版,100元每半年,internet
2c929293466b97a60147546099a57d81,U201116197,F0DEF1C78366,222.20.71.38,2014-07-20 12:14:21.380000000,2014-07-20 23:25:22.380000000,40261,1,本科生动态IP模版,20元每月,internet
······
# 以上网时长作为标签
# 将X和db改为如下代码即可
X=np.log(1+real_X[:,1:])
db=skc.DBSCAN(eps=0.14,min_samples=10).fit(X)
输出结果类似开始上网时间
如下图所示,类似于这样的原始数据分布式不能用于聚类的,可以对数据进行对数变幻(如上网时长聚类代码)
2. 降维
在保证数据所具有的代表性或者分布的情况下,将高纬数据转化为低维数据的过程
可用于数据可视化、精简数据
降维方法 | 加载模块 | 降维方法 | 加载模块 |
---|---|---|---|
主成分分析 | decomposition.PCA | 字典学习 | decomposition.SparseCoder |
截断SVD和LSA | decomposition.TruncatedSVD | 因子分析 | decomposition.FactorAnalysis |
非负矩阵分解 | decomposition.NMF | LDA | decomposition.LatentDirichletAllocation |
独立成分分析 | decomposition.FastICA |
目前sklearn提供7种降维算法,需要调用sklearn.decomposition
模块
算法 | 参数 | 可扩展性 | 适用任务 |
---|---|---|---|
PCA | 所降维度及其他参数 | 大规模数据 | 信号处理等 |
FastICA | 所降维度及其他参数 | 超大规模数据 | 图像图形特征提取 |
NMF | 所降维度及其他参数 | 大规模数据 | 图像图形特征提取 |
LDA | 所降维度及其他参数 | 大规模数据 | 文本数据、主题挖掘 |
2.1 PCA
主成分分析(PCA)通常用于高纬数据集的探索与可视化,还可以用作数据的压缩和预处理
PCA可以把具有相关性的高纬变量合成线性无关的低维变量,称为主成分。主成分能够尽可能保留原始数据的信息
PCA原理:矩阵的主成分就是协方差矩阵对应的特征向量,安装对应的特征值大小进行排序,最大的特征值就是第一主成分,其次是第二主成分,以此类推
方差:各个样本和样本均值的差的平方和的均值,用来度量一组数据的分散程度
协方差:用于度量2个变量之间的线性关系程度
矩阵特征向量:描述数据集结构的非零向量
过程:
- 对所有样本进行中心化
- 计算样本的协方差矩阵
- 对协方差矩阵做特征值分解
- 取最的d个大特征值所对应的特征向量
输出:投影矩阵
在sklearn库中,使用sklearn.decomposition.PCA,加载PCA进行降维,主要参数有:
-
n_components
:指定主成分的个数,即降维后数据的维度 -
svd_solver
:设置特征值分解的方法,默认auto
,其他可选有full
,arpack
,randomized
实例:将鸢尾花数据(4维)的三类样本,使用PCA对数据进行降维,实现在二维平面的可视化
# 加载数据可视化包
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
# 加载鸢尾花数据集
from sklearn.datasets import load_iris
# 调用载鸢尾花数据集,查看数据,发现是字典型
data = load_iris()
# 用字典方法,把数据和标签分别调取出来
y = data['target']
X = data['data']
# 加载PCA算法,设定降成二维数据
pca = PCA(n_components=2)
# 对数据进行降维,并保持到变量中
reduced_X = pca.fit_transform(X)
# 设定变量,按类别对降维后的数据进行保存
red_x, red_y = [], []
blue_x, blue_y = [], []
green_x, green_y = [], []
# 按照类别将降维后的数据保存在不同列表中
for i in range(len(reduced_X)):
if y[i] == 0:
red_x.append(reduced_X[i][0])
red_y.append(reduced_X[i][1])
elif y[i] == 1:
blue_x.append(reduced_X[i][0])
blue_y.append(reduced_X[i][1])
else:
green_x.append(reduced_X[i][0])
green_y.append(reduced_X[i][1])
# 数据可视化,用散点图表示
plt.scatter(red_x, red_y, c='r', marker='x')
plt.scatter(blue_x, blue_y, c='b', marker='D')
plt.scatter(green_x, green_y, c='g', marker='.')
plt.show()
因为类别是之前已经分类好的,这里直接设定3类,并按3类输出
可以看出,降维后,数据仍能清晰的分成3类。即降维后再聚类,降低分类工作量,还能保证质量
2.2 NMF
非负矩阵分解(NMF):在矩阵中所有元素均为非负数约束条件之下的矩阵分解方法
基本思想:给定一个非负矩阵V,NMF能够找到一个非负矩阵W和一个非负矩阵H,使得矩阵W和H的乘积近似等于矩阵V中的值
W矩阵:基础图像矩阵,相当于从原矩阵V中抽出来的特征
H矩阵:系数矩阵
NMF:广泛应用于图像分析、文本挖掘、语言处理等
矩阵分解优化目标:最小化H和W的乘积与原始矩阵的差
在sklearn库中,使用sklearn.decomposition.NMF,加载NMF进行降维,主要参数有:
-
n_components
:指定分解后矩阵的单个维度k,通过设定k大小,设置提取特征的数目 -
init
:W和H的初始化方式,默认为nudsvdar
实例:Olivetti脸部图像数据集。其中有400个人脸数据,每个数据时64*64大小。使用NMF对400个人脸数据进行特征提取(W矩阵),并还原图形
from numpy.random import RandomState
import matplotlib.pyplot as plt
# 用于创建随机种子
from sklearn.datasets import fetch_olivetti_faces
from sklearn import decomposition
# 设置图形展示时的排列情况,2行3列
n_row, n_col = 2, 3
# 设置提取的特征数目
n_components = n_row * n_col
# 设置人脸数据图片大小
image_shape = (64, 64)
# 加载数据,并打乱顺序
dataset = fetch_olivetti_faces(shuffle=True, random_state=RandomState(0))
# 提取数据
faces = dataset.data
def plot_gallery(title, images, n_col=n_col, n_row=n_row):
# 创建图片,并指明图片大小
plt.figure(figsize=(2. * n_col, 2.26 * n_row))
# 设置标题及字号大小
plt.suptitle(title, size=16)
for i, comp in enumerate(images):
# 选择绘制的子图
plt.subplot(n_row, n_col, i + 1)
vmax = max(comp.max(), -comp.min())
# 对数值归一化,并以灰度图显示
plt.imshow(comp.reshape(image_shape), cmap=plt.cm.gray,
interpolation='nearest', vmin=-vmax, vmax=vmax)
# 去除子图的坐标轴标签
plt.xticks(())
plt.yticks(())
# 调整子图的位置间隔
plt.subplots_adjust(0.01, 0.05, 0.99, 0.94, 0.04, 0.)
plot_gallery("First centered Olivetti faces", faces[:n_components])
# 对NMF和PCA进行实例化,并存储在一个列表中
estimators = [
('Eigenfaces - PCA using randomized SVD',
decomposition.PCA(n_components=6,whiten=True)),
('Non-negative components - NMF',
decomposition.NMF(n_components=6, init='nndsvda', tol=5e-3))
]
# 分别调用PCA和NMF
for name, estimator in estimators:
print("Extracting the top %d %s..." % (n_components, name))
print(faces.shape)
# 调用提取特征
estimator.fit(faces)
# 获取提取特征
components_ = estimator.components_
# 按照固定格式进行排序
plot_gallery(name, components_[:n_components])
# 可视化
plt.show()
3. 图像分隔
图像分隔:利用图像的灰度、颜色、纹理、形状等特征,把图像分成若干个互不重叠的区域,并使这些特征在同一区域内呈现相似性,在不同区域内存在明显差异。然后提取具有独特性质的区域用于不同研究
图像分隔常用方法:
- 阈值分割:对图像灰度进行度量,设置不同类别的阈值,达到分隔目的
- 边缘分隔:对图像边缘进行检测。即灰度值发生跳变的地方,则魏一片区域的边缘
- 直方图法:对图像的颜色建立直方图,波峰波谷能够表示一块区域的颜色范围,来达到分隔目的
- 特定理律:基于聚类分析、小波变换等理论完成分隔
实例描述:
- 目的:利用K-means算法对图像像素点颜色进行聚类,实现简单的图像分隔
- 输出:同一聚类中的点使用相同颜色标记
- 技术路线:sklearn.cluster.KMeans
import numpy as np
# 加载图像处理包
import PIL.Image as image
from sklearn.cluster import KMeans
def loadData(filePath):
# 以二进制形式打开文件
f = open(filePath,'rb')
data = []
# 以列表形式返回拖像素值,即获得图片像素数据
img = image.open(f)
# 获得图片的大小。
m,n = img.size
# 将每个像素点RGB颜色处理到0-1
for i in range(m):
for j in range(n):
x,y,z = img.getpixel((i,j))
# 将像素点数据存储在列表data中
data.append([x/256.0,y/256.0,z/256.0])
f.close()
# 以矩阵形式输出data以图片大小
return np.mat(data),m,n
# 调用函数,加载图片
imgData,row,col = loadData(r'E:\TDRDIS Book\编程\Python应用\pig\doctor.jpg')
# 设定聚类个数,对数据进行聚类,结果存储到变量中
label = KMeans(n_clusters=4).fit_predict(imgData)
# 还原聚类结果的维度信息
label = label.reshape([row,col])
# 创建一张新的灰度图保存聚类后的结果
pic_new = image.new("L", (row, col))
# 根据所属类别向图片中添加灰度值
for i in range(row):
for j in range(col):
pic_new.putpixel((i,j), int(256/(label[i][j]+1)))
# 以JPEG格式保存图像
pic_new.save(r'E:\TDRDIS Book\编程\Python应用\pig\doctor_new.jpg', "JPEG")
目录
Python机器学习应用
一、Sklearn库
二、无监督学习
三、有监督学习