学习向量量化与K均值算法类似,但是K均值算法是在原数据没有类别标记的情况下,是一种无监督算法,而学习向量量化算法是在数据集类别标签的这些监督信息来辅助聚类。
LVQ的目标是学得一组n维原型向量,每个原型向量代表一个聚类簇。计算待分类的数据与原型向量的差异度(欧氏距离),距离最近的原型向量的标签作为该数据的分类标签。
LVQ算法过程如下:
生成初始的原型向量
我采用的是鸢尾花数据集,该数据集共三种分类,所以原型向量设为三个,初始的向量,从三个类别数据中随机选择一个数据,作为初始向量。
导入需要的库:
import pandas as pd
import numpy as np
import random
读取数据,并将三种不同标签数据分类:
data = pd.read_csv('iris.data', header = None)
data_setosa = data[data[4]=='Iris-setosa']
data_versicolor = data[data[4]=='Iris-versicolor']
data_virginica = data[data[4]=='Iris-virginica']
根据行索引,随机选择三个数据作为初始原型向量
a = data_setosa.index
b = data_versicolor.index
c = data_virginica.index
i = random.sample(list(a), 1)
j = random.sample(list(b), 1)
k = random.sample(list(c), 1)
P = []#存储原型向量
for z in [i, j, k]:
P.append(np.array(data.loc[z]))#转化为numpy数组存储
依次计算各个测试数据,与原型向量的相似度,相似度高的原型向量作为该数据的标签预测,如果预测标签与原标签一致,则根据该数据修改原型向量的数据,具体过程如下:
设置学习率:
#训练数据数量
n = data.count()[0]
#学习率
learn_rate = 0.01
学习过程:
for z in range(10):#循环训练十次
for i in range(n):#依次选取训练数据
x = np.array(data.loc[i].loc[[0, 1, 2, 3]])
for j in range(3):#分别计算与原型向量的距离
y = P[j][0,0:4]
dist[j] = sum((y - x) ** 2) ** 0.5#采用欧式距离
k = dist.index(min(dist))
label0 = data.loc[i].loc[[4]][4]
label1 = P[k][0,-1]
if label0 == label1:#当预测标签与原标签一致时
p_new = P[k][0,0:4] + learn_rate * (x - P[k][0,0:4])
else:#当预测标签与原标签不一致时
p_new = P[k][0,0:4] - learn_rate * (x - P[k][0,0:4])
P[k][0,0:4] = p_new#修改原型向量
在学习10次后的原型向量如下:
[array([[5.003536028230874, 3.4111351660342106, 1.4660652690773865,
0.2449797582407023, 'Iris-setosa']], dtype=object),
array([[5.871050124424894, 2.7619305511268446, 4.074516745222619,
1.2121162425794136, 'Iris-versicolor']], dtype=object),
array([[6.672309379043307, 3.0192568700218554, 5.680761063621702,
2.0968836739757992, 'Iris-virginica']], dtype=object)]
根据原型向量划分数据集:
new_kind = {'Iris-setosa':[], 'Iris-versicolor':[], 'Iris-virginica':[]}
m = 0#记录正确预测的数据数量
for i in range(n):
x = np.array(data.loc[i].loc[[0, 1, 2, 3]])
for j in range(3):
y = P[j][0,0:4]
dist[j] = sum((y - x) ** 2) ** 0.5
k = dist.index(min(dist))
label_new = P[k][0,-1]
label_old = data.loc[i].loc[[4]][4]
new_kind[label_new].append(data.loc[i])
if label_new == label_old:
m += 1
计算正确率:
right_rate = m / n
正确率达到:
0.9266666666666666