KNN算法(K-NearestNeighbor)
特点:分类算法,基于实例学习,属于懒惰学习,无训练阶段,数据集事先已有分类和特征值,待收到新样本后直接进行处理。
思路:如果一个样本在特征空间中的k个最邻近的样本中的大多数都属于某个类别,则该样本也划分为这个类别。
算法描述:
- 计算测试数据与各个训练数据之间的距离;
- 按距离递增关系排序;
- 选取距离最小的k个点;
- 确定前k个点所在类别的出现概率;
- 返回频率最高的类别作为测试数据的预测分类。
关于k的取值:
k值过小,受噪声影响大,模型复杂,易过拟合;
k值过大,学习的近似误差增大,较远实例使预测发生错误;
取法:k=1开始,使用检验集估计分类器的误差率,每次k+1。
关于距离的选取:
常用的有:欧氏距离、余弦值、相关度、曼哈顿距离等。
总结:
- 简单有效的分类算法,易于实现;
- 样本集很大时,需要大量存储空间,且需计算测试集与所有训练集的距离,非常耗时;
- 对于样本不均衡的数据效果不好,改进方法是对k个近邻数据赋予权重,距离越小权值越大;
- 时间复杂度O(n),一般适用于样本较少的数据集,当数据量大时,可以将数据以树的形式呈现提高速度,如kd-tree、ball-tree。
代码实现:
from numpy import *
import operator
def classify(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize, 1)) - dataSet #求inX与训练集各个实例的差
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5 # 求欧式距离
sortedDistIndicies = distances.argsort() # 取排序的索引,用于排label
classCount={}
for i in range(k):
voteILabel = labels[sortedDistIndicies[i]]
classCount[voteILabel]=classCount.get(voteILabel,0)+1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] # 取最多的分类
group = array([[1,1.1],[1,1],[0,0],[0,0.1]]) # 训练集
labels = ['A','A','B','B'] # 训练集分类
print classify([1.2,1.3], group, labels, 3) # 对数据点[0,0]分类
K-Means算法
特点:聚类算法,将样本聚类成k个簇,无监督学习。
算法流程:
1、随机选取k个聚类质心点;
2、重复以下过程直至收敛{
对于每个样例,计算其应该属于的类(距离哪个类的质心点最近);
对于每个类,重复计算其质心点(对所有该类的样本坐标取平均);
}
代码实现:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
plt.figure()
random_state = 170
X,y = make_blobs(n_samples=200,random_state=random_state) # 使用sklearn提供的数据
y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X)
plt.scatter(X[:,0],X[:,1],c=y_pred)
plt.show()