机器学习knnlearn1
import matplotlib.pyplot as plt
import numpy as np
import operator
# 定义一个函数用于创建数据集
def createDataSet():
# 定义特征矩阵,每个元素是一个二维坐标点,代表不同策略数据点的坐标
group = np.array([[20, 3], [15, 5], [18, 1], [5, 17], [2, 15], [3, 20]])
# 定义每个数据点对应的标签,用于区分是服务策略还是平台策略
labels = ["服务策略", "服务策略", "服务策略", "平台策略", "平台策略", "平台策略"]
return group, labels
# classify()函数有4个输入参数:用于分类的输入向量是in_x,输
# 入的训练样本集为datas,标签向量为labels,最后的参数k表示用于
# 选择最近邻居的数目,其中标签向量的元素数目和datas的行数相同。
# 使用欧氏距离公式,计算两个向量点Axy和Bxy之间的
# 实现 K 近邻分类算法的函数
def classify(in_x, datas, labels, k):
# 获取数据集的行数,即数据点的数量 得到了6个点
data_size = datas.shape[0]
# 将要分类的点复制 data_size 次,使其与数据集的形状一致,方便后续计算距离
# 先复制出6个点都是4 17 分别和原始数据进行x轴减法,和y轴减法得到一个新的六个坐标值
diff_mat = np.tile(in_x, (data_size, 1)) - datas
# 计算差值的平方
# 六个新的坐标值 平方一次
sqrt_diff = diff_mat ** 2
# 按行求和,得到每个数据点到待分类点的平方距离
sub_distances = sqrt_diff.sum(axis=1)
# 对平方距离开方,得到实际距离
# [21.2602916254693, 16.278820596099706, 21.2602916254693, 1.0, 2.8284271247461903, 3.1622776601683795]
distances = sub_distances ** 0.5
# 对距离进行排序,返回排序后的索引
# [3, 4, 5, 1, 0, 2]
sorted_distances = distances.argsort()
# 用于存储每个类别的投票数
class_count = {}
# 选取距离最近的 k 个数据点
for i in range(k):
# 获取第 i 个最近数据点的标签
votel_label = labels[sorted_distances[i]]
# 如果该标签已经在字典中,投票数加 1;否则初始化为 1
class_count[votel_label] = class_count.get(votel_label, 0) + 1
# 对投票结果进行排序,按投票数从大到小排列
sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
# 返回投票数最多的类别以及所有类别的投票情况
return sorted_class_count[0][0], class_count
if __name__ == "__main__":
# 调用 createDataSet 函数获取特征矩阵和标签
group, labels = createDataSet()
# 分离服务策略和平台策略的数据点
service_strategy_points = group[:3]
platform_strategy_points = group[3:]
# 绘制服务策略的数据点,设置点的大小为 30,颜色为红色,形状为圆形
plt.scatter(service_strategy_points[:, 0], service_strategy_points[:, 1], s=30, c="r", marker="o")
# 绘制平台策略的数据点,设置点的大小为 100,颜色为蓝色,形状为叉号
plt.scatter(platform_strategy_points[:, 0], platform_strategy_points[:, 1], s=100, c="b", marker="x")
# 显示绘制好的散点图
plt.show()
# 对待分类点 [4, 17] 进行分类,k 值设为 3
result, vote_count = classify([4, 17], group, labels, 3)
print("分类分析结果:")
# 遍历每个类别的投票数并输出
for label, votes in vote_count.items():
print(f"{label} 获得 {votes} 票")
# 输出最终的分类结果
print(f"最终分类结果: {result}")
分类分析结果:
平台策略 获得 3 票
最终分类结果: 平台策略
# np.tile(in_x, (data_size, 1))
# np.tile 是 numpy 库中的一个函数,其作用是将数组重复指定次数来构建新数组。
# 它接收两个参数:第一个参数 in_x 是要重复的数组;第二个参数 (data_size, 1) 是重复的模式。data_size 代表数据集里数据点的数量,也就是 datas 数组的行数;1 表示在列方向上不进行重复。
# 举例来说,若 in_x = [4, 17],data_size = 6,那么 np.tile(in_x, (data_size, 1)) 的结果会是:
import numpy as np
in_x = [4, 17]
data_size = 6
result = np.tile(in_x, (data_size, 1))
print(result)
[[ 4 17]
[ 4 17]
[ 4 17]
[ 4 17]
[ 4 17]
[ 4 17]]
import numpy as np
# 假设这是计算得到的距离数组
distances = np.array([3.2, 1.5, 2.7, 0.8, 4.1])
# 使用 argsort() 方法获取排序后的索引
sorted_distances = distances.argsort()
print("原始距离数组:", distances)
print("排序后的索引:", sorted_distances)
原始距离数组: [3.2 1.5 2.7 0.8 4.1]
排序后的索引: [3 1 2 0 4]
# np.tile(in_x, (data_size, 1)) - datas
# 这里把复制后的 in_x 数组和 datas 数组相减。因为二者形状相同,所以 numpy 会按元素进行减法运算
import numpy as np
in_x = [4, 17]
datas = np.array([[20, 3], [15, 5], [18, 1], [5, 17], [2, 15], [3, 20]])
data_size = datas.shape[0]
diff_mat = np.tile(in_x, (data_size, 1)) - datas
print(diff_mat)
# 相当于把他的x ^ 2 和 y ^ 2
sqrt_diff = diff_mat ** 2
print(sqrt_diff)
# 相当于256+196 = 452 121+144 = 265 以此类推
sub_distances = sqrt_diff.sum(axis=1)
print(sub_distances)
# 相当于给开了平方
distances = sub_distances ** 0.5
print(distances)
sorted_distances = distances.argsort()
print(sorted_distances)
[[-16 14]
[-11 12]
[-14 16]
[ -1 0]
[ 2 2]
[ 1 -3]]
[[256 196]
[121 144]
[196 256]
[ 1 0]
[ 4 4]
[ 1 9]]
[452 265 452 1 8 10]
[21.26029163 16.2788206 21.26029163 1. 2.82842712 3.16227766]
[3 4 5 1 0 2]
欧氏距离公式
二维空间
两点
P
(
x
1
,
y
1
)
P(x_1, y_1)
P(x1,y1) 和
Q
(
x
2
,
y
2
)
Q(x_2, y_2)
Q(x2,y2) 之间的欧氏距离公式:
d
=
(
x
2
−
x
1
)
2
+
(
y
2
−
y
1
)
2
d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}
d=(x2−x1)2+(y2−y1)2
多维空间
对于
n
n
n 维空间中的点
P
(
p
1
,
p
2
,
…
,
p
n
)
P(p_1, p_2, \dots, p_n)
P(p1,p2,…,pn) 和
Q
(
q
1
,
q
2
,
…
,
q
n
)
Q(q_1, q_2, \dots, q_n)
Q(q1,q2,…,qn):
d
(
P
,
Q
)
=
∑
i
=
1
n
(
q
i
−
p
i
)
2
d(P, Q) = \sqrt{\sum_{i=1}^{n} (q_i - p_i)^2}
d(P,Q)=i=1∑n(qi−pi)2
import numpy as np
import operator
"""
Parameters:
无
Returns:
group - 数据集
labels - 分类标签
"""
# 函数说明:创建数据集
def createDataSet():
#六组二维特征
group = np.array([[3,104],[2,100],[1,81],[101,10],[99,5],[98,2]])
#六组特征的标签
labels = ['爱情片','爱情片','爱情片','动作片','动作片','动作片']
return group, labels
"""
Parameters:
inX - 用于分类的数据(测试集)
dataSet - 用于训练的数据(训练集)
labes - 分类标签
k - kNN算法参数,选择距离最小的k个点
Returns:
sortedClassCount[0][0] - 分类结果
"""
# 函数说明:kNN算法,分类器
def classify0(inX, dataSet, labels, k):
#numpy函数shape[0]返回dataSet的行数
dataSetSize = dataSet.shape[0]
#在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
#二维特征相减后平方
sqDiffMat = diffMat**2
#sum()所有元素相加,sum(0)列相加,sum(1)行相加
sqDistances = sqDiffMat.sum(axis=1)
#开方,计算出距离
distances = sqDistances**0.5
#返回distances中元素从小到大排序后的索引值
sortedDistIndices = distances.argsort()
#定一个记录类别次数的字典
classCount = {}
for i in range(k):
#取出前k个元素的类别
voteIlabel = labels[sortedDistIndices[i]]
#dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
#计算类别次数
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#python3中用items()替换python2中的iteritems()
#key=operator.itemgetter(1)根据字典的值进行排序
#key=operator.itemgetter(0)根据字典的键进行排序
#reverse降序排序字典
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#返回次数最多的类别,即所要分类的类别
return sortedClassCount[0][0],classCount
if __name__ == '__main__':
#创建数据集
group, labels = createDataSet()
#测试集
test = [101,20]
#kNN分类
test_class = classify0(test, group, labels, 3)
#打印分类结果
print(test_class)
('动作片', {'动作片': 3})
import numpy as np
"""
Parameters:
filename - 文件名
Returns:
returnMat - 特征矩阵
classLabelVector - 分类Label向量
"""
# 函数说明:打开并解析文件,对数据进行分类:1代表不喜欢,2代表魅力一般,3代表极具魅力
def file2matrix(filename):
#打开文件
fr = open(filename)
#读取文件所有内容
arrayOLines = fr.readlines()
#得到文件行数
numberOfLines = len(arrayOLines)
#返回的NumPy矩阵,解析完成的数据:numberOfLines行,3列
returnMat = np.zeros((numberOfLines,3))
#返回的分类标签向量
classLabelVector = []
#行的索引值
index = 0
for line in arrayOLines:
#s.strip(rm),当rm空时,默认删除空白符(包括'\n','\r','\t',' ')
line = line.strip()
#使用s.split(str="",num=string,cout(str))将字符串根据'\t'分隔符进行切片。
listFromLine = line.split('\t')
#将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵
returnMat[index,:] = listFromLine[0:3]
#根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
if listFromLine[-1] == 'didntLike':
classLabelVector.append(1)
elif listFromLine[-1] == 'smallDoses':
classLabelVector.append(2)
elif listFromLine[-1] == 'largeDoses':
classLabelVector.append(3)
index += 1
return returnMat, classLabelVector
if __name__ == '__main__':
#打开的文件名
filename = "datingTestSet.txt"
#打开并处理数据
datingDataMat, datingLabels = file2matrix(filename)
print(datingDataMat)
print(datingLabels)
[[4.0920000e+04 8.3269760e+00 9.5395200e-01]
[1.4488000e+04 7.1534690e+00 1.6739040e+00]
[2.6052000e+04 1.4418710e+00 8.0512400e-01]
...
[2.6575000e+04 1.0650102e+01 8.6662700e-01]
[4.8111000e+04 9.1345280e+00 7.2804500e-01]
[4.3757000e+04 7.8826010e+00 1.3324460e+00]]
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2, 1, 3, 1, 3, 1, 2, 1, 1, 2, 3, 3, 1, 2, 3, 3, 3, 1, 1, 1, 1, 2, 2, 1, 3, 2, 2, 2, 2, 3, 1, 2, 1, 2, 2, 2, 2, 2, 3, 2, 3, 1, 2, 3, 2, 2, 1, 3, 1, 1, 3, 3, 1, 2, 3, 1, 3, 1, 2, 2, 1, 1, 3, 3, 1, 2, 1, 3, 3, 2, 1, 1, 3, 1, 2, 3, 3, 2, 3, 3, 1, 2, 3, 2, 1, 3, 1, 2, 1, 1, 2, 3, 2, 3, 2, 3, 2, 1, 3, 3, 3, 1, 3, 2, 2, 3, 1, 3, 3, 3, 1, 3, 1, 1, 3, 3, 2, 3, 3, 1, 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 1, 1, 3, 2, 3, 3, 1, 2, 1, 3, 1, 2, 3, 2, 3, 1, 1, 1, 3, 2, 3, 1, 3, 2, 1, 3, 2, 2, 3, 2, 3, 2, 1, 1, 3, 1, 3, 2, 2, 2, 3, 2, 2, 1, 2, 2, 3, 1, 3, 3, 2, 1, 1, 1, 2, 1, 3, 3, 3, 3, 2, 1, 1, 1, 2, 3, 2, 1, 3, 1, 3, 2, 2, 3, 1, 3, 1, 1, 2, 1, 2, 2, 1, 3, 1, 3, 2, 3, 1, 2, 3, 1, 1, 1, 1, 2, 3, 2, 2, 3, 1, 2, 1, 1, 1, 3, 3, 2, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 3, 2, 3, 3, 3, 3, 1, 2, 3, 1, 1, 1, 3, 1, 3, 2, 2, 1, 3, 1, 3, 2, 2, 1, 2, 2, 3, 1, 3, 2, 1, 1, 3, 3, 2, 3, 3, 2, 3, 1, 3, 1, 3, 3, 1, 3, 2, 1, 3, 1, 3, 2, 1, 2, 2, 1, 3, 1, 1, 3, 3, 2, 2, 3, 1, 2, 3, 3, 2, 2, 1, 1, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 3, 3, 3, 2, 3, 2, 1, 1, 1, 1, 1, 3, 2, 2, 1, 2, 1, 3, 2, 1, 3, 2, 1, 3, 1, 1, 3, 3, 3, 3, 2, 1, 1, 2, 1, 3, 3, 2, 1, 2, 3, 2, 1, 2, 2, 2, 1, 1, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 3, 1, 1, 2, 2, 1, 2, 2, 2, 3, 1, 1, 1, 3, 1, 3, 1, 3, 3, 1, 1, 1, 3, 2, 3, 3, 2, 2, 1, 1, 1, 2, 1, 2, 2, 3, 3, 3, 1, 1, 3, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 3, 1, 2, 3, 2, 1, 1, 1, 1, 3, 3, 3, 3, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 2, 3, 2, 1, 2, 2, 2, 3, 2, 1, 3, 2, 3, 2, 3, 2, 1, 1, 2, 3, 1, 3, 3, 3, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 1, 3, 3, 2, 2, 2, 3, 1, 2, 1, 1, 3, 2, 3, 2, 3, 2, 3, 3, 2, 2, 1, 3, 1, 2, 1, 3, 1, 1, 1, 3, 1, 1, 3, 3, 2, 2, 1, 3, 1, 1, 3, 2, 3, 1, 1, 3, 1, 3, 3, 1, 2, 3, 1, 3, 1, 1, 2, 1, 3, 1, 1, 1, 1, 2, 1, 3, 1, 2, 1, 3, 1, 3, 1, 1, 2, 2, 2, 3, 2, 2, 1, 2, 3, 3, 2, 3, 3, 3, 2, 3, 3, 1, 3, 2, 3, 2, 1, 2, 1, 1, 1, 2, 3, 2, 2, 1, 2, 2, 1, 3, 1, 3, 3, 3, 2, 2, 3, 3, 1, 2, 2, 2, 3, 1, 2, 1, 3, 1, 2, 3, 1, 1, 1, 2, 2, 3, 1, 3, 1, 1, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 2, 2, 3, 1, 3, 1, 2, 3, 2, 2, 3, 1, 2, 3, 2, 3, 1, 2, 2, 3, 1, 1, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2, 3, 2, 1, 3, 3, 3, 1, 1, 3, 1, 2, 3, 3, 2, 2, 2, 1, 2, 3, 2, 2, 3, 2, 2, 2, 3, 3, 2, 1, 3, 2, 1, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 1, 2, 2, 2, 3, 2, 3, 3, 1, 2, 1, 1, 2, 1, 3, 1, 2, 2, 1, 3, 2, 1, 3, 3, 2, 2, 2, 1, 2, 2, 1, 3, 1, 3, 1, 3, 3, 1, 1, 2, 3, 2, 2, 3, 1, 1, 1, 1, 3, 2, 2, 1, 3, 1, 2, 3, 1, 3, 1, 3, 1, 1, 3, 2, 3, 1, 1, 3, 3, 3, 3, 1, 3, 2, 2, 1, 1, 3, 3, 2, 2, 2, 1, 2, 1, 2, 1, 3, 2, 1, 2, 2, 3, 1, 2, 2, 2, 3, 2, 1, 2, 1, 2, 3, 3, 2, 3, 1, 1, 3, 3, 1, 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, 3, 3, 1, 1, 3, 2, 1, 2, 1, 2, 2, 3, 2, 2, 2, 3, 1, 2, 1, 2, 2, 1, 1, 2, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 3, 2, 3, 3, 2, 2, 1, 1, 1, 3, 3, 1, 1, 1, 3, 3, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 3, 2, 2, 1, 3, 1, 2, 3, 1, 2, 2, 2, 2, 3, 2, 3, 3, 1, 2, 1, 2, 3, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 3, 3]
, 2, 2, 3, 2, 2, 2, 3, 1, 2, 1, 2, 2, 1, 1, 2, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 3, 2, 3, 3, 2, 2, 1, 1, 1, 3, 3, 1, 1, 1, 3, 3, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 3, 2, 2, 1, 3, 1, 2, 3, 1, 2, 2, 2, 2, 3, 2, 3, 3, 1, 2, 1, 2, 3, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 3, 3]