''' 支持向量機: 支持向量機原理: 分類原則:尋求最優分類邊界 1.正確:對大部分樣本可以正確地划分類別。 2.泛化:最大化支持向量間距。 3.公平:與支持向量等距。 4.簡單:線性,直線或平面,分割超平面。 基於核函數的升維變換:通過名為核函數的特征變換,增加新的特征,使得低維度空間中的線性不可分問題變為高維度空間中的線性可分問題。 1>線性核函數:linear,不通過核函數進行維度提升,僅在原始維度空間中尋求線性分類邊界。 2>多項式核函數:poly,通過多項式函數增加原始樣本特征的高次方冪 y = x_1+x_2 y = x_1^2 + 2x_1x_2 + x_2^2 y = x_1^3 + 3x_1^2x_2 + 3x_1x_2^2 + x_2^3 3>徑向基核函數:rbf,通過高斯分布函數增加原始樣本特征的分布概率 基於線性核函數的SVM分類相關API: model = svm.SVC(kernel='linear') model.fit(train_x, train_y) 案例,基於徑向基核函數訓練sample2.txt中的樣本數據。 步驟: 1.讀取文件,繪制樣本點的分布情況 2.拆分測試集合訓練集 3.基於svm訓練分類模型 4.輸出分類效果,繪制分類邊界 ''' import numpy as np import sklearn.model_selection as ms import sklearn.svm as svm import sklearn.metrics as sm import matplotlib.pyplot as mp data = np.loadtxt('./ml_data/multiple2.txt', delimiter=',', unpack=False, dtype='f8') x = data[:, :-1] y = data[:, -1] # 才分訓練集和測試集 train_x, test_x, train_y, test_y = ms.train_test_split(x, y, test_size=0.25, random_state=5) # 訓練svm模型---基於線性核函數 # model = svm.SVC(kernel='linear') # model.fit(train_x, train_y) # 訓練svm模型---基於多項式核函數 # model = svm.SVC(kernel='poly', degree=3) # model.fit(train_x, train_y) # 訓練svm模型---基於徑向基核函數 model = svm.SVC(kernel='rbf', C=600) model.fit(train_x, train_y) # 預測 pred_test_y = model.predict(test_x) # 計算模型精度 bg = sm.classification_report(test_y, pred_test_y) print('分類報告:', bg, sep='\n') # 繪制分類邊界線 l, r = x[:, 0].min() - 1, x[:, 0].max() + 1 b, t = x[:, 1].min() - 1, x[:, 1].max() + 1 n = 500 grid_x, grid_y = np.meshgrid(np.linspace(l, r, n), np.linspace(b, t, n)) bg_x = np.column_stack((grid_x.ravel(), grid_y.ravel())) bg_y = model.predict(bg_x) grid_z = bg_y.reshape(grid_x.shape) # 畫圖顯示樣本數據 mp.figure('SVM Classification', facecolor='lightgray') mp.title('SVM Classification', fontsize=16) mp.xlabel('X', fontsize=14) mp.ylabel('Y', fontsize=14) mp.tick_params(labelsize=10) mp.pcolormesh(grid_x, grid_y, grid_z, cmap='gray') mp.scatter(test_x[:, 0], test_x[:, 1], s=80, c=test_y, cmap='jet', label='Samples') mp.legend() mp.show() 輸出結果: 分類報告: precision recall f1-score support 0.0 0.91 0.87 0.89 45 1.0 0.81 0.87 0.84 30 accuracy 0.87 75 macro avg 0.86 0.87 0.86 75 weighted avg 0.87 0.87 0.87 75
''' 支持向量機分類之樣本類別均衡化:通過類別權重的均衡化,使所占比例較小的樣本權重較高,而所占比例較大的樣本權重較低, 以此平均化不同類別樣本對分類模型的貢獻,提高模型性能。 樣本類別均衡化相關API: model = svm.SVC(kernel='linear', class_weight='balanced') model.fit(train_x, train_y) 案例:修改線性核函數的支持向量機案例,基於樣本類別均衡化讀取imbalance.txt訓練模型。 ''' import numpy as np import sklearn.model_selection as ms import sklearn.svm as svm import sklearn.metrics as sm import matplotlib.pyplot as mp data = np.loadtxt('./ml_data/imbalance.txt', delimiter=',', unpack=False, dtype='f8') x = data[:, :-1] y = data[:, -1] # 才分訓練集和測試集 train_x, test_x, train_y, test_y = ms.train_test_split(x, y, test_size=0.25, random_state=5) # 訓練svm模型---基於線性核函數 model = svm.SVC(kernel='linear', class_weight='balanced') model.fit(train_x, train_y) # 預測 pred_test_y = model.predict(test_x) # 計算模型精度 bg = sm.classification_report(test_y, pred_test_y) print('分類報告:', bg, sep='\n') # 繪制分類邊界線 l, r = x[:, 0].min() - 1, x[:, 0].max() + 1 b, t = x[:, 1].min() - 1, x[:, 1].max() + 1 n = 500 grid_x, grid_y = np.meshgrid(np.linspace(l, r, n), np.linspace(b, t, n)) bg_x = np.column_stack((grid_x.ravel(), grid_y.ravel())) bg_y = model.predict(bg_x) grid_z = bg_y.reshape(grid_x.shape) # 畫圖顯示樣本數據 mp.figure('SVM Classification', facecolor='lightgray') mp.title('SVM Classification', fontsize=16) mp.xlabel('X', fontsize=14) mp.ylabel('Y', fontsize=14) mp.tick_params(labelsize=10) mp.pcolormesh(grid_x, grid_y, grid_z, cmap='gray') mp.scatter(test_x[:, 0], test_x[:, 1], s=80, c=test_y, cmap='jet', label='Samples') mp.legend() mp.show() 輸出結果: 分類報告: precision recall f1-score support 0.0 0.35 0.14 0.20 42 1.0 0.87 0.96 0.91 258 accuracy 0.84 300 macro avg 0.61 0.55 0.56 300 weighted avg 0.80 0.84 0.81 300
上圖可見,該樣本數據的樣本類別區分度不好,選區的特征無法區分類別,遇到這種情況,通常要考慮增加樣本特征,以提高類別區分度
''' 支持向量機之置信概率:根據樣本與分類邊界的距離遠近,對其預測類別的可信程度進行量化,離邊界越近的樣本,置信概率越低, 反之,離邊界越遠的樣本,置信概率高。 獲取每個樣本的置信概率相關API: # 在獲取模型時,給出超參數probability=True model = svm.SVC(kernel='rbf', C=600, gamma=0.01, probability=True) 預測結果 = model.predict(輸入樣本矩陣) # 調用model.predict_proba(樣本矩陣)可以獲取每個樣本的置信概率矩陣 置信概率矩陣 = model.predict_proba(輸入樣本矩陣) 置信概率矩陣格式如下: 類別1 類別2 樣本1 0.8 0.2 樣本2 0.9 0.1 樣本3 0.5 0.5 案例:修改基於徑向基核函數的SVM案例,新增測試樣本,輸出每個測試樣本的置信概率,並給出標注。 ''' import numpy as np import sklearn.model_selection as ms import sklearn.svm as svm import sklearn.metrics as sm import matplotlib.pyplot as mp data = np.loadtxt('./ml_data/multiple2.txt', delimiter=',', unpack=False, dtype='f8') x = data[:, :-1] y = data[:, -1] # 才分訓練集和測試集 train_x, test_x, train_y, test_y = ms.train_test_split(x, y, test_size=0.25, random_state=5) # 訓練svm模型---基於徑向基核函數 model = svm.SVC(kernel='rbf', C=600, gamma=0.01, probability=True) model.fit(train_x, train_y) # 自定義一組測試樣本,輸出樣本的置信概率 prob_x = np.array([ [2, 1.5], [8, 9], [4.8, 5.2], [4, 4], [2.5, 7], [7.6, 2], [5.4, 5.9]]) pred_prob_y = model.predict(prob_x) probs = model.predict_proba(prob_x) print('自信概率為:', probs, sep='\n') # 計算模型精度 # bg = sm.classification_report(test_y, pred_test_y) # print('分類報告:', bg, sep='\n') # 繪制分類邊界線 l, r = x[:, 0].min() - 1, x[:, 0].max() + 1 b, t = x[:, 1].min() - 1, x[:, 1].max() + 1 n = 500 grid_x, grid_y = np.meshgrid(np.linspace(l, r, n), np.linspace(b, t, n)) bg_x = np.column_stack((grid_x.ravel(), grid_y.ravel())) bg_y = model.predict(bg_x) grid_z = bg_y.reshape(grid_x.shape) # 畫圖顯示樣本數據 mp.figure('SVM Classification', facecolor='lightgray') mp.title('SVM Classification', fontsize=16) mp.xlabel('X', fontsize=14) mp.ylabel('Y', fontsize=14) mp.tick_params(labelsize=10) mp.pcolormesh(grid_x, grid_y, grid_z, cmap='gray') mp.scatter(test_x[:, 0], test_x[:, 1], s=80, c=test_y, cmap='jet', label='Samples') mp.scatter(prob_x[:, 0], prob_x[:, 1], c='orange', s=100, label='prob_samples') # 為每一個點添加備注,標注置信概率 for i in range(len(probs)): mp.annotate( '[{:.2f}%,{:.2f}%]'.format(probs[i][0]*100, probs[i][1]*100), xy=prob_x[i], xytext=(-10, 30), xycoords='data', textcoords='offset points', arrowprops=dict(arrowstyle='-|>', connectionstyle='angle3'), fontsize=10, color='red' ) mp.legend() mp.show() 輸出結果為: 自信概率為: [[3.00000090e-14 1.00000000e+00] [3.00000090e-14 1.00000000e+00] [9.76198900e-01 2.38011003e-02] [5.86133509e-01 4.13866491e-01] [2.80092352e-03 9.97199076e-01] [2.50983575e-11 1.00000000e+00] [9.49824497e-01 5.01755028e-02]]