机器学习应用——无监督学习(实例:31省市居民家庭消费调查&学生上网时间分布聚类&鸢尾花数据&人脸数据特征提取)
Posted 柠檬茶@
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习应用——无监督学习(实例:31省市居民家庭消费调查&学生上网时间分布聚类&鸢尾花数据&人脸数据特征提取)相关的知识,希望对你有一定的参考价值。
前言
机器学习应用博客中,将核心介绍三大类学习,即:无监督学习、监督学习、强化学习。
本篇将简要介绍:
1.无监督学习概念(最常应用场景:聚类(clustering)和降维(Dimension Reduction))
2.聚类——kmeans方法(居民家庭消费调查)、DBSCAN方法(学生上网时间分布)
3.降维——PCA方法(鸢尾花数据)、NMF方法(人脸数据特征提取)
一、无监督学习简要介绍
1.目标&定义
(1)无监督学习:利用无标签的数据,学习数据的分布或数据与数据之间的关系被称作无监督学习
(2)有监督学习和无监督学习的最大区别在于数据是否有标签
(3)无监督学习最常应用的场景是聚类(clustering)和降维(Dimension Reduction)
2.聚类(clustering)
(1)聚类:根据数据的“相似性”将数据分为多类的过程
(2)评估两个不同样本之间的“相似性”,通常使用的方法就是计算两个样本之间的“距离”
(3)使用不同的方法计算样本间的距离会关系到聚类结果的好坏
(4)常用距离计算方法
①欧氏距离:最常用的一种距离度量方法,源于欧式空间中两点的距离
该图为二维空间中欧式距离的计算
②曼哈顿距离:称作“城市街区距离”,类似于在城市之中驾车行驶,从一个十字路口到另外一个十字楼口的距离。
该图为二维空间中曼哈顿距离的计算
③马氏距离:表示数据的协方差距离,是一种尺度无关的度量方式。也就是说马氏距离会先将样本点的各个属性标准化,再计算样本间的距离。
其中,s是协方差矩阵
④余弦相似度:用向量空间中两个向量夹角的余弦值作为衡量两个样本差异的大小。余弦值越接近1,说明两个向量夹角越接近0度,表明两个向量越相似。
3.sklearn.cluster
(1)scikit-learn库(简称sklearn库)提供的常用聚类算法函数包含在sklearn.cluster这个模块中,如:K-Means,近邻传播算法,DBSCAN,等。
(2)注:以同样的数据集应用于不同的算法,可能会得到不同的结果,算法所耗费的时间也不尽相同,这是由算法的特性决定的。
(3)sklearn.cluster模块提供的各聚类算法函数可以使用不同的数据形式作为输入
①相似性矩阵输人格式:即由[样本数目]定义的矩阵形式,矩阵中的每一个元素为两个样本的相似度,如DBSCAN,AffinityPropagation(近邻传播算法)接受这种输人。
② 如果以余弦相似度为例,则对角线元素全为1。矩阵中每个元素的取值范围为[0,1]。
4.降维
(1)定义:在保证数据所具有的代表性特性或者分布的情况下,将高维数据转化为低维数据的过程。
(2)作用
①数据的可视化
②精简数据
(3)分类vs.降维
①聚类和分类都是无监督学习的典型任务,任务之间存在关联
②比如某些高纬数据的分类可以通过降维处理更好的获得
③另外学界研究也表明代表性的分类算法如k-means与降维算法如NMF之间存在等价性
(4)sklearn vs.降维
①降维是机器学习领域的一个重要研究内容,有很多被工业界和学术界接受的典型算法,截止到目前sklearn库提供7种降维算法。
②降维过程也可以被理解为对数据集的组成成份进行分解(decomposition)的过程,因此sklearn为降维模块命名为decomposition,在对降维算法调用需要使用sklearn.decomposition模块。
③几个常用降维算法
(5)在后续中将通过实例展示如何利用sklearn库提供的分类和降维算法解决具体问题
①31省市居民家庭消费调查
②学生月上网时间分布调查
③人脸图像特征抽取
④图像分割
二、聚类
1.K-means方法
(1)k-means算法以k为参数,把n个对象分成k个簇,使簇内具有较高的相似度,而簇间的相似度较低。
(2)主要处理过程
①随机选择k个点作为初始的聚类中心。
②对于剩下的点,根据其与聚类中心的距离,将其归人最近的簇。
③对每个簇,计算所有点的均值作为新的聚类中心。
④重复2、3直到聚类中心不再发生改变。
(3)举例
①在5个点中随机选取两个聚类中心
②计算距离后,归入簇
③重新计算聚类中心,重新计算距离,将点归入簇
④直到簇的组成稳定
2.K-means应用
(1)问题分析
①数据介绍:现有1999年全国31个省份城镇居民家庭平均每人全年消费性支出的八个主要变量数据,这八个变量分别是:食品、衣着、家庭设备用品及服务、医疗保健、交通和通讯、娱乐教育文化服务、居住以及杂项商品和服务。利用已有数据,对31个省份进行聚类。
②实验目的:通过聚类,了解1999年各个省份的消费水平在国内的情况。
③技术路线:sklearn.cluster.Kmeans
④数据实例
(2)过程
①使用算法:K-means聚类算法
②实现过程
1)建立过程,导入sklearn相关包
import numpy as np
from sklearn.cluster import KMeans
2)加载数据,创建K-means算法实例,并进行训练,获得标签
注1:调用K-Means方法所需参数
1)n_cluster:用于指定聚类中心的个数
2)init:初始聚类中心的初始化方法
3)max_iter:最大的迭代次数
4)一般调用时只给出n_clusters即可,init默认是k-means++,max_iter默认是300
注2:其他参数
1)data:加载的数据
2)label:聚类后数据所属的标签
3)fit_predict():计算簇中心以及为簇分配序号
③输出标签,查看结果
1)将城市按照消费水平n clusters类,消费水平相近的城市聚集在一类中。
import numpy as np
from scipy.sparse import data
from sklearn.cluster import KMeans
def loadData(filePath):
fr = open(filePath, 'r+') # 读写打开一个文本文件
lines = fr.readline() # 一次读取整个文件
retData = [] #存储城市的各项消费信息
retCityName = [] #用于存储城市名称
for line in lines:
items = line.strip().split(",")
retCityName.append(items[0])
retData.append([float(items[i])
for i in range(1, len(items))])
for i in range(1,len(items)):
return retData, retCityName # 返回城市名称及各项消费信息
# 加载数据,创建K-means算法实例,并进行训练,获得标签
if __name__ == '__main__':
data.cityName = loadData('city.txt') #利用loadData方法读取数据,此处文件需自行准备
km = KMeans(n_clusters=3) # 创建实例
lable = km.fit_predict(data) # 调用Kmeans() fit_predict()进行聚类计算
expenses = np.num(km.cluster_centers_,axis=1) #expenses:聚类中心的数值加和,即平均消费水平
# print
CityCluster = [[],[],[]] # 将城市按lable分成设定的簇
for i in range(len(cityName)):
CityCluster[lable[i]].append(data.cityName[i])
for i in range(len(CityCluster)):
print("Expenses:%.2f"%expenses[i]) # 将每个簇的平均花费输出
print(CityCluster[i]) # 将每个簇的城市输出
2)结果展示:
-1:聚成2类:km = KMeans(n_clusters=2)
-2:聚成3类:km= KMeans(n_clusters=3)
-3:聚成4类:km= KMeans(n_clusters=4)
(3)拓展&&改进
①计算两条数据相似性时,Sklearn的K-Means默认用的是欧式距离。虽然还有余弦相似度,马氏距离等多种方法,但没有设定计算距离方法的参数。
②想自定义计算距离的方式时,可更改此处源代码
建议使用scipy.spatial.distance.cdist方法
3.DBSCAN方法
(1)DBSCAN算法是一种基于密度的聚类算法
①聚类的时候不需要预先指定簇的个数最终的
②簇的个数不定
(2)DBSCAN算法将数据点分为三类:
①核心点:在半径Eps内含有超过MinPts数目的点。
②边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内。
③噪音点:既不是核心点也不是边界点的点。
(3)DBSCAN算法流程
①将所有点标记为核心点、边界点或噪声点
②删除噪声点
③为距离在Eps之内的所有核心点之间赋予一条边
④每组连通的核心点形成一个簇
⑤将每个边界点指派到一个与之关联的核心点的簇中(即在哪一个核心点的半径范围之内)
(4)举例:如下13个样本点,使用DBSCAN进行聚类
①取Eps=3,MinPts=3,依据DBSACN对所有点进行聚类(这里使用曼哈顿距离)
②对每个点计算其邻域Eps=3内的点的集合,集合内点的个数超过MinPts=3的点为核心点
③查看剩余点是否在核心点的邻域内,若在,则为边界点,否则为噪声点。
④将距离不超过Eps=3的点相互连接构成一个簇,核心点邻域内的点也会被加入到这个簇中。
4.DBSCAN应用
(1)问题分析
①现有大学校园网的日志数据,为290条大学生的校园网使用情况数据
②数据包括用户ID,设备的MAC地址,IP地址,开始上网时间,停止上网时间,上网时长,校园网套餐等。
③利用已有数据,分析学生上网的模式。
(2)实验目的
通过DBSCAN聚类,分析学生上网时间和上网时长的模式。
(3)技术路线
采用sklearn.cluster.DBSCAN模块
(4)数据实例
(5)实验过程
(6)代码实现
①建立工程,导入sklearn相关包
import numpy as np
from sklearn.cluster import DBSCAN
②DBSCAN主要参数
1)eps:两个样本被看作邻居节点的最大距离
2)min_samples:簇的样本数
3)metric:距离计算方式
例:sklearn.cluster.DBSCAN(eps=0.5,min_samples=5,metric=‘euclidean’)
③对上网时间聚类,创建DBSCAN算法实例,并进行训练,获得标签
附码import numpy as np
import sklearn.cluster
from sklearn import metrics
from sklearn.cluster import DBSCAN
mac2id=dict() # 字典
onlinetimes=[]
f = open('TestData.txt')
for line in f:
mac = line.split(',')[2] # 读取每条中的mac地址
onlinetime = int(line.split(',')[6]) # 读取上网时长
starttime=int(line.split(',')[4].split(' ')[1].split(':')[0]) # 读取开始上网时间
if mac not in mac2id:
mac2id[mac]=len(onlinetimes) # 其中key是mac地址
onlinetimes.append((starttime,onlinetime)) # value是对应mac地址的上网时长以及开始上网时间
else:
onlinetimes[mac2id[mac]]=[(starttime,onlinetime)]
real_X=np.array(onlinetimes).reshape((-1,2))
#对上网时间聚类,创建DBSCAN算法实例,并进行训练,获得标签
X = real_X[:,0:1]
db = sklearn.cluster.DBSCAN(eps=0.01,min_samples=20).fit(X) #调用DBSCAN方法进行训练
labels=db.labels # labels为每个数据的簇标签
print('Labels:')
print(labels) # 打印数据被记上的标签
ratio=len(labels[labels:]==-1)/len(labels) #计算标签为-1,即噪声数据的比例
print('Noise ratio:',format(ratio,'.2%'))
# Number of clusters in labels,ignoring noise if present
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()))
#对上网时长聚类,创建DBSCAN算法实例,并进行训练,获得标签
X = np.log(1+real_X[:,1:])
db = sklearn.DBSCAN(eps=0.1401,min_samples=10).fit(X) #调用DBSCAN方法进行训练
labels=db.labels # labels为每个数据的簇标签
print('Labels:')
print(labels) # 打印数据被记上的标签
ratio=len(labels[labels:]==-1)/len(labels) #计算标签为-1,即噪声数据的比例
print('Noise ratio:',format(ratio,'.2%'))
# Number of clusters in labels,ignoring noise if present
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,':')
count=len(X[labels==i])
mean=np.mean(real_X[labels==i][:,1])
std=np.std(real_X[labels==i][:,1])
print('\\t number of sample:',count)
print('\\t mean of sample:',format(mean,'.1f'))
print('\\t std of sample:',format(std,'.1f'))
④输出标签,查看结果
⑤画直方图,分析实验结果
import matplotlib.pyplot as pet
plt.hist(X,24)
观察得出:上网时间大多聚集在22:00和23:00
⑥数据分布vs聚类
技巧:对数变换
⑦对上网时长聚类,创建DBSCAN算法实例,并进行训练,获得标签
⑧输出标签,查看结果
1)按照上网时长DBSCAN聚了5类,上图所示,显示了每个聚类的样本数量、聚类的均值、标准差。
2)时长聚类效果不如时间的聚类效果明显。
三、降维
1.PCA方法
(1)主成分分析(PCA)
①主成分分析(Principal Component Analysis,PCA)是最常用的一种降维方法,通常用于高维数据集的探索与可视化,还可以用作数据压缩和预处理等。
②PCA可以把具有相关性的高维变量合成为线性无关的低维变量,称为主成分。主成分能够尽可能保留原始数据的信息。
(2)涉及到的相关术语:
①方差:是各个样本和样本均值的差的平方和的均值,用来度量一组数据的分散程度
②协方差:用于度量2个辩论直接的线性相关性程度,罗为0,则可认为二者线性无关。
③协方差矩阵:由变量的协方差值构成的矩阵(对称阵)
④特征向量:描述数据集结构的非零向量
公式如图
A是方阵,v是特征向量,λ是特征值
(3)原理
①矩阵的主成分:其协方差矩阵对应的特征向量,按照对应的特征值大学进行排序
②最大特征值为第一主成分,其次是第二主成分,以此类推
(4)算法过程
(5)主要参数
在sklearn库中,可使用sklearn.decomposition.PCA加载PCA进行降维
①n_components:指定主成分的个数,即降维后数据的维度
②svd_solver:设置特征值分解的方法,默认为’auto’,其他可选有’full’,‘arpack’,‘randomized’,可参考官网API
2.PCA应用实例:鸢尾花数据
————PCA实现高维数据可视化
(1)问题分析
①已知鸢尾花数据是4维的,共三类样本。
②使用PCA实现对鸢尾花数据进行降维,实现在二维平面上的可视化。
(2)代码实现
①建立工程,导入sklearn相关工具包
# 加载matplotlib用于数据可视化
import matplotlib.pyplot as plt
#加载PCA算法包
from sklearn.decomposition import PCA
#加载鸢尾花数据集导入函数
from sklearn.datasets import load_iris
②加载数据并进行降维
③按类别对降维后的数据进行保存
④降维后数据点的可视化
#建立工程,导入sklearn相关工具包
# 加载matplotlib用于数据可视化
import matplotlib.pyplot as plt
#加载PCA算法包
from sklearn.decomposition import PCA
#加载鸢尾花数据集导入函数
from sklearn.datasets import load_iris
#加载数据并进行降维
data = load_iris() #以字典形式加载鸢尾花数据集
y = data.target #使用y表示数据集中的标签
X = data.data #使用x表示数据集中的属性标签
pca = PCA(n_components=2) # 加载PCA算法,设置降维后主成分数目为2
reduced_X = pca.fit_transform(X) #对原始数据进行降维,保存在reduce_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.NMF方法
(1)非负矩阵分解(Non-negative Matrix Factorization,NMF)是在矩阵中所有元素均为非负数约束条件之下的矩阵分解方法
(2)基本思想:给定一个非负矩阵V,NMF能够找到一个非负矩阵W和一个非负矩阵H,使得矩阵W和H的乘积近似等于矩阵V中的值
①W矩阵:基础图像矩阵,相当于从原矩阵V中抽取出来的特征
②H矩阵:系数矩阵
③NMF能够广泛应用于图像分析、文本挖掘和语音处理等领域
(3)矩阵分解优化目标:最小化“W与矩阵H的乘积”和“原始矩阵”之间的差别
①目标函数如下(基于欧氏距离)
②基于KL散度的优化目标,损失函数如下
③W矩阵和H矩阵的求解为迭代算法,在此不详细讲述,参考链接:
http://blog.csdn.net/acdreamers/article/details/44663421/
(4)在sklearn库中,可以使用sklearn.decomposition.NMF加载NMF算法,主要参数有
①n_components:用于指定分解后矩阵的单个维度k
②init:W矩阵和H矩阵的初始化方式,默认为’nndsvdar’
③其他参数参考官网API
4.NMF应用:人脸数据特征提取
(1)问题分析
①目标:已知Olivetti人脸数据共400个,每个数据是64*64大小。由于NMF分解得到的W矩阵相当于从原始矩阵中提取的特征,那么就可以使用NMF对400个人脸数据进行特征提取。
②通过设置k的大小,设置提取的特征的数目。在本实验中设置k=6,随后将提取的特征以图像的形式展示出来。
(2)代码实现
①建立工程,导入sklearn相关工具包
# 加载matplotlib用于数据的可视化
import matplotlib.pyplot as plt
# 加载PCA算法包
from sklearn import decomposition
# 加载Olivetti人脸数据集导入函数
from sklearn.datasets import fetch_olivetti_faces
# 加载RandomState用于创建随机种子
from numpy.random import RandomState
②设置基本参数并加载数据
③设置图像的展示方式
④创建特征提取的对象NMF,使用PCA作为对比
# 建立工程,导入sklearn相关工具包
# 加载matplotlib用于数据的可视化
import matplotlib.pyplot as plt
# 加载PCA算法包
from sklearn import decomposition
# 加载Olivetti人脸数据集导入函数
from sklearn import datasets
# 加载RandomState用于创建随机种子
from numpy.random import RandomState
# 设置基本参数并加载数据
n_row, n_col = 2, 3 # 设置图像展示时的排列情况(2行3列),如图
n_components = n_row*n_col # 设置提取的特征的数目
image_shape = (64,64) #设置人脸数据图片的大小
dataset = datasets.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.gray2019-07-25机器学习无监督学习之聚类 K-Means算法实例 (1999年中国居民消费城市分类)