无监督学习

无监督学习:利用无标签的数据学习数据的分布或数据与数据之间的关系,常用于聚类、降维。与有监督学习最大区别在于数据是否有标签

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点的距离


欧氏距离.png

曼哈顿距离:也称“城市街区距离”,类似于在城市之中驾车行驶,从一个十字路口到另外一个十字路口的距离

曼哈顿距离.png

马氏距离:数据的协方差距离,是一种尺度无关的度量方式,即会将样本各个属性标准化,再计算样本间距离

马氏距离.png

夹角余弦:余弦相似度用向量空间中2个向量夹角余弦值作为衡量2个样本样差异大小。值越接近1,表明越相相似


夹角余弦.png

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方法所需要参数:

  1. n_clusters:用于指定聚类中心的个数
  2. init:初始聚类中心的初始化方法,默认是k-means++
  3. max_iter:最大的迭代次数,默认是300
  4. data:加载的数据
  5. label:聚类后各数据所属的标签
  6. 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密度聚类,是一种基于面膜度的距离算法

  1. 不需要预先指定簇的个数
  2. 最终的簇个数不定

DBSCAN算法将数据分为3类:

  1. 核心点:在半径Eps内含有超过MinPts数目点
  2. 边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域 内
  3. 噪音点:既不是核心点也不是边界点的点


    DBACAN 1.png

其核心点中邻域内的点是图片中黄色的点,超过5个

DBSCAN算法流程

  1. 将所有点标记为核心点、边界点或噪音点
  2. 删除噪声点
  3. 为距离在Eps内的所核心点之间赋予一条边
  4. 每组连通的核心点形参一个簇
  5. 将每个边界点指派到一个与之关联的核心点的簇中

DBSCAN主要参数:

  1. eps:2个样本被看做邻居点的最大距离
  2. min_samples:簇的样本数
  3. 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
······

DBSCAN 2.png
DBACAN 3.png
DBSCAN 4.png
# 以上网时长作为标签
# 将X和db改为如下代码即可
X=np.log(1+real_X[:,1:])
db=skc.DBSCAN(eps=0.14,min_samples=10).fit(X)

输出结果类似开始上网时间
如下图所示,类似于这样的原始数据分布式不能用于聚类的,可以对数据进行对数变幻(如上网时长聚类代码)

DBSCAN 5.png

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个变量之间的线性关系程度
矩阵特征向量:描述数据集结构的非零向量

过程:

  1. 对所有样本进行中心化
  2. 计算样本的协方差矩阵
  3. 对协方差矩阵做特征值分解
  4. 取最的d个大特征值所对应的特征向量

输出:投影矩阵

在sklearn库中,使用sklearn.decomposition.PCA,加载PCA进行降维,主要参数有:

  1. n_components:指定主成分的个数,即降维后数据的维度
  2. 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类输出

鸢尾花降维散点图 1.png

可以看出,降维后,数据仍能清晰的分成3类。即降维后再聚类,降低分类工作量,还能保证质量

2.2 NMF

非负矩阵分解(NMF):在矩阵中所有元素均为非负数约束条件之下的矩阵分解方法
基本思想:给定一个非负矩阵V,NMF能够找到一个非负矩阵W和一个非负矩阵H,使得矩阵W和H的乘积近似等于矩阵V中的值

W矩阵:基础图像矩阵,相当于从原矩阵V中抽出来的特征
H矩阵:系数矩阵
NMF:广泛应用于图像分析、文本挖掘、语言处理等

矩阵分解优化目标:最小化H和W的乘积与原始矩阵的差
在sklearn库中,使用sklearn.decomposition.NMF,加载NMF进行降维,主要参数有:

  1. n_components:指定分解后矩阵的单个维度k,通过设定k大小,设置提取特征的数目
  2. 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()
NMF 0.png
NMF 1.png
NMF 2.png

3. 图像分隔

图像分隔:利用图像的灰度、颜色、纹理、形状等特征,把图像分成若干个互不重叠的区域,并使这些特征在同一区域内呈现相似性,在不同区域内存在明显差异。然后提取具有独特性质的区域用于不同研究
图像分隔常用方法:

  1. 阈值分割:对图像灰度进行度量,设置不同类别的阈值,达到分隔目的
  2. 边缘分隔:对图像边缘进行检测。即灰度值发生跳变的地方,则魏一片区域的边缘
  3. 直方图法:对图像的颜色建立直方图,波峰波谷能够表示一块区域的颜色范围,来达到分隔目的
  4. 特定理律:基于聚类分析、小波变换等理论完成分隔

实例描述:

  1. 目的:利用K-means算法对图像像素点颜色进行聚类,实现简单的图像分隔
  2. 输出:同一聚类中的点使用相同颜色标记
  3. 技术路线: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")
doctor.jpg
doctor_new.jpg

目录
Python机器学习应用
一、Sklearn库
二、无监督学习
三、有监督学习

Python机器学习应用.jpg

你可能感兴趣的:(无监督学习)