【数据+代码】网格搜索优化超参实现多分类

1、引言

本文涵盖主题:变量分析、数据分析、数据准备与特征工程、KNN-随机森林-SVM三种算法默认参数与网格搜索优化超参数6种方法进行对分类、总结六个部分。

本实验所使用数据包含影响预测的各种信息,如年龄、性别、血压、胆固醇水平、钠钾比和最后的药物类型。

本文主要结果汇总仪表板:

本期内容『数据+代码』已上传百度网盘。有需要的朋友可以关注公众号【小Z的科研日常】,后台回复关键词[多分类]获取。

2、变量分析

特征Age

对Age变量进行统计分析,观察Age变量在数据集中的最大最小值:

print("Max Age:", df.Age.max()) print("Min Age:", df.Age.min())

可观察到:

  • Max Age: 74

  • Min Age: 15

对年龄分布进行可视化:

# 设置绘图风格和颜色方案
sns.set_style('whitegrid')
colors = ['#FFB6C1', '#87CEFA', '#FFE4E1'] # 粉红色、天蓝色、粉色
sns.set_palette(colors)

# 创建画布并设置大小
fig, ax = plt.subplots(figsize=(8, 6))

# 绘制数据分布图,并设置透明度和线宽
sns.kdeplot(df['Age'], alpha=0.8, lw=3, shade=True, ax=ax)

# 配置坐标轴标签和标题,并设置字体大小和样式
ax.set_xlabel('Age', fontsize=20, fontweight='bold', color='k')
ax.set_ylabel('Density ', fontsize=20, fontweight='bold', color='k')
ax.set_title('Distribution of Age', fontsize=24, fontweight='bold', color='k')

# 调整刻度尺的字体大小和样式
for tick in ax.xaxis.get_major_ticks():
    tick.label.set_fontsize(16)
    tick.label.set_fontweight('bold')
    tick.label.set_color('k')
for tick in ax.yaxis.get_major_ticks():
    tick.label.set_fontsize(16)
    tick.label.set_fontweight('bold')
    tick.label.set_color('k')
# 显示图像
plt.show()

由上图可知,年龄分布主要集中在15-74之间。

特征Drug

Drug共由5个类别特征,对其进行分类统计,并进行可视化:

print(df.Drug.value_counts())
# 统计每个 Drug 类别出现的频率
counts = df['Drug'].value_counts()

# 选择颜色
custom_palette = sns.color_palette('pastel', n_colors=5)

# 设置调色板
sns.set_palette(custom_palette)

# 绘制条形图
plt.figure(figsize=(9,5))
sns.barplot(x=counts.index, y=counts.values)
plt.xlabel('Drug')
plt.ylabel('Count')
plt.title('Distribution of Drug in the Dataset')
plt.show()

药物是目标列,可以观察到该特征数据分布不均。为了获得可靠的模型训练结果,可使用K折交叉验证以使模型更可靠。

其余变量分析同理,本文不在赘述。

3、数据分析(部分展示)

由于篇幅原因,此章节只展示部分内容,若需完整资料可通过公众号获取。

Age----Drug

对不同年龄、Drug类型进行可视化分析:

plt.figure(figsize = (9,5))
sns.swarmplot(x = "Drug", y = "Age",data = df)
plt.legend(df.Drug.value_counts().index)
plt.title("Age -- Drug")

plt.show()

print("Minimum Age of DrugB",df.Age[df.Drug == "drugB"].min())

print("Maximum Age of DrugA",df.Age[df.Drug == "drugA"].max())

 

根据上图:药物B仅由51岁以上的人服用;药物A仅由50岁以下的人服用。

Sex----Drug

统计不同药物中,男性、女性的分布,并对其进行可视化观察:

df_Sex_Drug = df.groupby(["Drug","Sex"]).size().reset_index(name = "Count")
print(df_Sex_Drug)
plt.figure(figsize = (9,5))
sns.barplot(x = "Drug",y="Count", hue = "Sex",data = df_Sex_Drug)
plt.title("Sex -- Drug")
plt.show()

添加图片注释,不超过 140 字(可选)

上图可知:男性得到药物A、B和药物C的机会比女性多。女性得到的DrugY比男性多,药物X对男性和女性来说似乎是一样的。根据上述图表,性别特征不是一个重要的分类特征。

BP----Drug

与上述同理,先进行统计分析,其次进行可视化分析:

df_BP_Drug = df.groupby(["Drug","BP"]).size().reset_index(name = "Count")
plt.figure(figsize = (9,5))
sns.barplot(x = "Drug",y="Count", hue = "BP",data = df_BP_Drug)
plt.title("BP -- Drug")
plt.show()

 

 

上述分析表明,药物A和药物B只有高血压患者才能得到。血压低的人可以得到药物C。药物X是由高血压患者得到的。血压是分类的一个重要特征。

 

4、数据准备与特征工程

特征工程

经过上一章节的数据分析,如果Na_to_K数值大于15,则认定给予的药物是药物Y:

df['Na_to_K_Bigger_Than_15'] = [1 if i >=15.015 else 0 for i in df.Na_to_K]
df_NaK15 = df.groupby(["Drug","Na_to_K_Bigger_Than_15"]).size().reset_index(name = "Count")
plt.figure(figsize = (9,5))
sns.barplot(x = "Drug",y="Count", hue = "Na_to_K_Bigger_Than_15",data = df_NaK15)
plt.title("Na_to_K_Bigger_Than_15 -- Drug")
plt.show()

 

Na_to_K_Bigger_Than_15特征将是药物Y分类的重要特征。

标签编码

我们将非数值特征从对象转换为int64类型,以便后续进行模型训练:

