KNN算法 通过手肘法选取最优参数K(鸢尾花的数据)
实验目的:熟悉手肘法和KNN聚类
实验内容:针对iris数据集(相关信息详见https://archive.ics.uci.edu/ml/datasets/iris),进行KNN 分类模型的python实现,通过手肘法选取最优参数K(K不用超过10),并给出最优参数下以下新数据点的预测类别,并进行可视化(突出新数据点的位置,可视化所有数据的类别):
(1)4.5,3.4, 2.1, 0.8
(2)5.5,2.4, 7.3, 1.5
(3)7.6, 3.3, 5.7, 5.2
核心指标: S S E = ∑ i k ∑ ( p ∈ C i ) ∣ p − m i ∣ 2 SSE = \sum_i ^k\sum_(p\in C_i) |p-m_i|^2 SSE=∑ik∑(p∈Ci)∣p−mi∣2
- Ci是第i个簇
- p是Ci中的样本点
- mi是Ci的质心(Ci中所有样本的均值)
- SSE是所有样本的聚类误差,代表了聚类效果的好坏。
代码
import numpy as np
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt
# 读取数据并进行与预处理
a = pd.read_csv('iris.data', sep=',', names=[i for i in range(5)])
a.drop(4,axis = 1,inplace = True)
a.dropna(axis = 0, how = 'all') # 去掉nan
a = np.array(a)
# k不超过10
meanDispersions = []
for k in range(1,10):
kmeans = KMeans(n_clusters=k)
kmeans.fit(a)
#计算某个与其所属类聚中心的欧式距离
#计算所有点与对应中心的距离的平方和的均值
meanDispersions.append(sum(np.min(cdist(a, kmeans.cluster_centers_, 'euclidean'), axis=1)) / a.shape[0])
plt.plot(K, meanDispersions, 'o-')
plt.xlabel('k')
plt.ylabel('SSE')
plt.title('Selecting k with the Elbow Method')
plt.show()
运行结果
通过手肘法,由图得,应选择k = 3
KNN算法:
(1).计算测试数据点与训练集的欧氏距离并升序排序;
(2). 选取前k个距离中,出现次数最多的类别,该类别即为预测的类别
步骤:
- 将数据集分为30个测试集和120个训练集
- 通过KNN算法预测测试集的类别
- 将预测的类别和真实的类别比较,计算成功率
代码
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
# 通过手肘法选取的k值
k = 3
#将鸢尾花的数据分为测试集与训练集
def irisDivided(iris):
# 取30个随机数
indexs = np.random.permutation(len(iris))
indexs = indexs[0:30]
# 获得测试集
testSet = iris.take(indexs)
# 获得训练集,即原本的数据集-测试集
trainSet =iris.drop(indexs)
return [testSet, trainSet]
def knn(trainSet, testSet, trainResults):
testSet = testSet[:-1]
# 创建和trainSet一样大的矩阵
dist = np.zeros((len(trainSet), len(testSet)))
# 计算欧氏距离
for i in range(len(trainSet)):
for j in range(len(testSet)):
dist[i,j] = np.sqrt(np.sum((trainSet[i,:]-testSet)**2))
# 对距离求和并排序
dist = dist.sum(axis = 1)
indexs = dist.argsort()
#计算各个类别的个数
label_count = []
for i in range(k):
label = trainResults[indexs[i]]
label_count.append(label)
counts = Counter(label_count)
top = counts.most_common(1)
#返回出现次数最多的元素的类别
return (str)(top[0][0])
# 读取数据,并进行数据预处理
iris = pd.read_csv('iris.data', sep = ',', names=[i for i in range(5)])
iris.columns = ['0','1','2','3','species']
# 获得训练集和测试集
sets = irisDivided(iris)
trainSet = sets[1].drop(columns = ['species']).values
trainResults = sets[1]['species'].values
testSets = sets[0].values
# 记录成功的次数
cnt = 0
# 预测测试集的类别并计算成功率
for i in testSets:
ret = knn(trainSet, i, trainResults)
print("predicted : " repr(i[4]) ",actual : " repr(ret))
if i[4] == ret:
cnt = 1
Rate = cnt / len(sets[0]) * 100
print('成功率为:\n',Rate,'%')
运行结果
(1)第一次运行
(2)第二次运行
成功率均在90%以上
(1)4.5,3.4, 2.1, 0.8
(2)5.5,2.4, 7.3, 1.5
(3)7.6, 3.3, 5.7, 5.2
步骤:
- 通过KNN算法对新数据点预测
- 显示预测的结果
- 通过因子分析法对数据进行可视化
代码
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
# 通过手肘法选取的k值
k = 3
def knn(trainSet, testSet, trainResults):
# 创建和trainSet一样大的矩阵
dist = np.zeros((len(trainSet), len(testSet)))
# 计算欧氏距离
for i in range(len(trainSet)):
for j in range(len(testSet)):
dist[i,j] = np.sqrt(np.sum((trainSet[i,:]-testSet)**2))
# 对距离求和并排序
dist = dist.sum(axis = 1)
indexs = dist.argsort()
#计算各个类别的个数
label_count = []
for i in range(k):
label = trainResults[indexs[i]]
label_count.append(label)
counts = Counter(label_count)
top = counts.most_common(1)
#返回出现次数最多的元素的类别
return (str)(top[0][0])
# 读取数据并进行预处理
iris = pd.read_csv('iris.data', sep = ',', names=[i for i in range(5)])
iris.columns = ['0','1','2','3','species']
trainSet = iris.drop(columns = ['species']).values
trainResults = iris['species'].values
# 记录成功的次数
cnt = 0
# 测试集
testSets = [[4.5,3.4,2.1,0.8],
[5.5,2.4,7.3,1.5],
[7.6,3.3,5.7,5.2]]
ret = []
for i in testSets:
ret.append(knn(trainSet, i, trainResults))
testSets = np.c_[testSets, ret]
testSets = pd.DataFrame(testSets, columns = ['0','1','2','3','species'])
# 查看预测结果
print(testSets)
# 通过因子分析法对数据进行可视化
from sklearn import decomposition
fa = decomposition.FactorAnalysis(n_components=2)
X = fa.fit_transform(iris.iloc[:,:-1].values)
color = []
# 给每个点标上颜色
for i in range(len(iris['species'])):
if iris['species'][i] == 'Iris-virginica':
color.append('blue')
elif iris['species'][i] == 'Iris-setosa':
color.append('green')
else:
color.append('red')
# 绘图
plt.scatter(X[:,0],X[:,1],c = color)
X = fa.fit_transform(testSets.iloc[:,:-1].values)
plt.scatter(X[:,0],X[:,1],c = 'black', marker = '*', s = 50, label = 'test')
plt.legend()
plt.show()
运行结果
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhiabcge
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22