前篇:Python 項目里的數據清理工作(數據清洗步驟應用)
一,先接上文添加兩種數據填充的方法
1、線性回歸填充
def lr_train_fill(train_data,train_label):train_data_all = pd.concat([train_data, train_label], axis=1)train_data_all = train_data_all.reset_index(drop=True)train_data_X = train_data_all.drop('礦物類型', axis=1)null_num = train_data_X.isnull().sum() # 查看每個特中存在空數據的個數null_num_sorted = null_num.sort_values(ascending=True) # 將空數據的類別從小到大進行排序filling_feature = [] # 用來存儲需要傳入模型的特征名稱for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0: # 當前特征是否有空缺的內容。用來判斷是否開始訓練模型X = train_data_X[filling_feature].drop(i, axis=1) # 構建訓練集y = train_data_X[i] # 構建測試集row_numbers_mg_null = train_data_X[train_data_X[i].isnull()].index.tolist() # 獲取空數據對應行號X_train = X.drop(row_numbers_mg_null) # 非空的數據作為訓練數據集y_train = y.drop(row_numbers_mg_null) # 非空的標簽作為訓練標簽X_test = X.iloc[row_numbers_mg_null] # 空的數據作為測試數據集regr = LinearRegression() # 創建線性回歸模型regr.fit(X_train, y_train) # 訓練模型y_pred = regr.predict(X_test) # 使用模型進行預測train_data_X.loc[row_numbers_mg_null, i] = y_predprint('完成訓練數據集中的{}列數據的填充'.format(i))return train_data_X, train_data_all['礦物類型']def lr_test_fill(train_data,train_label, test_data,test_label):'''使用隨機森林算法對測試數據集中缺失的數據進行填充,主要是基于這樣一個思想:根據已經填充后的訓練數據集建立模型,來補充空缺的測試數據集。'''train_data_all = pd.concat([train_data,train_label], axis=1)train_data_all = train_data_all.reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1)test_data_all = test_data_all.reset_index(drop=True)train_data_X = train_data_all.drop('礦物類型', axis=1) #多余。test_data_X = test_data_all.drop('礦物類型', axis=1)null_num = test_data_X.isnull().sum()null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:y_train = train_data_X[i]X_test = test_data_X[filling_feature].drop(i, axis=1)row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist()X_train = train_data_X[filling_feature].drop(i, axis=1).drop(row_numbers_mg_null) # 非空的訓練數據集y_train = y_train.drop(row_numbers_mg_null) # 非空的訓練標簽X_test = X_test.iloc[row_numbers_mg_null] # 空的測試數據集regr = RandomForestRegressor() # 創建隨機森林回歸模型regr.fit(X_train, y_train) # 訓練模型y_pred = regr.predict(X_test) # 使用模型進行預測test_data_X.loc[row_numbers_mg_null, i] = y_pred # pandas.loc[3,4]print(f'完成測試數據集中的{i}列數據的填充')return train_data_X, train_data_all['礦物類型']
? ? '''使用線性回歸填充訓練數據集中的缺失值,主要是基于這樣一個思想:特征和目標變量之間存在一定的關系,因此可以利用這種關系對缺失的特征進行預測。
? ? 以下是使用線性填充缺失值的一般步驟:
? ? 1、首先,確定哪些特征包含缺失值。
? ? 2、對于包含缺失值的特征,將其作為目標變量,而其他特征(可以包括原始的目標變量)作為輸入特征。注意,如果多個特征都有缺失值,
? ? ? ?通常建議按照缺失值的數量從小到大進行處理。因為缺失值較少的特征對預測的要求較低,準確性可能更高。
? ? 3、在處理某個特征的缺失值時,將該特征中的已知值(即非缺失值)作為訓練集,而缺失值作為需要預測的目標。此時,其他特征的相應值作為輸入特征。
? ? 4、使用線性回歸模型進行訓練,并對缺失值進行預測。
? ? 5、將預測得到的值填充到原始數據中的相應位置。
? ? 6、重復上述步驟,直到處理完所有包含缺失值的特征。
? ? 需要注意的是,使用線性回歸填充缺失值時,可能會受到模型選擇和過擬合等因素的影響。因此,在實際應用中,建議對數據進行適當的預處理,
? ? 如特征選擇、異常值處理等,以提高填充的準確性和穩定性。同時,也可以使用交叉驗證等方法來評估填充的效果。
? ? '''
2、隨機森林填充
#-----------隨機森林算法實現訓練數據集、測試數據集的填充-----------
def rf_train_fill(train_data,train_label):train_data_all = pd.concat([train_data, train_label], axis=1)train_data_all = train_data_all.reset_index(drop=True)#data數據行號存在混亂(因隨機抽取70%的數train_data_X = train_data_all.drop('礦物類型', axis=1)null_num = train_data_X.isnull().sum() #查看每個種中存在空數據的個數null_num_sorted = null_num.sort_values(ascending=True)#將空數據的類別從小到大進行排序filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:X = train_data_X[filling_feature].drop(i, axis=1)y = train_data_X[i]row_numbers_mg_null = train_data_X[train_data_X[i].isnull()].index.tolist()# 獲取空數據對應行號 row_numX_train = X.drop(row_numbers_mg_null) # 非空的數據作為訓練數據集y_train = y.drop(row_numbers_mg_null) # 非空的標簽作為訓練標簽X_test = X.iloc[row_numbers_mg_null] # 空的數據作為測試數據集regr = RandomForestRegressor(n_estimators=100, random_state=42) # 創建隨機森林回歸模型regr.fit(X_train, y_train) # 訓練模型y_pred = regr.predict(X_test) # 使用模型進行預測 y_pred: [-0.02019263]train_data_X.loc[row_numbers_mg_null, i] = y_pred# loc和iloc的區別: iloc[行號,列號] loc[行名, 列名],例如iloprint('完成訓練數據集中的{}列數據的填充'.format(i))return train_data_X, train_data_all['礦物類型']def rf_test_fill(train_data,train_label, test_data,test_label):'''使用隨機森林算法對測試數據集中缺失的數據進行填充,主要是基于這樣一個思想:根據已經填充后的訓練數據集建立模型,來補充空缺的測試數據集。'''train_data_all = pd.concat([train_data,train_label], axis=1)train_data_all = train_data_all.reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1)test_data_all = test_data_all.reset_index(drop=True)train_data_X = train_data_all.drop('礦物類型', axis=1) #多余。test_data_X = test_data_all.drop('礦物類型', axis=1)null_num = test_data_X.isnull().sum()null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:y_train = train_data_X[i]X_test = test_data_X[filling_feature].drop(i, axis=1)row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist()X_train = train_data_X[filling_feature].drop(i, axis=1).drop(row_numbers_mg_null) # 非空的訓練數據集y_train = y_train.drop(row_numbers_mg_null) # 非空的訓練標簽X_test = X_test.iloc[row_numbers_mg_null] # 空的測試數據集regr = RandomForestRegressor(n_estimators=100, random_state=42)regr.fit(X_train, y_train) # 訓練模型y_pred = regr.predict(X_test) # 使用模型進行預測test_data_X.loc[row_numbers_mg_null, i] = y_pred # pandas.loc[3,4]print(f'完成測試數據集中的{i}列數據的填充')return train_data_X, train_data_all['礦物類型']
逐步填充策略:按照特征缺失值數量從少到多的順序依次填充,先用完整數據填充缺失少的特征,再用已填充的特征作為輸入去預測缺失多的特征,形成 "滾雪球" 式填充鏈條。
隨機森林回歸建模:對每個含缺失值的特征,將其作為目標變量,其他已填充特征作為輸入變量,構建隨機森林回歸模型,利用模型預測缺失值。
分階段填充邏輯:
- 先處理訓練集:用訓練集中的非缺失數據訓練模型,預測并填充同集中的缺失值
- 再處理測試集:基于已完整填充的訓練集構建模型,專門預測測試集中的缺失值
特征關聯利用:通過多特征協同建模,充分利用特征間的內在關聯性,相比簡單均值填充能更好地保留數據分布特征。
二、六種數據訓練方法
準備工作
import pandas as pd
from sklearn import metrics'''數據提取'''
train_data = pd.read_excel(r'./temp_data/2、測試數據集[平均值填充].xlsx')
# 訓練數據集的特征
train_data_x = train_data.iloc[:, 1:]
# 訓練數據集的測試標簽label
train_data_y = train_data.iloc[:, 0]
# 讀取測試數據集
test_data = pd.read_excel(r'./temp_data/2、訓練數據集[平均值填充].xlsx')
# 測試數據集的特征
test_data_x = test_data.iloc[:, 1:]
# 測試數據集的測試標簽label
test_data_y = test_data.iloc[:, 0]
# 用來保存在后面6種算法的結果。
result_data = {}
1、svm算法
在這里的訓練過程中,我們使用了網格搜索,和之前的交叉驗證相似,但是非常好
完整代碼段:
?
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV#網格搜索param_grid = {# 核函數類型,線性核、多項式核、RBF核、sigmoid核'kernel': ['linear', 'poly', 'rbf', 'sigmoid'],# 正則化參數,控制間隔大小,較小的值表示更強的正則化'C': [0.1, 1, 1.5, 2],# RBF、poly和sigmoid核的核系數'gamma': ['scale', 'auto', 0.001, 0.01, 0.1, 1],# 多項式核的階數(僅對poly有效)'degree': [2, 3, 4] # 多項式核的次數,通常3次以內效果較好
}svm = SVC()
# 創建GridSearchCV對象
grid_search = GridSearchCV(svm, param_grid, cv=5)
# 在訓練集上執行網格搜索
grid_search.fit(train_data_x, train_data_y)
# 輸出最佳參數
print("Best parameters set found on development set:")
print(grid_search.best_params_)# """建立最優模型"""
svm_result= {}#用來保存訓練之后的結果。
svm = SVC(C = 2, degree = 2,gamma = 1,kernel='rbf')
svm.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = svm.predict(train_data_x)
print('svm的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = svm.predict(test_data_x)
print('svm的test:\n',metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted,digits=6)
b = a.split()
svm_result['recall_0'] = float(b[6]) #添加類別為0的召回率
svm_result['recall_1'] = float(b[11]) #添加類別為1的召回率
svm_result['recall_2'] = float(b[16]) #添加類別為2的召回率
svm_result['recall_3'] = float(b[21]) #添加類別為3的召回率
svm_result['svm'] = float(b[25]) #添加accuracy的結果
介紹思路,詳細講解一下網格
這段代碼主要實現了使用支持向量機 (SVM) 進行分類任務,并通過網格搜索 (Grid Search) 尋找最優參數的過程。下面我將詳細講解其思路和網格搜索的原理。
整體思路
- 模型選擇:選擇支持向量機 (SVM) 作為分類模型,它在處理高維空間和小樣本數據集時表現優異
- 參數優化:通過網格搜索對 SVM 的關鍵參數進行組合測試,找到性能最佳的參數組合
- 模型訓練:使用最優參數構建 SVM 模型并在訓練集上進行訓練
- 模型評估:分別在訓練集和測試集上評估模型性能,記錄關鍵指標
網格搜索 (Grid Search) 詳解
網格搜索是一種暴力搜索方法,它會遍歷所有可能的參數組合,通過交叉驗證來評估每個組合的性能,最終選擇表現最好的參數組合。
在這段代碼中:
-
參數空間定義:
?param_grid = {'kernel': ['linear', 'poly', 'rbf', 'sigmoid'], # 核函數類型'C': [0.1, 1, 1.5, 2], # 正則化參數'gamma': ['scale', 'auto', 0.001, 0.01, 0.1, 1], # 核系數'degree': [2, 3, 4] # 多項式核的階數 }
這里定義了 4 個參數及其可能的取值,網格搜索會嘗試所有這些值的組合。
-
網格搜索的執行:
?grid_search = GridSearchCV(svm, param_grid, cv=5) grid_search.fit(train_data_x, train_data_y)
GridSearchCV
中的cv=5
表示使用 5 折交叉驗證- 交叉驗證的作用是將訓練集分成 5 份,輪流用其中 4 份訓練,1 份驗證,最后取平均性能
- 這種方式可以更穩健地評估模型性能,避免因數據劃分方式導致的評估偏差
-
參數組合數量:
這里總共有 4×4×6×3 = 288 種參數組合,網格搜索會對每種組合都進行訓練和評估 -
最佳參數獲取:
?print(grid_search.best_params_)
這行代碼會輸出表現最好的參數組合,例如代碼中后續使用的
C=2, degree=2, gamma=1, kernel='rbf'
為什么需要網格搜索
- SVM 對參數敏感:SVM 的性能很大程度上依賴于參數選擇
- 參數之間存在交互:不同參數的組合可能產生不同的效果,單獨調整一個參數難以找到最優解
- 自動化優化:省去了人工嘗試不同參數組合的繁瑣過程
- 提高模型性能:通過系統地搜索參數空間,往往能找到比經驗值更好的參數組合
后續步驟
找到最優參數后,代碼使用這些參數重新構建 SVM 模型,并分別在訓練集和測試集上進行預測和評估,最后將關鍵指標(各類別的召回率和整體準確率)保存到結果字典中,便于后續分析和比較。
這種參數優化方法雖然計算成本較高(需要訓練大量模型),但在數據集不是特別大的情況下,是提高模型性能的有效手段。
后面的代碼均使用網格搜索,思路完全相同,將這個代碼理解了后面就是修改參數的事了
2、邏輯回歸算法
因為邏輯回歸的參數之間會發生沖突,所以采用多字典的形式來訓練,網格搜索支持大量字典一起運行
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV#網格搜索param_grid = [# liblinear求解器的參數組合(支持l1和l2正則化,但不支持multinomial多類模式){'penalty': ['l1', 'l2'],'C': [0.001, 0.01, 0.1, 1, 10, 100],'solver': ['liblinear'],'max_iter': [100, 200, 500],},# saga求解器的參數組合(支持所有正則化類型){'penalty': ['l1', 'l2', 'elasticnet', 'none'],'C': [0.001, 0.01, 0.1, 1, 10, 100],'solver': ['saga'],'max_iter': [100, 200, 500],},# 其他求解器的參數組合(不支持l1和elasticnet正則化){'penalty': ['l2', 'none'],'C': [0.001, 0.01, 0.1, 1, 10, 100],'solver': ['newton-cg', 'lbfgs', 'sag'],'max_iter': [100, 200, 500],}
]# 多分類策略(注意:'none' 懲罰時不支持 'multinomial')
...
logreg = LogisticRegression()
# 創建GridSearchCV對象
grid_search = GridSearchCV(logreg, param_grid, cv=5)
# 在訓練集上執行網格搜索
grid_search.fit(train_data_x, train_data_y)
# 輸出最佳參數
print("Best parameters set found on development set:")
print(grid_search.best_params_)
####{'C': 0.001, 'max_iter': 100, 'penalty': 'l1', 'solver': 'liblinear'}# """建立最優模型"""
LR_result= {}#用來保存訓練之后的結果。
lr = LogisticRegression(C = 0.001, max_iter = 100,penalty='none',solver='newton-cg')
lr.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = lr.predict(train_data_x)
print('LR的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = lr.predict(test_data_x) #訓練數據集的預測結果 test_predicted: [2 0 1 0 0 0 0 1 0 1 2 0 0
print('LR的test:\n',metrics.classification_report(test_data_y, test_predicted)) #打印訓練數據集的測試結果
a = metrics.classification_report(test_data_y, test_predicted,digits=6)#digits表示保留有效位數 a:
b = a.split() # b: ['precision', 'recall', 'f1-score', 'support', '0', '0.960784', '0.835227', '0.893617',
LR_result['recall_0'] = float(b[6]) #添加類別為0的召回率
LR_result['recall_1'] = float(b[11]) #添加類別為1的召回率
LR_result['recall_2'] = float(b[16]) #添加類別為2的召回率
LR_result['recall_3'] = float(b[21]) #添加類別為3的召回率
LR_result['acc'] = float(b[25]) #添加accuracy的結果
3、隨機森林算法
RF算法實現代碼##############################'''
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV#網格搜索# param_grid = {
# # 決策樹的數量
# 'n_estimators': [50, 100, 200, 300],
# # 每棵樹的最大深度,控制過擬合
# 'max_depth': [None, 10, 20, 30, 40],
# # 分裂節點時需要考慮的最小樣本數
# 'min_samples_split': [2, 5, 10],
# # 葉節點所需的最小樣本數
# 'min_samples_leaf': [1, 2, 4],
# # 構建樹時考慮的最大特征數
# 'max_features': ['sqrt', 'log2', None],
# }
#
# rf = RandomForestClassifier()
# # 創建GridSearchCV對象
# grid_search = GridSearchCV(rf, param_grid, cv=5)
# # 在訓練集上執行網格搜索
# grid_search.fit(train_data_x, train_data_y)
# # 輸出最佳參數
# print("Best parameters set found on development set:")
# print(grid_search.best_params_)
# #{'max_depth': 10, 'max_features': None, 'min_samples_leaf': 1, 'min_samples_split': 5, 'n_estimators': 300}# # """建立最優模型"""
rf_result= {}#用來保存訓練之后的結果。
rf = RandomForestClassifier(max_features=None,max_depth=10,min_samples_leaf=1,min_samples_split=5,n_estimators=300)
rf.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = rf.predict(train_data_x)
print('RF的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = rf.predict(test_data_x)
print('RF的test:\n',metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted,digits=6)
b = a.split()
rf_result['recall_0'] = float(b[6]) #添加類別為0的召回率
rf_result['recall_1'] = float(b[11]) #添加類別為1的召回率
rf_result['recall_2'] = float(b[16]) #添加類別為2的召回率
rf_result['recall_3'] = float(b[21]) #添加類別為3的召回率
rf_result['rf'] = float(b[25]) #添加accuracy的結果
4、xgboost算法
import xgboost as xgb
from sklearn.model_selection import GridSearchCV#網格搜索# param_grid = {
# # 決策樹的數量
# 'n_estimators': [50, 100, 200, 300],
# # 每棵樹的最大深度,控制過擬合
# 'max_depth': [None, 10, 20, 30, 40],
# # 分裂節點時需要考慮的最小樣本數
# 'min_samples_split': [2, 5, 10],
# # 葉節點所需的最小樣本數
# 'min_samples_leaf': [1, 2, 4],
# }
#
# xgb = xgb.XGBClassifier()
# # 創建GridSearchCV對象
# grid_search = GridSearchCV(xgb, param_grid, cv=5)
# # 在訓練集上執行網格搜索
# grid_search.fit(train_data_x, train_data_y)
# # 輸出最佳參數
# print("Best parameters set found on development set:")
# print(grid_search.best_params_)
# {'max_depth': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 100}# # """建立最優模型"""
xgb_result= {}#用來保存訓練之后的結果。
xgb = xgb.XGBClassifier(max_depth=None,min_samples_leaf=1,min_samples_split=2,n_estimators=100)
xgb.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = xgb.predict(train_data_x)
print('xgboost的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = xgb.predict(test_data_x)
print('xgboost的test:\n',metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted,digits=6)
b = a.split()
xgb_result['recall_0'] = float(b[6]) #添加類別為0的召回率
xgb_result['recall_1'] = float(b[11]) #添加類別為1的召回率
xgb_result['recall_2'] = float(b[16]) #添加類別為2的召回率
xgb_result['recall_3'] = float(b[21]) #添加類別為3的召回率
xgb_result['xgb'] = float(b[25]) #添加accuracy的結果
5、adaboost算法
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import GridSearchCV#網格搜索# param_grid = {
# # 基礎估計器的數量(迭代次數)
# 'n_estimators': [50, 100, 200, 300],
# # 學習率,控制每個弱學習器的貢獻
# 'learning_rate': [0.01, 0.1, 0.5, 1.0],
# # 基礎分類器(默認是決策樹樁)
# 'base_estimator': [
# DecisionTreeClassifier(max_depth=1), # 決策樹樁(默認)
# DecisionTreeClassifier(max_depth=2), # 更深一點的決策樹
# DecisionTreeClassifier(max_depth=3) # 稍復雜的決策樹
# ]
# }
#
# ada = AdaBoostClassifier()
# # 創建GridSearchCV對象
# grid_search = GridSearchCV(ada, param_grid, cv=5)
# # 在訓練集上執行網格搜索
# grid_search.fit(train_data_x, train_data_y)
# # 輸出最佳參數
# print("Best parameters set found on development set:")
# print(grid_search.best_params_)
# ##{'base_estimator': DecisionTreeClassifier(max_depth=3), 'learning_rate': 0.01, 'n_estimators': 300}# # """建立最優模型"""
ada_result= {}#用來保存訓練之后的結果。
ada = AdaBoostClassifier(base_estimator=DecisionTreeClassifier(max_depth=3),learning_rate=0.01,n_estimators=300)
ada.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = ada.predict(train_data_x)
print('adaboost的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = ada.predict(test_data_x)
print('adaboost的test:\n',metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted,digits=6)
b = a.split()
ada_result['recall_0'] = float(b[6]) #添加類別為0的召回率
ada_result['recall_1'] = float(b[11]) #添加類別為1的召回率
ada_result['recall_2'] = float(b[16]) #添加類別為2的召回率
ada_result['recall_3'] = float(b[21]) #添加類別為3的召回率
ada_result['ada'] = float(b[25]) #添加accuracy的結果
6、高斯貝葉斯算法
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import GridSearchCV#網格搜索# param_grid = {
# # 用于數值穩定性的平滑參數,防止概率為0
# 'var_smoothing': [1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5]
# }
# gnb = GaussianNB()
# # 創建GridSearchCV對象
# grid_search = GridSearchCV(gnb, param_grid, cv=5)
# # 在訓練集上執行網格搜索
# grid_search.fit(train_data_x, train_data_y)
# # 輸出最佳參數
# print("Best parameters set found on development set:")
# print(grid_search.best_params_)
# #{'var_smoothing': 1e-10}# # """建立最優模型"""
gnb_result= {}#用來保存訓練之后的結果。
gnb = GaussianNB(var_smoothing=1e-10)
gnb.fit(train_data_x, train_data_y)'''測試結果【含訓練數據集的測試 + 測試數據集的測試】'''
train_predicted = gnb.predict(train_data_x)
print('GaussianNB的train:\n',metrics.classification_report(train_data_y, train_predicted))
test_predicted = gnb.predict(test_data_x)
print('GaussianNB的test:\n',metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted,digits=6)
b = a.split()
gnb_result['recall_0'] = float(b[6]) #添加類別為0的召回率
gnb_result['recall_1'] = float(b[11]) #添加類別為1的召回率
gnb_result['recall_2'] = float(b[16]) #添加類別為2的召回率
gnb_result['recall_3'] = float(b[21]) #添加類別為3的召回率
gnb_result['gnb'] = float(b[25]) #添加accuracy的結果
7、日式生成
import datetime
import os# 創建日志目錄(如果不存在)
log_dir = './model_logs'
if not os.path.exists(log_dir):os.makedirs(log_dir)# 生成帶時間戳的日志文件名
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
log_file = os.path.join(log_dir, f'model_results_{timestamp}.log')# 收集各算法的最佳參數(根據網格搜索結果手動填寫或從網格搜索對象獲取)
best_params = {'LogisticRegression': {'C': 0.001, 'max_iter': 100, 'penalty': 'l1', 'solver': 'liblinear'},'SVM': {'C': 2, 'degree': 2, 'gamma': 1, 'kernel': 'rbf'},'RandomForest': {'max_depth': 10, 'max_features': None, 'min_samples_leaf': 1,'min_samples_split': 5, 'n_estimators': 300},'XGBoost': {'max_depth': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 100},'AdaBoost': {'base_estimator': 'DecisionTreeClassifier(max_depth=3)', 'learning_rate': 0.01, 'n_estimators': 300},'GaussianNB': {'var_smoothing': 1e-10}
}# 收集各算法的評估結果
results = {'LogisticRegression': LR_result,'SVM': svm_result,'RandomForest': rf_result,'XGBoost': xgb_result,'AdaBoost': ada_result,'GaussianNB': gnb_result
}# 寫入日志文件
with open(log_file, 'w', encoding='utf-8') as f:f.write(f"模型訓練與評估日志 - {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")f.write("=" * 80 + "\n\n")for model_name in best_params.keys():f.write(f"【{model_name}】\n")f.write("最佳參數:\n")for param, value in best_params[model_name].items():f.write(f" {param}: {value}\n")f.write("評估結果:\n")result = results[model_name]for metric, value in result.items():f.write(f" {metric}: {value:.6f}\n")# 寫入詳細分類報告if model_name == 'LogisticRegression':test_predicted = lr.predict(test_data_x)elif model_name == 'SVM':test_predicted = svm.predict(test_data_x)elif model_name == 'RandomForest':test_predicted = rf.predict(test_data_x)elif model_name == 'XGBoost':test_predicted = xgb.predict(test_data_x)elif model_name == 'AdaBoost':test_predicted = ada.predict(test_data_x)else: # GaussianNBtest_predicted = gnb.predict(test_data_x)f.write("詳細分類報告:\n")f.write(metrics.classification_report(test_data_y, test_predicted, digits=6))f.write("\n" + "-" * 80 + "\n\n")print(f"日志已保存至:{log_file}")