在机器学习中,填充数据(即处理缺失值)后,选择合适的算法并优化模型以提高召回率是一个常见的任务。召回率是指模型正确识别的正例占所有实际正例的比例。
代码思路:
-
数据预处理:
- 导入填充后的数据
import pandas as pd import numpy as np train_data=pd.read_excel('训练数据集[随机森林填充].xlsx') test_data=pd.read_excel('测试数据集[随机森林填充].xlsx')
- 导入填充后的数据
-
特征与标签提取
- 从数据集中提取特征和标签。
train_data_x=train_data.drop('矿物类型',axis=1) train_data_y=train_data['矿物类型'] test_data_x=test_data.drop('矿物类型',axis=1) test_data_y=test_data['矿物类型'] #初始化存储所有算法的召回率字典 result_data={}
- 从数据集中提取特征和标签。
-
网格搜索(寻找最优参数可能时间花费较长)
-
用于超参数优化的方法,它系统地遍历多种超参数的组合,通过交叉验证来确定最佳的超参数设置。
-
步骤
-
定义参数网格:
- 确定需要优化的超参数及其可能的值。例如,学习率、正则化参数、树的深度等。
-
设置交叉验证:
- 选择交叉验证的折数(如5折或10折),这将影响模型评估的稳健性。
-
初始化模型:
- 选择一个基线模型,如逻辑回归、支持向量机、随机森林等。
-
配置网格搜索:
- 使用网格搜索算法,输入模型、参数网格和交叉验证设置。
-
训练和评估:
- 网格搜索算法将遍历所有参数组合,对每一组参数使用交叉验证来评估模型性能。
-
选择最佳参数:
- 根据交叉验证的结果,选择表现最好的参数组合。
-
最终模型训练:
- 使用最佳参数在完整的训练数据集上重新训练模型。
from sklearn.model_selection import GridSearchCV param_grid={ 'penalty':['l1','l2','elasticnet','none'], 'C':[0.001,0.01,0.1,1,10,100], 'solver':['newton_cg','lbfgs','linear','sag','sage'], 'max_iter':[100,200,500], 'multi_class':['auto','ovr','multionmial'] } from sklearn.linear_model import LogisticRegression lohreg=LogisticRegression() grid_search=GridSearchCV(lohreg,param_grid,cv=5) grid_search.fit(train_data_x,train_data_y) print('最佳参数') print(grid_search.best_params_)
- 使用最佳参数在完整的训练数据集上重新训练模型。
-
-
-
模型训练:
- 使用训练数据集来训练模型。
- 使用交叉验证来评估模型的稳定性和性能。
-
性能评估:
- 使用测试数据集来评估模型的性能。
- 重点观察召回率,但也要考虑精确度、F1分数等其他指标。
-
模型优化:
- 调整模型的超参数,如树的深度、学习率、正则化参数等。
- 使用网格搜索(Grid Search)或随机搜索(Random Search)来找到最优的超参数组合。
-
模型选择:
- 比较不同模型的性能,选择召回率最高的模型。
- 考虑模型的复杂度和训练时间,选择一个平衡性能和效率的模型。
-
选择算法:
-
线性回归
# 初始化逻辑回归模型 lr = LogisticRegression(C=10, max_iter=500, penalty='l2', solver='lbfgs') # 训练模型 lr.fit(train_data_x, train_data_y) # 预测训练集 train_pred = lr.predict(train_data_x) # 打印训练集的分类报告 print('LR的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = lr.predict(test_data_x) # 打印测试集的分类报告 print('LR的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 LR_result = {} # 提取召回率和准确率 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['accuracy'] = float(b[25]) # 添加准确率 # 将逻辑回归的结果添加到总体结果字典中 result_data = {'LR': LR_result} # 打印结束信息 print('LR结束')
-
支持向量机(SVM)
# 初始化SVM分类器 svm_model = svm.SVC( C=1, coef0=0.1, degree=4, gamma=1, kernel='poly', probability=True, random_state=100 ) # 训练模型 svm_model.fit(train_data_x, train_data_y) # 预测训练集 train_pred = svm_model.predict(train_data_x) # 打印训练集的分类报告 print('SVM的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = svm_model.predict(test_data_x) # 打印测试集的分类报告 print('SVM的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 svm_result = {} # 提取召回率和准确率 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['accuracy'] = float(b[25]) # 添加准确率 # 将SVM的结果添加到总体结果字典中 result_data = {'svm': svm_result} # 打印结束信息 print('SVM结束')
-
随机森林
# 初始化随机森林分类器 rf = RandomForestClassifier( bootstrap=False, max_depth=20, max_features='log2', min_samples_leaf=1, min_samples_split=2, n_estimators=50, random_state=487 ) # 训练模型 rf.fit(train_data_x, train_data_y) # 预测训练集 train_pred = rf.predict(train_data_x) # 打印训练集的分类报告 print('RF的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = rf.predict(test_data_x) # 打印测试集的分类报告 print('RF的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 rf_result = {} # 提取召回率和准确率 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['accuracy'] = float(b[25]) # 添加准确率 # 将随机森林的结果添加到总体结果字典中 result_data = {'rf': rf_result} # 打印结束信息 print('RF结束')
-
AdaBoost
# 初始化AdaBoost分类器 abc = AdaBoostClassifier( algorithm='SAMME.R', # 使用SAMME.R算法 base_estimator=DecisionTreeClassifier(max_depth=2), # 使用决策树作为基学习器 n_estimators=200, # 弱学习器的数量 learning_rate=1.0, # 学习率 random_state=0 # 随机数种子 ) # 训练模型 abc.fit(train_data_x, train_data_y) # 预测训练集 train_pred = abc.predict(train_data_x) # 打印训练集的分类报告 print('AdaBoost的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = abc.predict(test_data_x) # 打印测试集的分类报告 print('AdaBoost的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 abc_result = {} # 提取召回率和准确率 abc_result['recall_0'] = float(b[6]) # 添加类别为0的召回率 abc_result['recall_1'] = float(b[11]) # 添加类别为1的召回率 abc_result['recall_2'] = float(b[16]) # 添加类别为2的召回率 abc_result['recall_3'] = float(b[21]) # 添加类别为3的召回率 abc_result['accuracy'] = float(b[25]) # 添加准确率 # 将AdaBoost的结果添加到总体结果字典中 result_data = {'abc': abc_result} # 打印结束信息 print('AdaBoost结束')
-
XGBoost
# 初始化XGBoost分类器 xgb = xgbs.XGBClassifier( learning_rate=0.05, n_estimators=200, num_class=5, max_depth=7, min_child_weight=1, # 叶子节点中最小的样本权重 gamma=0, # 节点分裂所需的最小损失函数下降值 subsample=0.6, # 训练样本的子样本比例 colsample_bytree=0.8, # 每棵树随机采样的列数的占比 objective='multi:softmax', # 损失函数类型(对于多分类问题) seed=0 # 随机数种子 ) # 训练模型 xgb.fit(train_data_x, train_data_y) # 预测训练集 train_pred = xgb.predict(train_data_x) # 打印训练集的分类报告 print('XGB的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = xgb.predict(test_data_x) # 打印测试集的分类报告 print('XGB的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 xgb_result = {} # 提取召回率和准确率 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['recall_4'] = float(b[26]) # 添加类别为4的召回率 xgb_result['accuracy'] = float(b[31]) # 添加准确率 # 将XGBoost的结果添加到总体结果字典中 result_data = {'xgb': xgb_result} # 打印结束信息 print('XGB结束')
-
高斯朴素贝叶斯(GaussianNB)
# 初始化高斯朴素贝叶斯分类器 mb = GaussianNB() # 训练模型 mb.fit(train_data_x, train_data_y) # 预测训练集 train_pred = mb.predict(train_data_x) # 打印训练集的分类报告 print('MNB的train:\n', metrics.classification_report(train_data_y, train_pred)) # 预测测试集 test_pred = mb.predict(test_data_x) # 打印测试集的分类报告 print('MNB的test:\n', metrics.classification_report(test_data_y, test_pred)) # 获取分类报告的字符串表示,并分割成单独的部分 a = metrics.classification_report(test_data_y, test_pred, digits=6) b = a.split() # 初始化结果字典 mb_result = {} # 提取召回率和准确率 mb_result['recall_0'] = float(b[6]) # 添加类别为0的召回率 mb_result['recall_1'] = float(b[11]) # 添加类别为1的召回率 mb_result['recall_2'] = float(b[16]) # 添加类别为2的召回率 # 修正召回率的键名 'recall 3' 为 'recall_3' mb_result['recall_3'] = float(b[21]) # 添加类别为3的召回率 mb_result['accuracy'] = float(b[25]) # 添加准确率 # 将朴素贝叶斯的结果添加到总体结果字典中 result_data = {'mb': mb_result} # 打印结束信息 print('MNB结束')
-
代码结果
完整代码
import pandas as pd
import numpy as np
train_data=pd.read_excel('训练数据集[随机森林填充].xlsx')
train_data_x=train_data.drop('矿物类型',axis=1)
train_data_y=train_data['矿物类型']
test_data=pd.read_excel('测试数据集[随机森林填充].xlsx')
test_data_x=test_data.drop('矿物类型',axis=1)
test_data_y=test_data['矿物类型']
result_data={}
# from sklearn.model_selection import GridSearchCV
# param_grid={
# 'penalty':['l1','l2','elasticnet','none'],
# 'C':[0.001,0.01,0.1,1,10,100],
# 'solver':['newton_cg','lbfgs','linear','sag','sage'],
# 'max_iter':[100,200,500],
# 'multi_class':['auto','ovr','multionmial']
# }
from sklearn.linear_model import LogisticRegression
# lohreg=LogisticRegression()
# grid_search=GridSearchCV(lohreg,param_grid,cv=5)
# grid_search.fit(train_data_x,train_data_y)
# print('最佳参数')
# print(grid_search.best_params_)
LR_result={}
lr=LogisticRegression(C=10,max_iter=500,penalty='l2',solver='lbfgs')
lr.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=lr.predict(train_data_x)
print('LR的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=lr.predict(test_data_x)
print('LR的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,digits=6)
b=a.split()
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的结果
result_data['LR']= LR_result # result_data是总体的结果,
print('lr结束')
import xgboost as xgbs
xgb_result={}
xgb=xgbs.XGBClassifier(learning_rate=0.05,
n_estimators=200,
num_class = 5,
max_depth=7,
min_child_weight=1, # 叶子节点中最小的样本权重
qamma=0,#节点分裂所需的最小损失函数下降值
subsample=0.6,#训练样本的子样本比例
colsample_bytree=0.8,#每棵树随机采样的列数的占比
objective='multi:softmax',#损失函数类型(对于二分类问题)
seed=0 #随机数种子
)# 创建XGBoost分类器
xgb.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=xgb.predict(train_data_x)
print('xgb的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=xgb.predict(test_data_x)
print('xgb的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,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['acc']=float(b[25]) # 添加accuracy的结果
result_data['xgb']= xgb_result # result_data是总体的结果,
print('xgb结束')
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
abc_result={}
abc = AdaBoostClassifier(algorithm='SAMME.R', # 修正算法名称
base_estimator=DecisionTreeClassifier(max_depth=2), # 修正类名
n_estimators=200,
learning_rate=1.0, # 修正参数名称
random_state=0)
# abc=AdaBoostClassifier(algorithm='SAMME',base_estimator=DecisionTreeClassifier(max_depth=2),n_estimators=200,Learning_rate= 1.0,random_state=0)
abc.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=abc.predict(train_data_x)
print('abc的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=abc.predict(test_data_x)
print('abc的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,digits=6)
b=a.split()
abc_result['recall_0']= float(b[6]) # 添加类别为0的召回导
abc_result['recall_1']= float(b[11]) # 添加类别为1的召回字
abc_result['recall_2']= float(b[16]) # 并添加美别为2的台回率
abc_result['recall 3']= float(b[21]) # 添加类别为3的召回率
abc_result['acc']=float(b[25]) # 添加accuracy的结果
result_data['abc']= abc_result # result_data是总体的结果,
print('AdaBoost结束')
from sklearn import svm
svm_result={}
svm=svm.SVC(C=1, coef0=0.1, degree= 4, gamma= 1, kernel='poly', probability=True, random_state=100)#
svm.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=svm.predict(train_data_x)
print('svm的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=svm.predict(test_data_x)
print('svm的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,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['acc']=float(b[25]) # 添加accuracy的结果
result_data['svm']= svm_result # result_data是总体的结果,
print('svm结束')
from sklearn.ensemble import RandomForestClassifier
rf_result={}
rf=RandomForestClassifier(bootstrap= False,max_depth=20,max_features='log2',min_samples_leaf= 1,min_samples_split= 2,n_estimators=50,random_state=487)
rf.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=rf.predict(train_data_x)
print('rf的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=rf.predict(test_data_x)
print('rf的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,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['acc']=float(b[25]) # 添加accuracy的结果
result_data['rf']= rf_result # result_data是总体的结果,
print('rf结束')
from sklearn.naive_bayes import GaussianNB
mb_result={}
mb=GaussianNB()
mb.fit(train_data_x,train_data_y)
from sklearn import metrics
train_pred=mb.predict(train_data_x)
print('mb的train:\n',metrics.classification_report(train_data_y,train_pred))
test_pred=mb.predict(test_data_x)
print('mb的test:\n',metrics.classification_report(test_data_y,test_pred))
a=metrics.classification_report(test_data_y,test_pred,digits=6)
b=a.split()
mb_result['recall_0']= float(b[6]) # 添加类别为0的召回导
mb_result['recall_1']= float(b[11]) # 添加类别为1的召回字
mb_result['recall_2']= float(b[16]) # 并添加美别为2的台回率
mb_result['recall 3']= float(b[21]) # 添加类别为3的召回率
mb_result['acc']=float(b[25]) # 添加accuracy的结果
result_data['mb']= mb_result # result_data是总体的结果,
print('mb结束')
import json
result={}
with open('随机森林填充.json','w') as f1:
json.dump(result_data,f1,ensure_ascii=False)