學習向量量化與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