機械学習 11 - プロトタイプ クラスタリングのための学習ベクトル量子化 (LVQ)


序文

Zhou Zhihua の "Machine Learning" では、学習ベクトル量子化 (LVQ) が紹介されています。ご覧のとおり、LVQ はプロトタイプベースのクラスタリング アルゴリズムでもあります。K 平均法とは異なり、LVQ はサンプルの実クラス ラベルを使用してクラスタリングを支援します。まず、LVQ は以下に基づいています。サンプルのクラスをマーキングし、クラスタのプロトタイプとして各カテゴリからサンプルをランダムに選択し、プロトタイプの特徴ベクトル グループを形成します。その後、サンプル セットからサンプルをランダムに選択し、それとサンプル内の各ベクトルの間の距離を計算します。そして、その分割結果として最も距離が小さいプロトタイプベクトルが位置するクラスタを選択し、実クラスラベルと比較する。

LVQ アルゴリズムの流れは次のとおりです。

ここに画像の説明を挿入
一般的なプロセスは次のとおりです。

  1. 合計 q カテゴリがあると仮定した統計サンプルのカテゴリ、およびプロトタイプ ベクトルとして初期化されたラベルは {t1,t2,...,tq} です。サンプルから q 個のサンプル点プロトタイプ ベクトル {p1, p2 ,..., pq} をランダムに選択します。学習率 a、値の範囲 (0,1) を初期化します。
  2. サンプル集合からサンプル(x,y)をランダムに選択し、サンプルとq個のプロトタイプベクトル間の距離(ユークリッド距離)を計算し、サンプルからの距離が最も小さいプロトタイプベクトルpを求め、サンプルのマークyを判定します。とプロトタイプ ベクトル ラベル t は一貫していません。一貫性がある場合は、p' = p + a*(xp) に更新し、そうでない場合は、p' = p - a*(x - p) に更新します。
  3. 停止条件が満たされるまで手順 2 を繰り返します。(最大反復回数に達した場合など)
  4. q 個のプロトタイプ ベクトルを返します。

1. 学習ベクトル量子化 (LVQ) は、単純に 2 つの分類を実装します。

  1. データ作成
    ここでは比較的小規模なサンプルデータを使用しており、サンプルデータは全部で 13 個あり、各サンプルの特徴は密度、糖度、品質の良し悪しです。良いか悪いかのラベルは、Y と N です。
import re
import math
import numpy as np
import pylab as pl #pylab模块多用折线图和曲线图上 
# import matplotlib.pyplot as plt

data = \
"""1,0.697,0.46,Y,
2,0.774,0.376,Y,
3,0.634,0.264,Y,
4,0.608,0.318,Y,
5,0.556,0.215,Y,
6,0.403,0.237,Y,
7,0.481,0.149,Y,
8,0.437,0.211,Y,
9,0.666,0.091,N,
10,0.639,0.161,N,
11,0.657,0.198,N,
12,0.593,0.042,N,
13,0.719,0.103,N"""
# data
  1. データの前処理
# 数据简单处理
a = re.split(',', data.strip(" "))# 数据划分
dataset = []     # dataset:数据集
for i in range(int(len(a)/4)):
    temp = tuple(a[i * 4: i * 4 + 4])
    dataset.append(watermelon(temp))
  1. 距離を計算する
# 计算欧几里得距离,a,b分别为两个元组
def dist(a, b):
    return math.sqrt(math.pow(a[0]-b[0], 2)+math.pow(a[1]-b[1], 2))
  1. アルゴリズムモデルの確立
# 算法模型
def LVQ(dataset, a, max_iter):
    # 统计样本一共有多少个分类
    T = list(set(i.good for i in dataset))
    print('样本分类总数', T)
    # 随机产生原型向量
    P = [(i.density, i.sweet,i.good) for i in np.random.choice(dataset, 2)]
    print('原型向量', P)
    while max_iter>0:
        # 从样本集dataset中随机选取一个样本X
        X = np.random.choice(dataset, 1)[0]
        #print(i for i in P)
        #index = np.argmin(dist((X.density, X.sweet), (i[0], i[1])) for i in P)
        # 找出P中与X距离最近的原型向量P[index]
        m = []
        for i in range(len(P)):
            m.append(dist((X.density, X.sweet),(P[i][0],P[i][1])))
        index = np.argmin(m)
        #print('m为',m)
        #print ('index为',index)
        # 获得原型向量的标签t,并判断t是否与随机样本的标签相等
        t = P[index][2]
        #print('t为',t)
        if t == X.good:
            P[index] = ((1 - a) * P[index][0] + a * X.density, (1 - a) * P[index][1] + a * X.sweet,t )
        else:
            P[index] = ((1 + a) * P[index][0] - a * X.density, (1 + a) * P[index][1] - a * X.sweet,t )
        max_iter -= 1
    return P

ここに画像の説明を挿入

  1. plの図面
# 画图
def draw(C, P):
    colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
    for i in range(len(C)):
        coo_X = []    # x坐标列表
        coo_Y = []    # y坐标列表
        for j in range(len(C[i])):
            coo_X.append(C[i][j].density)
            coo_Y.append(C[i][j].sweet)
        pl.scatter(coo_X, coo_Y, marker='x', color=colValue[i%len(colValue)], label=i)
    # 展示原型向量
    P_x = []
    P_y = []
    for i in range(len(P)):
        P_x.append(P[i][0])
        P_y.append(P[i][1])
        pl.scatter(P[i][0], P[i][1], marker='o', color=colValue[i%len(colValue)], label="vector")
    pl.legend(loc='upper right')
    pl.show()

