import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel("模擬數據.xlsx")
from sklearn.model_selection import train_test_split
# 分割數據集
X = df.drop(['OP'], axis = 1)
y = df['OP']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3,
stratify=df['OP']) #分離訓練集和測試
df.head()
先加載了一個多分類數據集,并將數據集拆分為特征變量和目標變量,接著使用 train_test_split 方法將數據集分為訓練集和測試集,確保模型能夠基于不同的數據進行訓練和測試,數據集的特征矩陣 X 包含所有用于分類的特征,而 y 是數據的分類標簽,為了保證類別分布一致,我們使用 stratify 參數保持數據集中的類別平衡,該數據集中的每一行代表某個中藥材在多個波長/頻率下的紅外光譜信息,第一列是對應的中藥類別標簽,后面的列是光譜強度值
from sklearn.svm import SVC
from hyperopt import fmin, tpe, hp
from sklearn.metrics import accuracy_score
from sklearn import svm
# 定義超參數空間
parameter_space_svc = {
'C': hp.loguniform('C', np.log(100), np.log(1000)),
'kernel': hp.choice('kernel', ['rbf', 'poly']), # 有時推薦只使用rbf核函數
'gamma': hp.loguniform('gamma', np.log(100), np.log(1000))
}
# 初始化計數器
count = 0
# 定義優化目標函數
def func(args):
global count
count += 1
print(f"\nIteration {count}: Hyperparameters - {args}")
# 創建SVM分類器,傳遞超參數
clf = svm.SVC(**args)
# 訓練模型
clf.fit(X_train, y_train)
# 預測測試集
prediction = clf.predict(X_test)
# 計算準確率
score = accuracy_score(y_test, prediction)
print(f'Test accuracy: {score}')
# 由于fmin函數默認是最小化目標函數,所以返回負準確率作為目標
return -score
# 使用TPE算法進行超參數優化,最大評估次數為100
best = fmin(func, parameter_space_svc, algo=tpe.suggest, max_evals=100)
# 將最佳的核函數類型從索引值轉換為相應的字符串
kernel_list = ['rbf', 'poly']
best['kernel'] = kernel_list[best['kernel']]
# 輸出最佳超參數
print('\nBest hyperparameters:', best)
SVM 模型有兩個關鍵的超參數,即 C 和 gamma,分別控制決策邊界的平滑度和核函數的復雜度,為了提高模型的準確率,需要對這些超參數進行優化,在本文中,通過 Hyperopt 庫實現基于貝葉斯優化的超參數搜索
貝葉斯優化的目標是在超參數空間內找到使模型性能最優的超參數組合,我們通過定義超參數搜索空間,并采用TPE算法進行搜索,定義的超參數空間如下:
接下來,定義優化目標函數,該函數首先根據給定的超參數訓練 SVM 模型,并在測試集上進行預測,然后,計算模型的準確率,作為目標函數的評估指標,由于貝葉斯優化中的 fmin 函數默認是最小化目標函數,因此返回負準確率作為優化目標,經過 100 次迭代尋找最佳的超參數組合
# 創建SVM分類器,并使用最佳超參數進行配置
clf = SVC(
C=best['C'], # 懲罰項參數
kernel=best['kernel'], # 核函數類型,這里選擇徑向基函數(RBF)
gamma=best['gamma'], # 核函數系數
decision_function_shape='ovr', # 多分類問題時使用"ovr"(一對多)策略
cache_size=5000 # 緩存大小,單位為MB
)
# 使用訓練數據進行模型訓練
clf.fit(X_train, y_train)
利用找到的最佳超參數,構建最終的 SVM 模型
分類報告
# 使用模型在測試集上進行預測
y_pred= clf.predict(X_test)
from sklearn.metrics import classification_report
# 輸出模型報告, 查看評價指標
print(classification_report(y_test, y_pred))
分類報告顯示了每個類別的精確率、召回率和F1值,這些指標可以幫助評估模型在不同類別上的表現
from sklearn.metrics import confusion_matrix
# 計算混淆矩陣
confusion_matrix = confusion_matrix(y_test, y_pred)
# 繪制混淆矩陣
fig, ax = plt.subplots(figsize=(10, 7),dpi=1200)
cax = ax.matshow(confusion_matrix, cmap='Blues')
fig.colorbar(cax)
# 設置英文標簽
ax.set_xlabel('Predicted')
ax.set_ylabel('Actual')
ax.set_xticks(np.arange(11))
ax.set_yticks(np.arange(11))
ax.set_xticklabels([f'Class {i}' for i in range(1, 12)])
ax.set_yticklabels([f'Class {i}' for i in range(1, 12)])
for (i, j), val in np.ndenumerate(confusion_matrix):
ax.text(j, i, f'{val}', ha='center', va='center', color='black')
plt.title('Confusion Matrix Heatmap')
plt.savefig('Confusion Matrix Heatmap.pdf', format='pdf', bbox_inches='tight')
plt.show()
為了更直觀地展示分類效果,最后繪制了混淆矩陣熱力圖,混淆矩陣展示了模型在各類別上的分類結果,包括正確分類的樣本數量和錯誤分類的數量
本文展示了如何使用貝葉斯優化對 SVM 模型進行超參數調優,并將其應用于多分類問題。相比于傳統的網格搜索和隨機搜索,貝葉斯優化能更高效地找到最優超參數,減少了計算資源的消耗。最終的實驗結果表明,通過優化后的 SVM 模型能夠在測試集上取得較高的分類準確率,并且分類效果在各類別上相對均衡。混淆矩陣和分類報告清晰展示了模型的性能,進一步驗證了優化后模型的有效性,貝葉斯優化為機器學習模型的調優提供了一種強有力的工具,尤其在大規模超參數搜索問題中,能夠大幅提升效率和模型表現