機器學習----04

樸素貝葉斯分類

分類報告

sklearn.metrics提供了分類報告相關API, 不僅可以得到混淆矩陣, 還可以得到交叉驗證的查準率, 召回率, f1得分的結果. 這樣可以方便的分析出那些樣本是異常樣本.

import sklearn.metrics as sm
# 獲取分類報告
cr = sm.classification_report(實際輸出, 預測輸出)
print(cr)

決策樹分類

決策樹分類模型會找到與樣本特徵匹配的葉子節點, 然後以投票的方式進行分類.

案例: 基於決策樹分類算法, 訓練模型, 預測小汽車(car.txt)等級. 需要注意的是每一個特徵都需要使用標籤編碼做預處理.

import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

for row in range(len(data)):
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        train_x.append(encoder.fit_transform(data[row]))
    else:
        train_y = encoder.fit_transform(data[row])
    encoders.append(encoder)

train_x = np.array(train_x).T
# 基於隨機森林分類器完成模型訓練
model = se.RandomForestClassifier(max_depth=6, n_estimators=200, random_state=7)
print(ms.cross_val_score(model, train_x, train_y, cv=4, scoring='f1_weighted').mean())
model.fit(train_x, train_y)
# 造一些測試數據, 進行測試
data = [
    ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
    ['high', 'high', '4', '4', 'med', 'med', 'acc'],
    ['low', 'low', '2', '4', 'small', 'high', 'good'],
    ['low', 'med', '3', '4', 'med', 'high', 'vgood'],
]

# 對測試數據進行相同的標籤編碼操作, 纔可以使用訓練好的模型
data = np.array(data).T
test_x, test_y = [], []
for row in range(len(data)):
    encoder = encoders[row]
    if row < len(data) - 1:
        test_x.append(encoder.transform(data[row]))
    else:
        test_y = encoder.transform(data[row])

test_x = np.array(test_x).T

pred_test_y = model.predict(test_x)
e = encoders[-1]
print(e.inverse_transform(test_y))
print(e.inverse_transform(pred_test_y))

驗證曲線

驗證曲線: 模型性能 = f(超參數)
驗證曲線是超參數優選的一種解決方案, 通過驗證曲線相關API, 可以得到相同模型在不同超參數下的模型性能得分, 從而得知最優超參數.

import sklearn.model_selection as ms
train_scores, test_scores = ms.validation_curve(
    model,  # 初始模型
    輸入集, 輸出集,
    'n_estimators', # 超參數名
    np.array([50, 60, 80, 100]), # 超參數取值列表
    cv=5, # 摺疊�樹
)

train scores的結構

超參數 CV1 CV2 CV3 CV4
50 0.973 0.894 0.944 0.924
100 0.914 0.924 0.934 0.954

test_scores的結構與上述結構一致.

案例: 小汽車案例中使用驗證曲線選擇超參數.

import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms
import matplotlib.pyplot as mp

# data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')
#
# data = data.T
# encoders = []
# train_x, train_y = [], []
#
# for row in range(len(data)):
#     encoder = sp.LabelEncoder()
#     if row < len(data) - 1:
#         train_x.append(encoder.fit_transform(data[row]))
#     else:
#         train_y = encoder.fit_transform(data[row])
#     encoders.append(encoder)
#
# train_x = np.array(train_x).T
# # 基於隨機森林分類器完成模型訓練
# model = se.RandomForestClassifier(max_depth=6, random_state=7)
#
# # 獲取關於n_estimators的驗證曲線
# n_estimators = np.arange(50, 550, 50)
# train_scores, test_scores = ms.validation_curve(
#     model, train_x, train_y,
#     'n_estimators', n_estimators, cv=5
# )
#
# train_means = train_scores.mean(axis=1)
# for p, s in zip(n_estimators, train_means):
#     print(p, '->', s)
#
# mp.figure('N_estimators', facecolor='lightgray')
# mp.title('N_estimators', fontsize=16)
# mp.xlabel('Estimators', fontsize=14)
# mp.ylabel('Scores', fontsize=14)
# mp.tick_params(labelsize=12)
# mp.grid(linestyle=":")
# mp.plot(n_estimators, train_means, c='dodgerblue', label='Valid Curve')
# mp.legend()
# mp.show()

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

for row in range(len(data)):
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        train_x.append(encoder.fit_transform(data[row]))
    else:
        train_y = encoder.fit_transform(data[row])
    encoders.append(encoder)

train_x = np.array(train_x).T
# 基於隨機森林分類器完成模型訓練
model = se.RandomForestClassifier(max_depth=8, n_estimators=200, random_state=7)

# 獲取關於n_estimators的驗證曲線
max_depths = np.arange(1, 11)
train_scores, test_scores = ms.validation_curve(
    model, train_x, train_y,
    'max_depth', max_depths, cv=5
)

