乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      廣義學習矢量量化(GLVQ)分類算法介紹和代碼實現(xiàn)

       漢無為 2023-03-14 發(fā)布于湖北
      圖片
      廣義學習矢量量化(Generalized Learning Vector Quantization,GLVQ)是一種基于原型的分類算法,用于將輸入數(shù)據(jù)分配到先前定義的類別中。GLVQ是LVQ(Learning Vector Quantization)的一種擴展形式,LVQ在特征空間中利用一組代表性原型來對輸入數(shù)據(jù)進行分類。
      圖片

      GLVQ

      GLVQ是一種監(jiān)督學習算法,屬于學習矢量量化(LVQ)算法的范疇。LVQ算法是一種基于原型的分類算法,它根據(jù)類與代表每個類的一組原型(也稱為范例或參考向量)的距離將類分配給數(shù)據(jù)點。GLVQ通過允許類之間更靈活的決策邊界來擴展LVQ,這在數(shù)據(jù)類不可線性可分時尤其有用。
      GLVQ與LVQ的主要區(qū)別在于,GLVQ將類別之間的區(qū)別表示為權(quán)重矩陣,而不是在特征空間中使用距離度量。GLVQ中的權(quán)重矩陣可以從數(shù)據(jù)中學習,使得分類器可以自適應(yīng)地調(diào)整權(quán)重,以便更好地區(qū)分不同的類別。此外,GLVQ還可以使用非線性映射將輸入數(shù)據(jù)投影到一個新的特征空間中,這樣就可以更好地處理非線性分類問題。
      GLVQ可以應(yīng)用于各種分類問題,尤其是在需要處理高維度數(shù)據(jù)和非線性分類問題的情況下。以下是GLVQ的一些具體應(yīng)用:
      1. 模式識別:GLVQ可以用于模式識別,例如人臉識別、手寫數(shù)字識別、圖像分類等。通過將輸入數(shù)據(jù)映射到原型向量空間,GLVQ可以在原型向量之間尋找最佳匹配,實現(xiàn)分類的目的。
      2. 計算機視覺:GLVQ可以用于計算機視覺領(lǐng)域的各種任務(wù),例如目標檢測、圖像分割、物體跟蹤等。GLVQ可以將輸入數(shù)據(jù)投影到一個低維空間,然后利用原型向量來分類數(shù)據(jù)。
      3. 生物醫(yī)學工程:GLVQ可以應(yīng)用于生物醫(yī)學工程領(lǐng)域,例如基因表達數(shù)據(jù)分析、心電信號分類等。GLVQ可以用于分析和分類復雜的生物醫(yī)學數(shù)據(jù),幫助研究人員識別疾病的特征并做出預測。
      4. 自然語言處理:GLVQ可以用于自然語言處理領(lǐng)域,例如文本分類、情感分析、機器翻譯等。GLVQ可以通過將文本數(shù)據(jù)映射到原型向量空間來實現(xiàn)文本分類和情感分析等任務(wù)。
      GLVQ的目標是學習一個權(quán)重矩陣,該矩陣將輸入向量映射到類別空間中的向量。該映射可以通過最小化一個目標函數(shù)來學習,該目標函數(shù)將輸入向量映射到它們正確的類別向量的距離最小化。
      具體來說,GLVQ學習一個由原型向量組成的集合,其中每個原型向量代表一個類別。對于一個新的輸入向量,GLVQ計算該向量與每個原型向量之間的距離,并將其分配給與其距離最近的原型向量所代表的類別。GLVQ可以根據(jù)分類的準確性調(diào)整原型向量的位置,以便更好地區(qū)分不同的類別。
      GLVQ有許多變體,包括適應(yīng)性GLVQ(Adaptive GLVQ)、增強型GLVQ(Enhanced GLVQ)和概率GLVQ(Probabilistic GLVQ),它們在權(quán)重矩陣的形式、目標函數(shù)和學習算法等方面有所不同。這些變體廣泛應(yīng)用于模式識別、計算機視覺、語音識別等領(lǐng)域,以解決各種分類問題。

      數(shù)學解釋和python代碼

      廣義學習矢量量化(Generalized Learning Vector Quantization,GLVQ)的分類原理是將輸入樣本映射到原型向量上,并找到距離最近的原型向量,將輸入樣本分配給與其距離最近的原型向量所代表的類別。
      圖片
      在 GLVQ 中,每個類別都有一個原型向量,表示該類別在特征空間中的位置。輸入樣本與原型向量之間的距離可以通過歐幾里得距離或曼哈頓距離等度量方法來計算。下圖為二元分類的代碼
       # normalize the data
       def normalization(self, input_data):
           minimum = np.amin(input_data, axis=0)
           maximum = np.amax(input_data, axis=0)
           normalized_data = (input_data - minimum)/(maximum - minimum)
           return normalized_data
       
       # define prototypes
       def prt(self, input_data, data_labels, prototype_per_class):
       
           # prototype_labels are
           prototype_labels = np.unique(data_labels)
           prototype_labels = list(prototype_labels) * prototype_per_class
       
           # prototypes are
           prt_labels = np.expand_dims(prototype_labels, axis=1)
           expand_dimension = np.expand_dims(np.equal(prt_labels, data_labels),
                                             axis=2)
       
           count = np.count_nonzero(expand_dimension, axis=1)
           proto = np.where(expand_dimension, input_data, 0)
           prototypes = np.sum(proto, axis=1)/count
       
           self.prt_labels = prototype_labels
           return self.prt_labels, prototypes
       # define euclidean distance
       def euclidean_dist(self, input_data, prototypes):
           expand_dimension = np.expand_dims(input_data, axis=1)
           distance = expand_dimension - prototypes
           distance_square = np.square(distance)
           sum_distance = np.sum(distance_square, axis=2)
           eu_dist = np.sqrt(sum_distance)
           return eu_dist
       
       # define d_plus
       def distance_plus(self, data_labels, prototype_labels,
                         prototypes, eu_dist):
           expand_dimension = np.expand_dims(prototype_labels, axis=1)
           label_transpose = np.transpose(np.equal(expand_dimension, data_labels))
       
           # distance of matching prototypes
           plus_dist = np.where(label_transpose, eu_dist, np.inf)
           d_plus = np.min(plus_dist, axis=1)
       
           # index of minimum distance for best matching prototypes
           w_plus_index = np.argmin(plus_dist, axis=1)
           w_plus = prototypes[w_plus_index]
           return d_plus, w_plus, w_plus_index
       
       # define d_minus
       def distance_minus(self, data_labels, prototype_labels,
                          prototypes, eu_dist):
           expand_dimension = np.expand_dims(prototype_labels, axis=1)
           label_transpose = np.transpose(np.not_equal(expand_dimension,
                                                       data_labels))
       
           # distance of non matching prototypes
           minus_dist = np.where(label_transpose, eu_dist, np.inf)
           d_minus = np.min(minus_dist, axis=1)
       
           # index of minimum distance for non best matching prototypes
           w_minus_index = np.argmin(minus_dist, axis=1)
           w_minus = prototypes[w_minus_index]
           return d_minus, w_minus, w_minus_index
      圖片
       # define classifier function
       def classifier_function(self, d_plus, d_minus):
          classifier = (d_plus - d_minus) / (d_plus + d_minus)
          return classifier
       
       # define sigmoid function
       def sigmoid(self, x, beta=10):
          return (1/(1 + np.exp(-beta * x)))
      GLVQ 將該樣本映射到所有原型向量上,并計算每個映射結(jié)果與該輸入樣本的距離。然后GLVQ 將輸入樣本 x 分類為距離最近的原型向量所代表的類別。
      圖片
       # define delta_w_plus
       def change_in_w_plus(self, input_data, prototypes, lr, classifier,
                            w_plus, w_plus_index, d_plus, d_minus):
       
           sai = (2) * (d_minus / (np.square(d_plus + d_minus))) * \
              (self.sigmoid(classifier)) * (1 - self.sigmoid(classifier))
       
           expand_dimension = np.expand_dims(sai, axis=1)
           change_w_plus = expand_dimension * (input_data - w_plus) * lr
       
           # index of w_plus
           unique_w_plus_index = np.unique(w_plus_index)
           unique_w_plus_index = np.expand_dims(unique_w_plus_index, axis=1)
       
           add_row_change_in_w = np.column_stack((w_plus_index, change_w_plus))
           check = np.equal(add_row_change_in_w[:, 0], unique_w_plus_index)
           check = np.expand_dims(check, axis=2)
           check = np.where(check, change_w_plus, 0)
           sum_change_in_w_plus = np.sum(check, axis=1)
           return sum_change_in_w_plus, unique_w_plus_index
       
       # define delta_w_minus
       def change_in_w_minus(self, input_data, prototypes, lr, classifier,
                             w_minus, w_minus_index, d_plus, d_minus):
       
           sai = (2) * (d_plus / (np.square(d_plus + d_minus))) * \
              (self.sigmoid(classifier)) * (1 - self.sigmoid(classifier))
       
           expand_dimension = np.expand_dims(sai, axis=1)
           change_w_minus = (expand_dimension) * (input_data - w_minus) * lr
       
           # index of w_minus
           unique_w_minus_index = np.unique(w_minus_index)
           unique_w_minus_index = np.expand_dims(unique_w_minus_index, axis=1)
       
           add_row_change_in_w = np.column_stack((w_minus_index, change_w_minus))
           check = np.equal(add_row_change_in_w[:, 0], unique_w_minus_index)
           check = np.expand_dims(check, axis=2)
           check = np.where(check, change_w_minus, 0)
           sum_change_in_w_minus = np.sum(check, axis=1)
           return sum_change_in_w_minus,
      可以使用下面代碼繪制數(shù)據(jù):
       # plot data
       def plot(self, input_data, data_labels, prototypes, prototype_labels):
           plt.scatter(input_data[:, 0], input_data[:, 2], c=data_labels,
                       cmap='viridis')
           plt.scatter(prototypes[:, 0], prototypes[:, 2], c=prototype_labels,
                       s=60, marker='D', edgecolor='k')
      我們的訓練代碼如下:
       # fit function
       def fit(self, input_data, data_labels, learning_rate, epochs):
           normalized_data = self.normalization(input_data)
           prototype_l, prototypes = self.prt(normalized_data, data_labels,
                                              self.prototype_per_class)
           error = np.array([])
           plt.subplots(8, 8)
           for i in range(epochs):
               eu_dist = self.euclidean_dist(normalized_data, prototypes)
       
               d_plus, w_plus, w_plus_index = self.distance_plus(data_labels,
                                                                 prototype_l,
                                                                 prototypes,
                                                                 eu_dist)
       
               d_minus, w_minus, w_minus_index = self.distance_minus(data_labels,
                                                                     prototype_l,
                                                                     prototypes,
                                                                     eu_dist)
       
               classifier = self.classifier_function(d_plus, d_minus)
       
               sum_change_in_w_plus, unique_w_plus_index = self.change_in_w_plus(
                   normalized_data, prototypes, learning_rate, classifier,
                   w_plus, w_plus_index,  d_plus, d_minus)
               update_w_p = np.add(np.squeeze(
                   prototypes[unique_w_plus_index]), sum_change_in_w_plus)
               np.put_along_axis(prototypes, unique_w_plus_index,
                                 update_w_p, axis=0)
       
               sum_change_in_w_m, unique_w_minus_index = self.change_in_w_minus(
                   normalized_data, prototypes, learning_rate, classifier,
                   w_minus, w_minus_index, d_plus, d_minus)
               update_w_m = np.subtract(np.squeeze(
                   prototypes[unique_w_minus_index]), sum_change_in_w_m)
               np.put_along_axis(
                   prototypes, unique_w_minus_index, update_w_m, axis=0)
       
               err = np.sum(self.sigmoid(classifier), axis=0)
               change_in_error = 0
       
               if (i == 0):
                   change_in_error = 0
       
               else:
                   change_in_error = error[-1] - err
       
               error = np.append(error, err)
               print('Epoch : {}, Error : {} Error change : {}'.format(
                   i + 1, err, change_in_error))
       
               plt.subplot(1, 2, 1)
               self.plot(normalized_data, data_labels, prototypes, prototype_l)
               plt.subplot(1, 2, 2)
               plt.plot(np.arange(i + 1), error, marker='d')
               plt.pause(0.5)
           plt.show()
           accuracy = np.count_nonzero(d_plus < d_minus)
           acc = accuracy / len(d_plus) * 100
           print('accuracy = {}'.format(acc))
           self.update_prototypes = prototypes
           return self.update_prototypes
      GLVQ 的訓練過程是通過不斷更新原型向量來進行的,這個過程可以迭代多次,直到分類結(jié)果收斂或達到指定的迭代次數(shù)為止。同時,為了防止過擬合,可以引入正則化項對原型向量的更新進行限制。
      GLVQ 的數(shù)學解釋相對簡單,但需要注意的是,不同的距離度量方法、學習率調(diào)度方法和正則化項都會對算法的性能產(chǎn)生影響,需要根據(jù)具體問題進行選擇和調(diào)整。
      預測數(shù)據(jù):
       # data predict
       def predict(self, input_value):
           input_value = self.normalization(input_value)
           prototypes = self.update_prototypes
           eu_dist = self.euclidean_dist(input_value, prototypes)
           m_d = np.min(eu_dist, axis=1)
           expand_dims = np.expand_dims(m_d, axis=1)
           ylabel = np.where(np.equal(expand_dims, eu_dist),
                             self.prt_labels, np.inf)
           ylabel = np.min(ylabel, axis=1)
           print(ylabel)
           return ylabel
      需要注意的是,GLVQ  的分類結(jié)果不一定是唯一的,因為在一些情況下,輸入樣本可能與多個原型向量的距離相等。為了解決這個問題,可以引入一些規(guī)則來確定分類結(jié)果,例如優(yōu)先將輸入樣本分配給更接近的原型向量所代表的類別,或根據(jù)原型向量所代表的類別的先驗概率分布來確定分類結(jié)果。

      Pytorch實現(xiàn)

      上面我們介紹的是python的實現(xiàn),下面我們嘗試使用pytorch來實現(xiàn)這個過程(注意:這里是根據(jù)原理編寫,不保證100%正確,如果發(fā)現(xiàn)問題請留言指出)
      在 PyTorch 中實現(xiàn) GLVQ 的方法,主要分為以下幾步:
      1. 準備數(shù)據(jù):需要準備訓練集和測試集的數(shù)據(jù),并進行數(shù)據(jù)預處理,例如標準化、歸一化等操作,以便進行訓練和測試。
      2. 定義模型:需要定義 GLVQ 模型,包括原型向量、距離度量、更新規(guī)則等。在 PyTorch 中,可以通過自定義 nn.Module 類來實現(xiàn) GLVQ 模型,其中包括前向傳播和反向傳播的方法。
      3. 定義損失函數(shù):GLVQ 的損失函數(shù)通常采用類間距離最小化和類內(nèi)距離最大化的原則,可以通過自定義 nn.Module 類來實現(xiàn) GLVQ 的損失函數(shù),其中包括計算損失值和反向傳播的方法。
      4. 訓練模型:需要利用訓練集對 GLVQ 模型進行訓練,并在測試集上進行測試。在 PyTorch 中,可以使用標準的訓練和測試流程來訓練和測試 GLVQ 模型。
       import torch
       import torch.nn as nn
       
       class GLVQ(nn.Module):
           def __init__(self, num_prototypes, input_size, output_size):
               super(GLVQ, self).__init__()
               self.num_prototypes = num_prototypes
               self.input_size = input_size
               self.output_size = output_size
               self.prototypes = nn.Parameter(torch.randn(num_prototypes, input_size))
               self.output_layer = nn.Linear(num_prototypes, output_size)
       
           def forward(self, x):
               distances = torch.cdist(x, self.prototypes)
               activations = -distances.pow(2)
               outputs = self.output_layer(activations)
               return outputs
       
       class GLVQLoss(nn.Module):
           def __init__(self, prototype_labels, prototype_lambda):
               super(GLVQLoss, self).__init__()
               self.prototype_labels = prototype_labels
               self.prototype_lambda = prototype_lambda
       
           def forward(self, outputs, targets):
               distances = torch.cdist(outputs, self.prototype_labels)
               class_distances = torch.gather(distances, 1, targets.unsqueeze(1))
               other_distances = distances.clone()
               other_distances[torch.arange(outputs.size(0)), targets] = float('inf')
               other_class_distances, _ = other_distances.min(1)
               loss = torch.mean(class_distances - other_class_distances + self.prototype_lambda * distances.pow(2))
               return loss
       
       # Training
       model = GLVQ(num_prototypes=10, input_size=784, output_size=10)
       criterion = GLVQLoss(prototype_labels=torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), prototype_lambda=0.1)
       optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
       
       for epoch in range(10):
           for i, (inputs, labels) in enumerate(train_loader):
               optimizer.zero_grad()
               outputs = model(inputs.view(inputs.size(0), -1))
               loss = criterion(outputs, labels)
               loss.backward()
      上述代碼實現(xiàn)了一個 GLVQ 模型,其中包含了一個原型向量矩陣 W,每一行表示一個類別的原型向量。訓練過程中,輸入樣本 x  通過計算與每個類別的原型向量之間的距離來進行分類,并將其分配給與其距離最近的原型向量所代表的類別。然后,根據(jù)分類結(jié)果和樣本真實標簽之間的誤差來更新原型向量,使其向輸入樣本的方向移動。這樣,通過不斷更新原型向量,GLVQ 可以學習到特征空間中不同類別之間的邊界,并用于分類新的輸入樣本。
      主要說明下GLVQLoss :具體而言,假設(shè)輸入樣本 x 分配給類別 c_{min},則 GLVQ 損失可以表示為:
      圖片
      其中 W_{c_{min}}W_{c_{not min}} 分別表示輸入樣本 x  分配給的類別和未分配給的其他類別的原型向量,||\cdot||_2 表示歐幾里得范數(shù)。該損失表示了輸入樣本 x  與其正確類別原型向量之間的距離與其他類別原型向量之間距離之差,即正確類別的原型向量應(yīng)該更接近輸入樣本 x。GLVQLoss 是一個帶有動態(tài)原型向量矩陣的損失函數(shù),它可以根據(jù)輸入樣本和當前的原型向量矩陣來計算損失,并使用梯度下降算法來更新原型向量。

      總結(jié)

      綜上所述,廣義學習向量量化(GLVQ)是一種強大而靈活的基于原型的分類算法,可以處理非線性可分類。通過允許更靈活的決策邊界,GLVQ可以在許多分類任務(wù)上實現(xiàn)更高的精度。
      總的來說,GLVQ提供了一種獨特而強大的分類方法,其處理非線性可分離數(shù)據(jù)的能力使其成為可用的分類算法集的一個有價值的補充。

      圖片

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多