KNN算法
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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236