train_means = train_scores.mean(axis=1)
for p, s in zip(max_depths, train_means):
    print(p, '->', s)

mp.figure('max_depths', facecolor='lightgray')
mp.title('max_depths', fontsize=16)
mp.xlabel('max_depth', fontsize=14)
mp.ylabel('Scores', fontsize=14)
mp.tick_params(labelsize=12)
mp.grid(linestyle=":")
mp.plot(max_depths, train_means, c='dodgerblue', label='Valid Curve')
mp.legend()
mp.show()

print(ms.cross_val_score(model, train_x, train_y, cv=4, scoring='f1_weighted').mean())
model.fit(train_x, train_y)
# 造一些測試數據, 進行測試
data = [
    ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
    ['high', 'high', '4', '4', 'med', 'med', 'acc'],
    ['low', 'low', '2', '4', 'small', 'high', 'good'],
    ['low', 'med', '3', '4', 'med', 'high', 'vgood'],
]

# 對測試數據進行相同的標籤編碼操作, 纔可以使用訓練好的模型
data = np.array(data).T
test_x, test_y = [], []
for row in range(len(data)):
    encoder = encoders[row]
    if row < len(data) - 1:
        test_x.append(encoder.transform(data[row]))
    else:
        test_y = encoder.transform(data[row])

test_x = np.array(test_x).T

pred_test_y = model.predict(test_x)
e = encoders[-1]
print(e.inverse_transform(test_y))
print(e.inverse_transform(pred_test_y))

學習曲線

學習曲線:模型性能 = f(訓練集大小)

學習曲線相關API:

import sklearn.model_selection as ms
# 獲取學習曲線
_, train_scores, test_scores = ms.learning_curve(
    model, # 初始模型
    輸入集, 輸出集,
    [0.9, 0.8, 0.7], # 訓練集大小
    cv=5 # 摺疊數
)

案例:

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

for row in range(len(data)):
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        train_x.append(encoder.fit_transform(data[row]))
    else:
        train_y = encoder.fit_transform(data[row])
    encoders.append(encoder)

train_x = np.array(train_x).T
# 基於隨機森林分類器完成模型訓練
model = se.RandomForestClassifier(max_depth=8, n_estimators=200, random_state=7)

# 使用學習曲線獲取最優訓練集大小
train_sizes = np.linspace(0.1, 1, 10)
_, train_scores, test_scores = ms.learning_curve(
    model, train_x, train_y,
    train_sizes=train_sizes,
    cv=5
)
train_means = train_scores.mean(axis=1)
for size, score in zip(train_sizes, train_means):
    print(size, '->', score)

mp.figure('Learning Curve')
mp.title('Learning Curve', fontsize=16)
mp.xlabel('Train Size', fontsize=12)
mp.ylabel('Curve Score', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(train_sizes, train_means, 'o-', c='dodgerblue', label='Curve')
mp.legend()
mp.show()

支持向量機(SVM)

核心理念: 尋求最優分類邊界
正確: 對大部分樣本可以正確的劃分類別.
泛化: 最大化支持向量間距.
公平: 類別與支持向量等距.
簡單: 線性, 直線, 平面做類別分割.
基於核函數的升維變換
基於難以分類的一些樣本, 執行基於核函數的升維變換. 增加新的特徵, 使得低維度空間的線性不可分問題, 變成高維度空間中的線性可分問題.
SVM提供的常用核函數

  1. 線性核函數 linear
  2. 多項式核函數 poly
  3. 徑向核函數 rbf
    線性核函數
    不通過核函數進行維度提升, 僅在原始維度空間中尋求線性分類便捷.
    基於線性核函數的SVM分類器:
import  sklearn.svm as svm
model = svm.SVC(kernel='linear')
model.fit(train_x, train_y)

案例: 使用線性核函數的SVM訓練multiple2.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

x, y = [], []
data = np.loadtxt('multiple2.txt', delimiter=',', 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)

# 基於線性核函數的支持向量機模型
model = svm.SVC(kernel='linear')
model.fit(train_x, train_y)

# 畫出分類邊界
n = 500
l, r = x[:, 0].min() - 1, x[:, 0].max() + 1
b, t = x[:, 1].min() - 1, x[:, 1].max() + 1
grid_x, grid_y = np.meshgrid(
    np.linspace(l, r, n),
    np.linspace(l, r, n)
)
samples = np.column_stack(
    (grid_x.ravel(), grid_y.ravel())
)
grid_z = model.predict(samples)
grid_z = grid_z.reshape(grid_x.shape)
# 使用模型預測測試集數據, 輸出分類報告
pred_test_y = model.predict(test_x)
cr = sm.classification_report(test_y, pred_test_y)
print(cr)

# 繪製分類邊界
mp.figure('SVM Linear Classfication', facecolor='lightgray')
mp.title('SVM Linear Classfication', fontsize=16)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=12)
mp.pcolormesh(grid_x, grid_y, grid_z, cmap='gray')
mp.scatter(train_x[:, 0], train_x[:, 1], c=train_y, cmap='brg', s=80)
mp.show()

