KNN算法是一个用于对数据样本进行分类预测的算法
KNN算法就是根据样本之间的距离,来对新的样本来进行分类
计算过程:将新的样本点,与历史样本点中的每一个样本点进行距离的计算 取前k个距离最近的样本点的分类结果 取分类结果频次最好的二分类项作为新样本的分类。
网络搜索:手动指定不同参数的检索范围,通过网络搜索来寻找最优的超参数或者模型参数
K就表示要取离新样本最近的K个样本进行分类决策
通常我们只提供已有数据的 90 %作为训练样本来训练分类器 ,而使用其余的 10% 数据去测试分类器(测试数据占总数据比例不同也会影响到算法的测试结果),且数据划分是随机的
机械学习中的两种类型参数
在训练之前,需要设置的参数
k值
距离权重
P值
对于寻找最优超参数的过程,称之为网络搜索
模型参数
通过样本训练处的参数
数据归一化:将所有数据的量纲映射到同一尺度下。
1.最值归一化:把所有数据映射到0~1上(数据边界确定,例如学生分数,最低0,最高1)
2.均值方差归一化:把数据归一到均值为0,方差为1的分布中(数据分布没有明确边界,有可能存在极端数据值)
优点:
简单,易于理解,易于实现,无需参数估计,无需训练;
对异常值不敏感(个别噪音数据对结果的影响不是很大);
适合对稀有事件进行分类;
适合于多分类问题(multi-modal,对象具有多个类别标签),KNN要比SVM表现要好;
缺点:
对测试样本分类时的计算量大,内存开销大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本;
可解释性差,无法告诉你哪个变量更重要,无法给出决策树那样的规则;
K值的选择:最大的缺点是当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进;
KNN是一种消极学习方法、懒惰算法。
KNN算法是一个用于对数据样本进行分类预测的算法
#KNN算法
import numpy as np
import matplotlib.pyplot as plt
a_x = [np.random.random() * 10 for i in range(10)]
a_y = [np.random.random() * 10 for i in range(10)]
b_x = [np.random.random() * 10 for i in range(10)]
b_y = [np.random.random() * 10 for i in range(10)]
plt.scatter(a_x,a_y,color = 'r' , marker='+')
plt.scatter(b_x,b_y,color = 'b' , marker='o')
plt.show()
#新增样本
new_data = [np.random.random() * 10 for i in range(10)]
plt.scatter(a_x,a_y,color = 'r' , marker='+')
plt.scatter(b_x,b_y,color = 'b' , marker='o')
plt.scatter(new_data[0],new_data[1],color='g')
plt.show()
#KNN就是根据样本点之间的距离进行分类
#K就表示要取离新样本点最近的K个样本进行分类决策
#实现
train_data = np.array([np.random.random() * 10 for i in range(10)])
train_label = np.array([0,0,0,0,0,1,1,1,1,1])
print('train_data:',train_data)
print('train_label:',train_label)
test_data = [np.random.random() * 10]
distances = []
#计算两个样本之间的距离
for data in train_data:
distances.append(np.sqrt(np.sum((data - test_data)**2)))
#首先对样本进行从小到大的排序,并返回排序后的,原始数据的索引
nearest = np.array(distances).argsort()
K = 3
predict_label = [train_label[i] for i in nearest[:K]]
print(predict_label)
from collections import Counter
votes = Counter(predict_label)
```
result = votes.most_common()[0][0]
```
print(result)
tr_data = np.array([np.random.random() * 10 for i in range(20)])
tr_data = tr_data.reshape((10,2))
print(tr_data)
n_data = np.array([np.random.random() * 10,np.random.random() * 10])
print(n_data)
axis = 1 ,是以行为单位 , 如果不加就会将所有的数进行求和
s = np.sqrt(np.sum((tr_data - n_data)**2,axis = 1)).argsort()
print(s)
pre_label = [train_label[i] for i in s[:K]]
res = Counter(pre_label).most_common()[0][0]
print(res)
plt.scatter(tr_data[train_label==0,0] , tr_data[train_label==0,1],color = 'r' , marker='+')
plt.scatter(tr_data[train_label==1,0] , tr_data[train_label==1,1],color = 'r' , marker='+')
plt.scatter(n_data[0],n_data[1],color='g')
plt.show()
from knn import KNNClassfer
from sklean.neighbors import KNeighborsClassifier
knn_clf = KNNClassfer(k = 3)
knn_clf.fit(tr_data,train_label)
x = knn_clf.predit(n_data)
print(x)
封装的KNN算法
import numpy as np
from collections import Counter
class KNNClassfer:
def __init__(self, k=3):
self.k = k
def fit(self, train_data, train_label):
self.train_data = train_data
self.train_label = train_label
def predit(self, test_data):
predit_label = [self.train_label[i] for i in np.sqrt(np.sum((self.train_data - test_data)**2,axis = 1)).argsort()[:self.k]]
return Counter(predit_label).most_common()[0][0]
数据集分割
from sklearn.model_selection import trai_test_spit
#加载数据
x = iris.data
#查看类别的目标值
y = iris.target
#打乱下标
np.random.permutation(len(x))
#随机数种子,以666作为种子随机,是保证以后每次随机结果都是一样的
train_data, test_data, train_label, test_label = train_test_split(x , y, test_size = 0.2, random_state=666)
模型训练
from sklearn.metrics import accuracy_score
accuracy_score(test_label, predict_label)
knn_clf.score(test_data, test_label)
超参数:在模型运行前需要决定的参数
模型参数:算法过程中学习的参数
KNN中的超参数
1.K值
2.p值
3.距离权重
找到最好的K值
best_k = 0
best_score = 0.0
for k in range(1,11):
knn_clf = KNeighborsClassifier(n_neighbors = k)
knn_clf.fit(train_data, train_label)
score = knn_clf.score(test_data, test_label)
if score > best_score:
best_score = score
best_k = k
print('best_k:',best_k)
print('best_score:',best_score)
距离权重
best_k = 0
best_method = ''
best_score = 0.0
for method in ['uniform','distance']:
for k in range(1,11):
knn_clf = KNeighborsClassifier(n_neighbors = k)
knn_clf.fit(train_data, train_label)
score = knn_clf.score(test_data, test_label)
if score > best_score:
best_method = method
best_score = score
best_k = k
print('best_k:',best_k)
print('best_score:',best_score)
print('best_method:',best_method)
寻找最好的P参数
best_k = 0
best_p = 0
best_score = 0.0
for k in range(1,11):
for p in range(1,6):
knn_clf = KNeighborsClassifier(n_neighbors = k, weights='distance',p=p)
knn_clf.fit(train_data, train_label)
score = knn_clf.score(test_data, test_label)
if score > best_score:
best_p = p
best_score = score
best_k = k
print('best_k:',best_k)
print('best_score:',best_score)
print('best_p:',best_p)
网格搜索
grid_param = [
{
"weight":['uniform'],
"n_neighbors":[i for i in range(1,11)]
},
{
"weight":['distance'],
"n_neighbors":[i for i in range(1,11)],
"p":[i for i in range(1,6)]
}
]
最值归一化
x_scaler = (x - np.min(x)) / (np.max(x) - np.min(x))
向量最值归一化
X = np.random.randint(1,100,200)
X = np.array(X ,dtype='float')
X = X.reshape(100,2)
#X[:,0] 是对第1列进行操作
X[:,0] = (X[:,0] - np.min(X[:,0])) /(np.max(X[:,0]) - np.min(X[:,0]))
X[:,1] = (X[:,1] - np.min(X[:,1])) /(np.max(X[:,1]) - np.min(X[:,1]))
均值方差归一化
(std_x - np.mean(std_x)) / np.var(std_x)
sklearn的归一化
from sklearn.preprocessing import StandardScaler
先进行归一化,再进行模型计算
std_train_data = std_scaler.transform(train_data)
std_test_data = std_scaler.transform(test_data)