from sklearn.preprocessing import LabelEncoder
def label_encoder(y):
    le = LabelEncoder()
    df[y] = le.fit_transform(df[y])

label_list = ["Sex","BP","Cholesterol","Na_to_K","Na_to_K_Bigger_Than_15","Drug"]
for l in label_list:
    label_encoder(l)

训练、测试集划分

from sklearn.model_selection import train_test_split
x = df.drop(["Drug"],axis=1)
y = df.Drug
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size = 0.2, random_state = 42, shuffle = True)
y_train = y_train.values.reshape(-1,1)
y_test = y_test.values.reshape(-1,1)
print("x_train shape:",x_train.shape)
print("x_test shape:",x_test.shape)
print("y_train shape:",y_train.shape)
print("y_test shape:",y_test.shape)

5、模型建立

实验将尝试三种模型并比较它们的结果。对于所有的模型,采用GridSearchCV方法来寻找最佳分数。此外,为了确保模型性能是随机的,使用5折交叉验证方法。

KNN默认参数

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier()
accuracies = cross_val_score(knn, x_train, y_train, cv=5)
knn.fit(x_train,y_train)
print("Train Score:",np.mean(accuracies))
print("Test Score:",knn.score(x_test,y_test))
  • Train Score: 0.59375

  • Test Score: 0.65

GridSearchCV优化KNN

为了找到KNN模型的最佳得分,将尝试不同的n_neighbors、p和weights参数值:

 

 

grid = {'n_neighbors':np.arange(1,120),
        'p':np.arange(1,3),
        'weights':['uniform','distance']
       }

knn = KNeighborsClassifier(algorithm = "auto")
knn_cv = GridSearchCV(knn,grid,cv=5)
knn_cv.fit(x_train,y_train)
print("Hyperparameters:",knn_cv.best_params_)
print("Train Score:",knn_cv.best_score_)
print("Test Score:",knn_cv.score(x_test,y_test))
  • Hyperparameters:{'n_neighbors':10, 'p': 1, 'weights': 'distance'}

  • Train Score: 0.75625

  • Test Score: 0.7

随机森林默认参数

from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(random_state = 42)
accuracies = cross_val_score(rfc, x_train, y_train, cv=5)
rfc.fit(x_train,y_train)

print("Train Score:",np.mean(accuracies))
print("Test Score:",rfc.score(x_test,y_test))
  • Train Score: 0.98125

  • Test Score: 0.975

GridSearchCV优化随机森林

为了找到随机森林模型的最佳得分,将尝试不同的n_estimators和标准参数的值。

grid = {'n_estimators':np.arange(100,1000,100),
        'criterion':['gini','entropy']
       }

rf = RandomForestClassifier(random_state = 42)
rf_cv = GridSearchCV(rf,grid,cv=5)
rf_cv.fit(x_train,y_train)

print("Hyperparameters:",rf_cv.best_params_)
print("Train Score:",rf_cv.best_score_)
print("Test Score:",rf_cv.score(x_test,y_test))

  • Hyperparameters:{'criterion':'entropy','n_estimators': 100}

  • Train Score: 0.9875

  • Test Score: 0.975

SVM默认参数

from sklearn.svm import SVC
svc = SVC(random_state = 42)
accuracies = cross_val_score(svc, x_train, y_train, cv=5)
svc.fit(x_train,y_train)

print("Train Score:",np.mean(accuracies))
print("Test Score:",svc.score(x_test,y_test))
  • Train Score: 0.7125

  • Test Score: 0.65

GridSearchCV优化SVM

grid = {
    'C':[0.01,0.1,1,10],
    'kernel' : ["linear","poly","rbf","sigmoid"],
    'degree' : [1,3,5,7],
    'gamma' : [0.01,1]
}

svm  = SVC ();
svm_cv = GridSearchCV(svm, grid, cv = 5)
svm_cv.fit(x_train,y_train)
print("Best Parameters:",svm_cv.best_params_)
print("Train Score:",svm_cv.best_score_)
print("Test Score:",svm_cv.score(x_test,y_test))
  • Best Parameters: {'C': 1, 'degree': 1, 'gamma': 0.01, 'kernel': 'linear'}

  • Train Score: 0.9875

  • Test Score: 0.975

6、总结

对上述六种方法得分进行总结与可视化:

经上述分析与图表观察,随机森林算法和SVM算法(经过超参数调整)分类效果最佳。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的网格搜索优化LSTM超参数的Python代码示例: ```python import numpy as np from keras.models import Sequential from keras.layers import Dense, LSTM from sklearn.model_selection import GridSearchCV from sklearn.metrics import mean_squared_error # 准备数据 X_train = np.random.rand(100, 10, 1) y_train = np.random.rand(100, 1) # 定义模型 def create_model(lstm_units=50, optimizer='adam'): model = Sequential() model.add(LSTM(lstm_units, input_shape=(10, 1))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer=optimizer) return model # 定义要搜索的参数 lstm_units = [50, 100, 150] optimizer = ['adam', 'rmsprop'] # 创建模型 model = KerasRegressor(build_fn=create_model, verbose=0) # 定义网格参数 param_grid = dict(lstm_units=lstm_units, optimizer=optimizer) # 进行网格搜索 grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1) grid_result = grid.fit(X_train, y_train) # 输出最好的结果 print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) # 输出所有结果 means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, std, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, std, param)) ``` 以上代码使用了Keras和Scikit-learn库进行超参优化,使用LSTM模型对一个随机生成的10维时间序列进行预测。在这个例子中,我们需要搜索2个超参数:LSTM单元数量和优化器类型。这个例子演示了如何使用网格搜索来找到最佳超参数组合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小Z的科研日常

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值