多項式核函數
通過多項式函數增加原始樣本特徵的高次冪作爲新的特徵, 在新的思考維度中對樣本進行分類.

# 基於多項式核函數擴展新的特徵
model = svm.SVC(kernel='poly', degree=3)
model.fit(train_x, train_y)

徑向基核函數

通過高斯分佈函數增加原始樣本特徵的分佈概率

# 基於徑向基核函數擴展新的特徵
# C: 正則強度, 過擬合調大
# gamma: 正太分佈曲線的標準差
model = svm.SVC(kernel='rbf', C=600, gamma=0.01)
model.fit(train_x, train_y)

樣本類別均衡化

通過類別均衡化, 使所佔比例較小的樣本權重較高, 而所佔比例較大的樣本權重較低. 平均化不同類別樣本對分類模型的貢獻, 以提高模型精度.

# 添加class_weight = 'balanced' 實現樣本類別均衡化
model = svm.SVC(kernel='linear', class_weight='balanced')
model.fit(train_x, train_y)

案例: 基於線性核函數對imbalance.txt進行訓練

# 基於線性核函數的支持向量機模型
model = svm.SVC(kernel='rbf', C=1000,
                gamma=0.01,
                class_weight='balanced')
model.fit(train_x, train_y)

置信概率

根據樣本與分類邊界的距離遠近, 對其預測類別的可信程度進行量化, 離邊界越近的樣本, 置信概率越低, 反之, 離邊界越遠的樣本, 置信概率越高.

獲取每個樣本的置信概率API:

# 在獲取支持向量機模型時, 給出超參數 probability = True
# 獲取每個樣本的置信概率
置信概率矩陣 = model.predict_proba(test_x)
m = svm.SVC(kelnel='', C=1, gamma=0.01, probability=True)

置信概率矩陣格式:

- 類別1 類別2
樣本1 0.8 0.2
樣本2 0.6 0.4

案例: 修改徑向基核函數的SVM案例, 新增測試樣本, 輸出置信概率.

# 新增測試點 輸出置信概率, 繪製圖像
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)

mp.scatter(prob_x[:, 0], prob_x[:, 1], c=pred_prob_y, cmap='jet_r', s=80, marker='D')

# 爲每個點加上備註: 1類別概率, 2類別概率
for i in range(len(probs)):
    mp.annotate(
        '{}% {}%'.format(
            round(probs[i, 0]*100, 2),
            round(probs[i, 1]*100, 2),
        ),
        xy=(prob_x[i, 0], prob_x[i, 1]),
        xytext=(12, -12),
        textcoords='offset points',
        fontsize=9,
        bbox={
            'boxstyle': 'round, pad=0.6',
            'fc': 'orange',
            'alpha': 0.8
            }
    )

網格搜索

獲取一個最優超參數的方式可以繪製驗證曲線, 但是驗證曲線只能每次獲取一個最優超參數. 如果多個超參數有很多排列組合的話, 就可以使用網格搜索尋求最優超參數組合.

在網格搜索過程中, 針對每一個超參數組合, 實例化給定的模型, 做cv次交叉驗證, 將其中平均f1得分最高的超參數組合作爲最佳選擇, 實例化模型對象.(FlyAI)

網格搜索相關API:

import sklearn.model_selection as ms
# 返回的是已經使用了最優超參數組合的model對象
model = ms.GridSearchCV(
    model,              # 原始模型
    超參數組合列表,     # 使用列表的方式把所有組合列出
    cv=5                # 交叉驗證摺疊樹
)
# 獲取網格搜索過程中每個參數的組合
model.cv_results_['params']
# 獲取網格搜索中每個參數組合對應的平均測試分
model.cv_results_['mean_test_score']
# 獲取最好的參數
model.best_params_  # 最優參數
model.best_scores_  # 最優得分
model.best_estimator_   # 最優模型

案例: 修改置信概率案例, 基於網格搜索尋求最優超參數

# 基於徑向基核函數的支持向量機模型
model = svm.SVC()
# 整理超參數列表, 做網格搜索, 尋找最優
params = [
    {
    'kernel': ['linear'],
    'C': [1, 10, 100, 1000]
    },
    {
    'kernel': ['poly'],
    'C': [1],
    'degree': [2, 3]
    },
    {
    'kernel': ['rbf'],
    'C': [1, 10, 100, 1000],
    'gamma': [1, 0.1, 0.01, 0.001]
    }
]
model = ms.GridSearchCV(model, params, cv=5)
model.fit(train_x, train_y)
print(model.best_params_)
print(model.best_score_)
print(model.best_estimator_)

# 查看網格搜索過程的細節
for p, s in zip(
    model.cv_results_['params'],
    model.cv_results_['mean_test_score']
):
    print(p, '->', s)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章