<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 如何用Python從頭開始實現學習向量量化 > 原文: [https://machinelearningmastery.com/implement-learning-vector-quantization-scratch-python/](https://machinelearningmastery.com/implement-learning-vector-quantization-scratch-python/) [k-最近鄰居](http://machinelearningmastery.com/k-nearest-neighbors-for-machine-learning/)的限制是您必須保留一個大型訓練樣例數據庫才能進行預測。 [學習向量量化](http://machinelearningmastery.com/learning-vector-quantization-for-machine-learning/)算法通過學習最能代表訓練數據的更小的模式子集來解決這個問題。 在本教程中,您將了解如何使用Python從頭開始實現學習向量量化算法。 完成本教程后,您將了解: * 如何從訓練數據集中學習一組碼本向量。 * 如何使用學習的碼本向量進行預測。 * 如何將學習向量量化應用于實際預測建模問題。 讓我們開始吧。 * **2017年1月更新**:將cross_validation_split()中的fold_size計算更改為始終為整數。修復了Python 3的問題。 * **更新Aug / 2018** :經過測試和更新,可與Python 3.6配合使用。 ![How To Implement Learning Vector Quantization From Scratch With Python](img/9116ae5fdf9659e09d1603c386bd07bd.jpg) 如何用Python從頭開始實現學習向量量化 照片由 [Tony Faiola](https://www.flickr.com/photos/tonyfaiola/10303914233/) ,保留一些權利。 ## 描述 本節簡要介紹了學習向量量化算法和我們將在本教程中使用的電離層分類問題 ### 學習向量量化 學習向量量化(LVQ)算法很像k-Nearest Neighbors。 通過在模式庫中找到最佳匹配來進行預測。不同之處在于,模式庫是從訓練數據中學習的,而不是使用訓練模式本身。 模式庫稱為碼本向量,每個模式稱為碼本。將碼本向量初始化為來自訓練數據集的隨機選擇的值。然后,在許多時期,它們適于使用學習算法最佳地總結訓練數據。 學習算法一次顯示一個訓練記錄,在碼本向量中找到最佳匹配單元,如果它們具有相同的類,則將其移動到更接近訓練記錄,或者如果它們具有不同的類,則更遠離訓練記錄。 一旦準備好,碼本向量用于使用k-Nearest Neighbors算法進行預測,其中k = 1。 該算法是為分類預測建模問題而開發的,但可以適用于回歸問題。 ### 電離層數據集 電離層數據集根據雷達返回數據預測電離層的結構。 每個實例都描述了大氣層雷達回波的特性,任務是預測電離層中是否存在結構。 共有351個實例和34個數字輸入變量,每對雷達脈沖有17對2,通常具有0-1的相同比例。類值是一個字符串,其值為“g”表示良好返回,“b”表示不良返回。 使用零規則算法預測具有最多觀測值的類,可以實現64.286%的基線準確度。 您可以從 [UCI機器學習庫](https://archive.ics.uci.edu/ml/datasets/Ionosphere)了解更多信息并下載數據集。 下載數據集并將其放在當前工作目錄中,名稱為 **ionosphere.csv** 。 ## 教程 本教程分為4個部分: 1. 歐幾里德距離。 2. 最佳匹配單位。 3. 訓練碼本向量。 4. 電離層案例研究。 這些步驟將為實現LVQ算法并將其應用于您自己的預測建模問題奠定基礎。 ### 歐幾里德距離 需要的第一步是計算數據集中兩行之間的距離。 數據行主要由數字組成,計算兩行或數字向量之間的距離的簡單方法是繪制一條直線。這在2D或3D中是有意義的,并且可以很好地擴展到更高的尺寸。 我們可以使用歐幾里德距離測量來計算兩個向量之間的直線距離。它被計算為兩個向量之間的平方差之和的平方根。 ```py distance = sqrt( sum( (x1_i - x2_i)^2 ) ``` 其中 **x1** 是第一行數據, **x2** 是第二行數據, **i** 是特定列的索引,因為我們對所有列求和。 對于歐幾里德距離,值越小,兩個記錄就越相似。值為0表示兩個記錄之間沒有差異。 下面是一個名為 **euclidean_distance()**的函數,它在Python中實現了這一功能。 ```py # calculate the Euclidean distance between two vectors def euclidean_distance(row1, row2): distance = 0.0 for i in range(len(row1)-1): distance += (row1[i] - row2[i])**2 return sqrt(distance) ``` 您可以看到該函數假定每行中的最后一列是從距離計算中忽略的輸出值。 我們可以用一個小的人為分類數據集測試這個距離函數。當我們構造LVQ算法所需的元素時,我們將使用該數據集幾次。 ```py X1 X2 Y 2.7810836 2.550537003 0 1.465489372 2.362125076 0 3.396561688 4.400293529 0 1.38807019 1.850220317 0 3.06407232 3.005305973 0 7.627531214 2.759262235 1 5.332441248 2.088626775 1 6.922596716 1.77106367 1 8.675418651 -0.242068655 1 7.673756466 3.508563011 1 ``` 綜上所述,我們可以編寫一個小例子,通過打印第一行和所有其他行之間的距離來測試我們的距離函數。我們希望第一行和它自己之間的距離為0,這是一個值得注意的好事。 下面列出了完整的示例。 ```py from math import sqrt # calculate the Euclidean distance between two vectors def euclidean_distance(row1, row2): distance = 0.0 for i in range(len(row1)-1): distance += (row1[i] - row2[i])**2 return sqrt(distance) # Test distance function dataset = [[2.7810836,2.550537003,0], [1.465489372,2.362125076,0], [3.396561688,4.400293529,0], [1.38807019,1.850220317,0], [3.06407232,3.005305973,0], [7.627531214,2.759262235,1], [5.332441248,2.088626775,1], [6.922596716,1.77106367,1], [8.675418651,-0.242068655,1], [7.673756466,3.508563011,1]] row0 = dataset[0] for row in dataset: distance = euclidean_distance(row0, row) print(distance) ``` 運行此示例將打印數據集中第一行和每一行之間的距離,包括其自身。 ```py 0.0 1.32901739153 1.94946466557 1.55914393855 0.535628072194 4.85094018699 2.59283375995 4.21422704263 6.52240998823 4.98558538245 ``` 現在是時候使用距離計算來定位數據集中的最佳匹配單位。 ### 2.最佳匹配單位 最佳匹配單元或BMU是與新數據最相似的碼本向量。 要在數據集中找到BMU以獲取新的數據,我們必須首先計算每個碼本與新數據之間的距離。我們可以使用上面的距離函數來做到這一點。 計算距離后,我們必須按照與新數據的距離對所有碼本進行排序。然后我們可以返回第一個或最相似的碼本向量。 我們可以通過跟蹤數據集中每個記錄的距離作為元組來進行此操作,按距離(按降序排序)對元組列表進行排序,然后檢索BMU。 下面是一個名為 **get_best_matching_unit()**的函數,它實現了這個功能。 ```py # Locate the best matching unit def get_best_matching_unit(codebooks, test_row): distances = list() for codebook in codebooks: dist = euclidean_distance(codebook, test_row) distances.append((codebook, dist)) distances.sort(key=lambda tup: tup[1]) return distances[0][0] ``` 您可以看到上一步中開發的 **euclidean_distance()**函數用于計算每個碼本與新 **test_row** 之間的距離。 在使用自定義鍵的情況下對碼本和距離元組的列表進行排序,以確保在排序操作中使用元組中的第二項( **tup [1]** )。 最后,返回頂部或最相似的碼本向量作為BMU。 我們可以使用上一節中準備的小型人為數據集來測試此功能。 下面列出了完整的示例。 ```py from math import sqrt # calculate the Euclidean distance between two vectors def euclidean_distance(row1, row2): distance = 0.0 for i in range(len(row1)-1): distance += (row1[i] - row2[i])**2 return sqrt(distance) # Locate the best matching unit def get_best_matching_unit(codebooks, test_row): distances = list() for codebook in codebooks: dist = euclidean_distance(codebook, test_row) distances.append((codebook, dist)) distances.sort(key=lambda tup: tup[1]) return distances[0][0] # Test best matching unit function dataset = [[2.7810836,2.550537003,0], [1.465489372,2.362125076,0], [3.396561688,4.400293529,0], [1.38807019,1.850220317,0], [3.06407232,3.005305973,0], [7.627531214,2.759262235,1], [5.332441248,2.088626775,1], [6.922596716,1.77106367,1], [8.675418651,-0.242068655,1], [7.673756466,3.508563011,1]] test_row = dataset[0] bmu = get_best_matching_unit(dataset, test_row) print(bmu) ``` 運行此示例將數據集中的BMU打印到第一個記錄。正如預期的那樣,第一條記錄與自身最相似,位于列表的頂部。 ```py [2.7810836, 2.550537003, 0] ``` 使用一組碼本向量進行預測是一回事。 我們使用1最近鄰居算法。也就是說,對于我們希望進行預測的每個新模式,我們在集合中找到最相似的碼本向量并返回其關聯的類值。 現在我們知道如何從一組碼本向量中獲得最佳匹配單元,我們需要學習如何訓練它們。 ### 3.訓練碼本向量 訓練一組碼本向量的第一步是初始化該集合。 我們可以使用訓練數據集中隨機特征構建的模式對其進行初始化。 下面是一個名為 **random_codebook()**的函數,它實現了這個功能。從訓練數據中選擇隨機輸入和輸出特征。 ```py # Create a random codebook vector def random_codebook(train): n_records = len(train) n_features = len(train[0]) codebook = [train[randrange(n_records)][i] for i in range(n_features)] return codebook ``` 在將碼本向量初始化為隨機集之后,必須調整它們以最好地總結訓練數據。 這是迭代完成的。 1. **時期**:在頂層,對于固定數量的時期或訓練數據的曝光重復該過程。 2. **訓練數據集**:在一個時期內,每次使用一個訓練模式來更新該碼本向量集。 3. **模式特征**:對于給定的訓練模式,更新最佳匹配碼本向量的每個特征以使其移近或遠離。 為每個訓練模式找到最佳匹配單元,并且僅更新該最佳匹配單元。訓練模式和BMU之間的差異被計算為誤差。比較類值(假定為列表中的最后一個值)。如果它們匹配,則將錯誤添加到BMU以使其更接近訓練模式,否則,將其減去以將其推得更遠。 調整BMU的量由學習率控制。這是對所有BMU所做更改量的加權。例如,學習率為0.3意味著BMU僅移動了訓練模式和BMU之間的誤差或差異的30%。 此外,調整學習率以使其在第一時期具有最大效果并且隨著訓練繼續進行直到其在最后時期中具有最小效果的效果較小。這稱為線性衰減學習率計劃,也可用于人工神經網絡。 我們可以按時期總結學習率的衰減如下: ```py rate = learning_rate * (1.0 - (epoch/total_epochs)) ``` 我們可以通過假設學習率為0.3和10個時期來測試這個等式。每個時期的學習率如下: ```py Epoch Effective Learning Rate 0 0.3 1 0.27 2 0.24 3 0.21 4 0.18 5 0.15 6 0.12 7 0.09 8 0.06 9 0.03 ``` 我們可以把所有這些放在一起。下面是一個名為 **train_codebooks()**的函數,它實現了在給定訓練數據集的情況下訓練一組碼本向量的過程。 該函數對訓練數據集,創建和訓練的碼本向量的數量,初始學習率和訓練碼本向量的時期數量采用3個附加參數。 您還可以看到該函數記錄每個時期的總和平方誤差,并打印一條消息,顯示時期編號,有效學習率和總和平方誤差分數。在調試訓練函數或給定預測問題的特定配置時,這很有用。 您可以看到使用 **random_codebook()**初始化碼本向量和 **get_best_matching_unit()**函數來查找一個迭代內每個訓練模式的BMU。 ```py # Train a set of codebook vectors def train_codebooks(train, n_codebooks, lrate, epochs): codebooks = [random_codebook(train) for i in range(n_codebooks)] for epoch in range(epochs): rate = lrate * (1.0-(epoch/float(epochs))) sum_error = 0.0 for row in train: bmu = get_best_matching_unit(codebooks, row) for i in range(len(row)-1): error = row[i] - bmu[i] sum_error += error**2 if bmu[-1] == row[-1]: bmu[i] += rate * error else: bmu[i] -= rate * error print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, rate, sum_error)) return codebooks ``` 我們可以將它與上面的示例結合起來,為我們設計的數據集學習一組代碼簿向量。 以下是完整的示例。 ```py from math import sqrt from random import randrange from random import seed # calculate the Euclidean distance between two vectors def euclidean_distance(row1, row2): distance = 0.0 for i in range(len(row1)-1): distance += (row1[i] - row2[i])**2 return sqrt(distance) # Locate the best matching unit def get_best_matching_unit(codebooks, test_row): distances = list() for codebook in codebooks: dist = euclidean_distance(codebook, test_row) distances.append((codebook, dist)) distances.sort(key=lambda tup: tup[1]) return distances[0][0] # Create a random codebook vector def random_codebook(train): n_records = len(train) n_features = len(train[0]) codebook = [train[randrange(n_records)][i] for i in range(n_features)] return codebook # Train a set of codebook vectors def train_codebooks(train, n_codebooks, lrate, epochs): codebooks = [random_codebook(train) for i in range(n_codebooks)] for epoch in range(epochs): rate = lrate * (1.0-(epoch/float(epochs))) sum_error = 0.0 for row in train: bmu = get_best_matching_unit(codebooks, row) for i in range(len(row)-1): error = row[i] - bmu[i] sum_error += error**2 if bmu[-1] == row[-1]: bmu[i] += rate * error else: bmu[i] -= rate * error print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, rate, sum_error)) return codebooks # Test the training function seed(1) dataset = [[2.7810836,2.550537003,0], [1.465489372,2.362125076,0], [3.396561688,4.400293529,0], [1.38807019,1.850220317,0], [3.06407232,3.005305973,0], [7.627531214,2.759262235,1], [5.332441248,2.088626775,1], [6.922596716,1.77106367,1], [8.675418651,-0.242068655,1], [7.673756466,3.508563011,1]] learn_rate = 0.3 n_epochs = 10 n_codebooks = 2 codebooks = train_codebooks(dataset, n_codebooks, learn_rate, n_epochs) print('Codebooks: %s' % codebooks) ``` 運行該示例訓練一組2個碼本向量用于10個時期,初始學習率為0.3。每個時期打印細節,并顯示從訓練數據中學習的一組2??個碼本向量。 我們可以看到學習率的變化符合我們上面針對每個時期探討的期望。我們還可以看到,每個時期的總和平方誤差在訓練結束時繼續下降,并且可能有機會進一步調整示例以實現更少的錯誤。 ```py >epoch=0, lrate=0.300, error=43.270 >epoch=1, lrate=0.270, error=30.403 >epoch=2, lrate=0.240, error=27.146 >epoch=3, lrate=0.210, error=26.301 >epoch=4, lrate=0.180, error=25.537 >epoch=5, lrate=0.150, error=24.789 >epoch=6, lrate=0.120, error=24.058 >epoch=7, lrate=0.090, error=23.346 >epoch=8, lrate=0.060, error=22.654 >epoch=9, lrate=0.030, error=21.982 Codebooks: [[2.432316086217663, 2.839821664184211, 0], [7.319592257892681, 1.97013382654341, 1]] ``` 現在我們知道如何訓練一組碼本向量,讓我們看看如何在真實數據集上使用這個算法。 ### 4.電離層案例研究 在本節中,我們將學習向量量化算法應用于電離層數據集。 第一步是加載數據集并將加載的數據轉換為我們可以與歐氏距離計算一起使用的數字。為此我們將使用輔助函數 **load_csv()**來加載文件, **str_column_to_float()**將字符串數轉換為浮點數, **str_column_to_int()**轉換??為class列到整數值。 我們將使用5倍折疊交叉驗證來評估算法。這意味著每個折疊中將有351/5 = 70.2或僅超過70個記錄。我們將使用輔助函數 **evaluate_algorithm()**來評估具有交叉驗證的算法和 **accuracy_metric()**來計算預測的準確性。 The complete example is listed below. ```py # LVQ for the Ionosphere Dataset from random import seed from random import randrange from csv import reader from math import sqrt # Load a CSV file def load_csv(filename): dataset = list() with open(filename, 'r') as file: csv_reader = reader(file) for row in csv_reader: if not row: continue dataset.append(row) return dataset # Convert string column to float def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # Convert string column to integer def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset] unique = set(class_values) lookup = dict() for i, value in enumerate(unique): lookup[value] = i for row in dataset: row[column] = lookup[row[column]] return lookup # Split a dataset into k folds def cross_validation_split(dataset, n_folds): dataset_split = list() dataset_copy = list(dataset) fold_size = int(len(dataset) / n_folds) for i in range(n_folds): fold = list() while len(fold) < fold_size: index = randrange(len(dataset_copy)) fold.append(dataset_copy.pop(index)) dataset_split.append(fold) return dataset_split # Calculate accuracy percentage def accuracy_metric(actual, predicted): correct = 0 for i in range(len(actual)): if actual[i] == predicted[i]: correct += 1 return correct / float(len(actual)) * 100.0 # Evaluate an algorithm using a cross validation split def evaluate_algorithm(dataset, algorithm, n_folds, *args): folds = cross_validation_split(dataset, n_folds) scores = list() for fold in folds: train_set = list(folds) train_set.remove(fold) train_set = sum(train_set, []) test_set = list() for row in fold: row_copy = list(row) test_set.append(row_copy) row_copy[-1] = None predicted = algorithm(train_set, test_set, *args) actual = [row[-1] for row in fold] accuracy = accuracy_metric(actual, predicted) scores.append(accuracy) return scores # calculate the Euclidean distance between two vectors def euclidean_distance(row1, row2): distance = 0.0 for i in range(len(row1)-1): distance += (row1[i] - row2[i])**2 return sqrt(distance) # Locate the best matching unit def get_best_matching_unit(codebooks, test_row): distances = list() for codebook in codebooks: dist = euclidean_distance(codebook, test_row) distances.append((codebook, dist)) distances.sort(key=lambda tup: tup[1]) return distances[0][0] # Make a prediction with codebook vectors def predict(codebooks, test_row): bmu = get_best_matching_unit(codebooks, test_row) return bmu[-1] # Create a random codebook vector def random_codebook(train): n_records = len(train) n_features = len(train[0]) codebook = [train[randrange(n_records)][i] for i in range(n_features)] return codebook # Train a set of codebook vectors def train_codebooks(train, n_codebooks, lrate, epochs): codebooks = [random_codebook(train) for i in range(n_codebooks)] for epoch in range(epochs): rate = lrate * (1.0-(epoch/float(epochs))) for row in train: bmu = get_best_matching_unit(codebooks, row) for i in range(len(row)-1): error = row[i] - bmu[i] if bmu[-1] == row[-1]: bmu[i] += rate * error else: bmu[i] -= rate * error return codebooks # LVQ Algorithm def learning_vector_quantization(train, test, n_codebooks, lrate, epochs): codebooks = train_codebooks(train, n_codebooks, lrate, epochs) predictions = list() for row in test: output = predict(codebooks, row) predictions.append(output) return(predictions) # Test LVQ on Ionosphere dataset seed(1) # load and prepare data filename = 'ionosphere.csv' dataset = load_csv(filename) for i in range(len(dataset[0])-1): str_column_to_float(dataset, i) # convert class column to integers str_column_to_int(dataset, len(dataset[0])-1) # evaluate algorithm n_folds = 5 learn_rate = 0.3 n_epochs = 50 n_codebooks = 20 scores = evaluate_algorithm(dataset, learning_vector_quantization, n_folds, n_codebooks, learn_rate, n_epochs) print('Scores: %s' % scores) print('Mean Accuracy: %.3f%%' % (sum(scores)/float(len(scores)))) ``` 運行此示例將打印每個折疊的分類準確度以及所有折疊的平均分類精度。 我們可以看出,87.143%的準確率優于64.286%的基線。我們還可以看到,我們的20個碼本向量庫遠遠少于保存整個訓練數據集。 ```py Scores: [90.0, 88.57142857142857, 84.28571428571429, 87.14285714285714, 85.71428571428571] Mean Accuracy: 87.143% ``` ## 擴展 本節列出了您可能希望探索的教程的擴展。 * **調諧參數**。上述示例中的參數未進行調整,請嘗試使用不同的值來提高分類準確度。 * **不同的距離測量**。嘗試不同的距離測量,如曼哈頓距離和閔可夫斯基距離。 * **多次通過LVQ** 。可以通過多次訓練運行來更新碼本向量。通過大學習率的訓練進行實驗,接著是大量具有較小學習率的時期來微調碼本。 * **更新更多BMU** 。嘗試在訓練時選擇多個BMU,并將其從訓練數據中拉出。 * **更多問題**。將LVQ應用于UCI機器學習存儲庫中的更多分類問題。 **你有沒有探索過這些擴展?** 在下面的評論中分享您的經驗。 ## 評論 在本教程中,您了解了如何在Python中從頭開始實現學習向量量化算法。 具體來說,你學到了: * 如何計算模式之間的距離并找到最佳匹配單元。 * 如何訓練一組碼本向量以最好地總結訓練數據集。 * 如何將學習向量量化算法應用于實際預測建模問題。 **你有什么問題嗎?** 在下面的評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看