KNN算法介绍
KNN(K-Nearest Neighbor)是最简单的机器学习算法之一,k近邻法是一种基本的分类和回归方法,是监督学习方法里的一种常用方法。k近邻算法假设给定一个训练数据集,其中的实例类别已定。分类时,对新的实例,根据其k个最近邻的训练实例类别,通过多数表决等方式进行预测。可以用于分类和回归,是一种监督学习算法。它的思路是这样,如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。也就是说,该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
数据集的采集
读取数据集
由于数据集为手机拍摄,且均为统一大小即不用对图像归一处理,直接读取图像
def lode_data():
data=[]
labels=[]
for filename in os.listdir(r"data/car"):
filenames = 'data/car/'+filename
img = cv2.imread(filenames,1)
data.append(img.flatten())
labels.append('car')
for filename in os.listdir(r"data/cycle"):
filenames = 'data/cycle/'+filename
img = cv2.imread(filenames,1)
data.append(img.flatten())
labels.append('cycle')
data = np.array(data)
labels = np.array(labels)
print(labels)
return data, labels
把数据集以8:2分为训练集和测试集,并随机打乱
def separate_dataset(dataset, labels, spearate_rate=0.8):
train_data = []
train_labels = []
test_data = []
test_labels = []
#随机打乱数据集
dataset_tmp = list(range(len(dataset)))
random.shuffle(dataset_tmp)
train_data_index = dataset_tmp[:int(len(dataset)*spearate_rate)]
test_data_index = dataset_tmp[int(len(dataset)*spearate_rate):]
for i in train_data_index:
train_data.append(dataset[i])
train_labels.append(labels[i])
for i in test_data_index:
test_data.append(dataset[i])
test_labels.append(labels[i])
train_data = np.array(train_data)
train_labels = np.array(train_labels)
test_data = np.array(test_data)
test_labels = np.array(test_labels)
return train_data, train_labels, test_data, test_labels
k-近邻算法
输入4个参数 ,首先将图像得到的矩阵转化为一维向量,
if len(img.shape) > 1:
img = img.flatten()
用于分类的输入向量是img,输入的训练样本集为dataset,标签向量为lavels,最后的参数k表示用于选择最近邻居的数目,其中标签向量的元素数目和矩阵dataset的行数相同。
def classify0(img, dataset, labels, k):
diffMat = np.tile(img, (dataset.shape[0], 1)) - dataset
sqDiffMat = (diffMat ** 2).sum(axis=1)
distences = sqDiffMat ** 0.5
sorted_distences = distences.argsort()
classcount={}
for i in range(k):
vote_label = labels[sorted_distences[i]]
classcount[vote_label] = classcount.get(vote_label, 0) + 1
sortedClassCount = sorted(classcount.items(),
key = operator.itemgetter(1), reverse = True)
return sortedClassCount[0][0]
测试训练集
令k=2时,
测试正确的数据集除以所有的测试集则为测试的准确率
def test(train_data, train_labels, test_data, test_labels, k):
right = 0
for i in range(len(test_data)):
if classify0(test_data[i], train_data, train_labels, k) == test_labels[i]:
right+=1
return right
data, labels = lode_data()
train_data, train_labels, test_data, test_labels = separate_dataset(data, labels)
right = test(train_data, train_labels, test_data, test_labels, 2)
accuracy = right/len(test_labels)
print(f"accuracy = {accuracy}")
多个k值进行测试
for i in tqdm(range(0,7)):
right = test(train_data, train_labels, test_data, test_labels, i + 1)
accuracy = right/len(test_labels)
accuracy2.append(accuracy)
plt.plot(range(len(train_data) - 1),accuracy2)
plt.ylabel('accuracy')
plt.xlabel('k')
plt.show()
由于数据集较少,则实验结果较为偏差
结果分析
由结果可以看出KNN中的K值选取对K近邻算法的结果有较大影响,当K值增大则精度会减小,而如果数据集大增大则准确率会大幅提高,而对K值则以最小值逐步上调来寻找准确度最高的训练