无监督学习

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

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342