本帖最后由 dirty 于 2024-8-17 16:24 编辑
本篇讲述机器学习,通过阅读学习笔记,更进一步理解机器学习。本书代码可通过Git 获取。
机器学习分类:监督式学习、非监督式学习、半监督式学习、强化学习、
机器学习常用算法:回归算法、基于实例算法、正则化算法、决策树算法、贝叶斯算法 、基于核的算法、聚类算法、关联规则学习算法、降低维度算法、集成算法。
数据预处理过程:清理、格式化、采样、分解、缩放。
主成分分析(PrincipalComponentAnalysis,PCA)是一种统计方法。通过正交变将一组可能存在相关性的变量转换为一组互不相关的变量,转换后的这组变量称为主成分。PCA是一种降维统计方法,它通过正交变换,将分量相关的原始变量转换为分量不相关的新变量。
聚类,是指将具有相似特征的庞杂对象自动归类到一起,形成一个簇,簇内的对象越相似,聚类的效果越好。它是一种非监督式学习方法,无须预先标注好训练数据。聚类与分类最大的区别就是分类的对象是事先已知的,而聚类的对象是未知的。
K-Means 算法是常用的聚类算法中的“相似度”,是利用距离作为评价指标来衡量的,即通过对象与对象之间的距离远近来判断它们是否属于同一类,也就是说,是否属于同一个簇。K-Means 是最经典、最实用、最简单的聚类算法的代表,K-Means 是一种用于发现给定数据集的K个簇的聚类算法,称其为 K-Means 是因为在发现的K个簇(数据点的集合,簇中的对象是相似的)中,每个的中心都对应该簇中数据的均值。簇的个数K是用户指定的,每个通过其质心(centroid),即簇中所有数据点的中心来描述。K-Means算法代码如下
import numpy as np
import matplotlib.pyplot as plt
# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")
plt.scatter(data[:,0],data[:,1])
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("载入数据")
plt.show()
print(data.shape)
# # 训练模型
# 计算距离
def euclDistance(vector1, vector2):
return np.sqrt(sum((vector2 - vector1)**2))
# 初始化质心
def initCentroids(data, k):
numSamples, dim = data.shape
# k个质心,列数跟样本的列数一样
centroids = np.zeros((k, dim))
# 随机选出k个质心
for i in range(k):
# 随机选取一个样本的索引
index = int(np.random.uniform(0, numSamples))
# 作为初始化的质心
centroids[i, :] = data[index, :]
return centroids
# 传入数据集和k的值
def kmeans(data, k):
# 计算样本个数
numSamples = data.shape[0]
# 样本的属性,第一列保存该样本属于哪个簇,第二列保存该样本跟它所属簇的误差
clusterData = np.array(np.zeros((numSamples, 2)))
# 决定质心是否要改变的变量
clusterChanged = True
# 初始化质心
centroids = initCentroids(data, k)
while clusterChanged:
clusterChanged = False
# 循环每一个样本
for i in range(numSamples):
# 最小距离
minDist = 100000.0
# 定义样本所属的簇
minIndex = 0
# 循环计算每一个质心与该样本的距离
for j in range(k):
# 循环每一个质心和样本,计算距离
distance = euclDistance(centroids[j, :], data[i, :])
# 如果计算的距离小于最小距离,则更新最小距离
if distance < minDist:
minDist = distance
# 更新最小距离
clusterData[i, 1] = minDist
# 更新样本所属的簇
minIndex = j
# 如果样本的所属的簇发生了变化
if clusterData[i, 0] != minIndex:
# 质心要重新计算
clusterChanged = True
# 更新样本的簇
clusterData[i, 0] = minIndex
# 更新质心
for j in range(k):
# 获取第j个簇所有的样本所在的索引
cluster_index = np.nonzero(clusterData[:, 0] == j)
# 第j个簇所有的样本点
pointsInCluster = data[cluster_index]
# 计算质心
centroids[j, :] = np.mean(pointsInCluster, axis = 0)
# showCluster(data, k, centroids, clusterData)
return centroids, clusterData
# 显示结果
def showCluster(data, k, centroids, clusterData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 完整例子!")
return 1
# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Your k is too large!")
return 1
# 画样本点
for i in range(numSamples):
markIndex = int(clusterData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])
# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("显示结果")
plt.show()
# 设置k值,聚类的个数
k = 4
# centroids 簇的中心点
# cluster Data样本的属性,第一列保存该样本属于哪个簇,第二列保存该样本跟它所属簇的误差
centroids, clusterData = kmeans(data, k)
if np.isnan(centroids).any():
print('Error')
else:
print('cluster complete!')
# 显示结果
showCluster(data, k, centroids, clusterData)
print(centroids)
# 做预测
x_test = [0,1]
np.tile(x_test,(k,1))
# 误差
np.tile(x_test,(k,1))-centroids
# 误差平方
(np.tile(x_test,(k,1))-centroids)**2
# 误差平方和
((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1)
# 最小值所在的索引号
np.argmin(((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1))
def predict(datas):
return np.array([np.argmin(((np.tile(data,(k,1))-centroids)**2).sum(axis=1)) for data in datas])
# # 画出簇的作用区域
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1
# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z = z.reshape(xx.shape)
# 等高线图
cs = plt.contourf(xx, yy, z)
# 显示结果
showCluster(data, k, centroids, clusterData)
仿真结果如下:
图1:K-Means 算法仿真
线性回归以一个坐标系中的一个维度为结果,其他维度为特征(如在二维平面坐标系中,以纵轴为结果,横轴为特征)。如果将无数的样本点放在坐标系中,发现它们是围绕着一条直线分布的(类似方程y=kx+b),那么可以采用线性回归进行分析。线性回归的目的,就是寻找一条直线最大程度地“拟合”样本特征和样本输出标记之间的关系。只有一个样本特征的线性回归,,为简单线性回归。如下是一个简单线性回归算法实例
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1., 2., 3., 4., 5.])
y = np.array([1., 3., 2., 3., 5.])
plt.scatter(x, y)
plt.axis([0, 6, 0, 6])
plt.show()
x_mean = np.mean(x)
y_mean = np.mean(y)
num = 0.0
d = 0.0
for x_i, y_i in zip(x, y):
num += (x_i - x_mean) * (y_i - y_mean)
d += (x_i - x_mean) ** 2
a = num/d
b = y_mean - a * x_mean
y_hat = a * x + b
plt.scatter(x, y)
plt.plot(x, y_hat, color='r')
plt.axis([0, 6, 0, 6])
plt.show()
x_predict = 6
y_predict = a * x_predict + b
print(y_predict)
图2:线性回归
通过学习了解了机器学习的概念和基础知识,并演示了K-Means 算法和线性回归算法,对机器学习算法有了进一步认识。