学习向量量化(LVQ)
是一种无模型的数据点聚类方法。可以用来执行分类任务。
(他很难搞清楚反应变量y和预测器x之间存在什么样的联系。因而在许多现实的场景中,它是作为一种黑箱方法来加以应用的。)
步骤:
- 为数据集里的每个类别选择k个初始的原始向量,如果是一个两分类问题,并且每个分类中有两个原型向量,那我们就需要设置4个初始的原型向量,它们是从输入的数据集中随机选择的。
- 接着进行循环,直到ε值变成0或者预先设定的阈值。我们得确定一个ε值并在每次循环中都使之减小。
- 每次循环中,我们都要采样一个输入点,采用欧式距离找到离它最近的原型向量。然后按下面的操作更新最近邻点的原型向量。
- 如果它的原型向量的类别标签和输入数据点的相同,则在原型向量上增加原型向量和数据点的差异。
- 如果类别标签不同,则在原型向
源码
from sklearn.datasets import load_iris
import numpy as np
from sklearn.metrics import euclidean_distances
data=load_iris()
x=data['data']
y=data['target']
#对变量进行缩放
from sklearn.preprocessing import MinMaxScaler
minmax=MinMaxScaler()
x=minmax.fit_transform(x)
#操作方法
#1.声明LVQ的参数
R=2
n_classes=2
epsilon=0.9
epsion_dec_factor=0.001
#2.定义一个类来保存原型向量
class prototype(object):
def _init_(self,class_id,p_vector,epsilon):
self.class_id=class_id
self.p_vector=p_vector
self.epsilon=epsilon
def updata(self,u_vector,increment=True):
if increment:
#将原型向量向输入向量靠近
self.p_vector=self.p_vector+self.epsilon*(u_vector-self.p_vector)
else:
#使原型向量远离输入向量
self.p_vector=self.p_vector-self.epsilon*(u_vector-self.p_vector)
#3.找到离给定向量最近的原型向量
def find_closest(in_vector,proto_vectors):
closest=None
closest_distance=9999
for p_v in proto_vectors:
distance=euclidean_distances(in_vector,p_v.p_vector)
if distance<closest_diatance:
closest_distance =distance
closest=p_v
return closest
#4.找到最近的原型向量的类别ID
def find_class_id(test_vector,p_vectors):
return find_closest(test_vector,p_vectors).class_id
#5.选择初始化的k×原型向量类别数
p_vectors=[]
for i in range(n_classes):
#选择一个类
y_subset=np.where(y==i)
#为选中的类选择元组
x_subset=x[y_subset]
#获得R个随机下标,介于0~50
samples=np.random.randint(0,len(x_subset),R)
#选择p_vectors
for sample in samples:
s=x_subset[samples]
p=prototype(i,s,epsilon)
p_vectors.append(p)
print ("class_id\t Initial protype vecotr\n")
for p_v in p_vectors:
print(p_v.class_id,'\t',p_v.vector)
#6.利用已有的数据点,执行循环调整原型向量,对新的点进行分类/聚类
while epsilon>=0.01:
#随机采样一个训练实例
rnd_i=np.random.randint(0,149)
rnd_s=x[rnd_i]
target_y=y[rad_i]
#为下一次循环减小ε
epsilon=epsilon-epsilon_dec_factor
#查找与给定最相近的原型向量x
closest_pvector=find_closest(rnd_s,p_vectors)
#更新最相近的原型向量
if target_y==closest_pvector.class_id:
closest_pvector.update(rnd_s)
else:
closest_pvector.update(rnd_s,False)
closest_pvector.epsilon=epsilon
print("class_id \t Final Prototype Vector\n")
for p_vector in p_vectors:
print(p_vector.class_id,'\t',p_vector.p_vector)
#7.下面是测试代码来检查方法是否正确
predicted_y=[find_class_id(instance,p_vectors) for instance in x]
from sklear.metrics import classification_report
print(classification_report(y,predicted_y,target_names=['Iris-Setosa','Iris-Versicolour','Iris-Virginica']))
量上减去原型向量和数据点的差异。