ここに画像の説明を挿入

  1. 学習ベクトル量子化 (LVQ) はプロトタイプ ベクトルを出力します
def train_show(dataset, P):
    C = [[] for i in P]
    for i in dataset:
        C[i.good == 'Y'].append(i)
    return C

P = LVQ(dataset, 0.1, 2000)
C = train_show(dataset, P)
draw(C, P)
print('P为',P)
# print('C为',C)

ここに画像の説明を挿入

  • LVQ(dataset, a, max_iter) では、dataset はサンプル セット、a はサンプルとプロトタイプ ベクトル間の距離、max_iter は最大反復数です。

2. 3 つの分類を実現するためのベクトル量子化 (LVQ) の学習

  1. データセットの生成
from sklearn import datasets
import matplotlib.pyplot as plt
import numpy as np

X=datasets.make_blobs(n_samples=1000,centers=3) #1000个样本点分为3类
# X

ここに画像の説明を挿入

  1. プロトタイプベクトルを初期化する
    P=np.zeros((q,col)) #原型向量
    for i in range(q):   #初始化原型向量
        index=np.where(sample[1]==Label[i])[0]
        choose=np.random.randint(0,len(index),1)
        P[i,:]=sample[0][index[choose],:]
  1. 研修科目
    for i in range(1000):   #训练
        choose=np.random.randint(0,row,1) #随机选取一个样本
        dis=np.linalg.norm(sample[0][choose,:]-P,axis=1) #计算与原型向量的距离
        y=dis.tolist().index(min(dis))  #获取距离最近的原型向量下标
        if Label[y]==sample[1][choose]: #更新原型向量
            P[y,:]=P[y,:]+eta*(sample[0][choose,:]-P[y,:])
        else:
            P[y,:]=P[y,:]-eta*(sample[0][choose,:]-P[y,:])
  1. 分類マーク
    IDX=[]  #分类标记
    for i in sample[0]:  #以距离最近的标记为样本的类别
        D=np.linalg.norm(i-P,axis=1)
        y=D.tolist().index(min(D))
        IDX.append(Label[y])
    plot(IDX,sample[0],max(Label)+1,P)
    return P
  1. 描く
def plot(a,X,k,p):  #绘画板块
    m=k
    for j in range(m):
        index=[i for i,v in enumerate(a) if v==j]
        x=[]
        y=[]
        for k in index:
            x.append(X[k][0])
            y.append(X[k][1])
        plt.scatter(x,y)
    plt.scatter(p[:,0],p[:,1],marker='x')
    plt.show()
  • 完全なコード
from sklearn import datasets
import matplotlib.pyplot as plt
import numpy as np

X=datasets.make_blobs(n_samples=1000,centers=3) #1000个样本点分为3类

def lvq(sample,q,Label,eta):
    if q!=len(Label):
        return 0
    row,col=np.shape(sample[0]) #获取样本集的规格
    P=np.zeros((q,col)) #原型向量
    for i in range(q):   #初始化原型向量
        index=np.where(sample[1]==Label[i])[0]
        choose=np.random.randint(0,len(index),1)
        P[i,:]=sample[0][index[choose],:]
    for i in range(1000):   #训练
        choose=np.random.randint(0,row,1) #随机选取一个样本
        dis=np.linalg.norm(sample[0][choose,:]-P,axis=1) #计算与原型向量的距离
        y=dis.tolist().index(min(dis))  #获取距离最近的原型向量下标
        if Label[y]==sample[1][choose]: #更新原型向量
            P[y,:]=P[y,:]+eta*(sample[0][choose,:]-P[y,:])
        else:
            P[y,:]=P[y,:]-eta*(sample[0][choose,:]-P[y,:])
    IDX=[]  #分类标记
    for i in sample[0]:  #以距离最近的标记为样本的类别
        D=np.linalg.norm(i-P,axis=1)
        y=D.tolist().index(min(D))
        IDX.append(Label[y])
    plot(IDX,sample[0],max(Label)+1,P)
    return P
def plot(a,X,k,p):  #绘画板块
    m=k
    for j in range(m):
        index=[i for i,v in enumerate(a) if v==j]
        x=[]
        y=[]
        for k in index:
            x.append(X[k][0])
            y.append(X[k][1])
        plt.scatter(x,y)
    plt.scatter(p[:,0],p[:,1],marker='x')
    plt.show()

テストコード: lvq(X,5,[0,1,0,1,2],0.5)

出力は次のとおりです。
ここに画像の説明を挿入
ここに画像の説明を挿入


要約する

K 最近傍法の欠点の 1 つは、トレーニング データセット全体を保持する必要があることです。ただし、Learning Vector Quantization (略して LVQ) は、保持するトレーニング インスタンスの数を選択し、それらのインスタンスがどのようなものであるかを正確に知ることができる人工ニューラル ネットワーク アルゴリズムです。

LVQの表現は、コードブック ベクトルのコレクションです。これらは最初にランダムに選択され、学習アルゴリズムの複数回の反復にわたってトレーニング データセットを最適に要約するように適応されます(実行ごとに結果が異なるため、目的の結果を達成するまでに複数回の反復が必要になります)。学習後、コードブック ベクトルを使用して、K 最近傍法などの予測を行うことができます。最も類似した近傍 (最も一致するコードブック ベクトル) は、各コードブック ベクトルと新しいデータ インスタンスの間の距離を計算することによって見つかります次に、最も一致するユニットのクラス値または (回帰の場合は実際の値) が予測として返されます。同じ範囲 (たとえば 0 から 1 の間) になるようにデータを再スケーリングすると、最良の結果が得られます。

おすすめ

転載: blog.csdn.net/ex_6450/article/details/126437602