2023年华为杯数学建模E题——代码复盘(第一问)

简介: 2023年华为杯数学建模E题——代码复盘(第一问)


写在最前面

超开心又有点遗憾

结果上来看 国二很可以了 顺便买个策略的教训

和数统专业队友——文月宝 配合相当默契 ~ 主要负责写代码,第一次建模比赛可以几乎不写论文,说一下思路就行,真的好爽啊;还能帮我把绘图优化,流程图也真的好好看

其他;

嘿嘿是每年一次的数模!每次都玩的好开心,这次也是!

每次数模建模有点像是一年一次的摸底考,通过实践感受自身的进步。

2023年,今年改代码时能捕捉到代码的内在逻辑,然后比较顺利的根据题目定制,改完之后几乎都能跑通,开心 ✿✿ヽ(°▽°)ノ✿

下面是这次的代码复盘,欢迎交流

整体框架:题目+问题1+a、b、c

题目+分解模块+思路+代码

目录

没错,这就是提交的论文目录。玩的很开心也很遗憾

问题1a

1、计算时间间隔

2、三阶样条插值。三种插值区间:不插值、(xmin,48)、(0,48)

3、绘图。为了求解方便,代码长度缩小方便修改,因此上述代码不包含绘图

计算时间间隔

思路说明

简单的数据处理

包含:读取数据,转化为日期时间对象,

一些小设计:

① 由于一共有13个时间间隔,能循环的就不枚举

通过enumerate+df[f"随访{i}时间点"]实现

for i, interval_name in enumerate(time_intervals, start=1):
    print(f"Index {i}: {interval_name}")
    df[interval_name] = (df[f"随访{i}时间点"] - df["入院首次检查时间点"]).dt.total_seconds() / 3600 + df1["发病到首次影像检查时间间隔"]

计算两个日期间的时间间隔,并间隔时间的单位,从s换算成h

df["入院首次检查时间点"]).dt.total_seconds() / 3600

② 字符串转换为日期时间对象

# 使用循环将"随访i时间点"列的数据从字符串转换为日期时间对象(一共12个)
# for i in range(1,12):
for i in range(1,8):
    df[f"随访{i}时间点"] = pd.to_datetime(df[f"随访{i}时间点"], format="%Y/%m/%d %H:%M:%S")

代码

import pandas as pd
# 读取Excel文件
file_path = "附表1-检索表格-流水号vs时间.xlsx"
df = pd.read_excel(file_path)
file_path1 = "表1-患者列表及临床信息.xlsx"
df1 = pd.read_excel(file_path1)
file_path2 = "表2-患者影像信息血肿及水肿的体积及位置.xlsx"
df2 = pd.read_excel(file_path2)
# 打印前几行数据
# print(df2.head())
column_list = df2.columns.tolist()
print(column_list)
# 将"入院首次检查时间点"列的数据从字符串转换为日期时间对象
df["入院首次检查时间点"] = pd.to_datetime(df["入院首次检查时间点"], format="%Y/%m/%d %H:%M:%S")
# 将"随访1时间点"列的数据从字符串转换为日期时间对象
# df["随访1时间点"] = pd.to_datetime(df["随访1时间点"], format="%Y/%m/%d %H:%M:%S")
# 使用循环将"随访i时间点"列的数据从字符串转换为日期时间对象(一共12个)
# for i in range(1,12):
for i in range(1,8):
    df[f"随访{i}时间点"] = pd.to_datetime(df[f"随访{i}时间点"], format="%Y/%m/%d %H:%M:%S")
# 创建一个列表来存储不同随访时间点的时间间隔列名
time_intervals = []
# 使用循环创建列名并添加到列表中
# for i in range(1, 13):  # 从1到12,包括1和12
for i in range(1, 9): 
    column_name = f"发病时间间隔{i}(h)"
    time_intervals.append(column_name)
# 打印时间间隔列名列表
print(time_intervals)
# 使用循环计算每个随访时间点与入院首次检查时间点之间的时间间隔
# 使用循环读取时间间隔字符串并计算时间间隔interval
df['发病时间间隔0(h)']= df1["发病到首次影像检查时间间隔"]
for i, interval_name in enumerate(time_intervals, start=1):
    print(f"Index {i}: {interval_name}")
    df[interval_name] = (df[f"随访{i}时间点"] - df["入院首次检查时间点"]).dt.total_seconds() / 3600 + df1["发病到首次影像检查时间间隔"]
# 绝对体积增加
deltaV0 = []
for i in range(1, 9): 
    column_name = f"绝对体积增加{i}"
    deltaV0.append(column_name)
print(deltaV0)
for i in range(1, 9):
    # print(f"绝对体积增加{i}")
    # 用sub()方法计算差值,只处理不是空值的行
    # df2[f"绝对体积增加{i}"] = df2[f'HM_volume.{i}'].sub(df2['HM_volume'], fill_value=0)
    df2[f"绝对体积增加{i}"] = df2[f'HM_volume.{i}'].sub(df2['HM_volume'])
# 相对体积增加
deltaV1 = []
for i in range(1, 9): 
    column_name = f"相对体积增加{i}"
    deltaV1.append(column_name)
print(deltaV1)
# 相对体积增加
for i in range(1, 9):
    df2[f"相对体积增加{i}"] = df2[f"绝对体积增加{i}"] / df2['HM_volume']
# 选择只包括"编号"和时间间隔列的子数据框
result_df0 = df[["编号"] + ['发病时间间隔0(h)'] +  time_intervals]
result_df1 = df2[["ID"] + deltaV0 + deltaV1]
# 表连接
merged_df = pd.merge(result_df0, result_df1, left_on="编号", right_on="ID")
# 保存结果到新的Excel文件
result_file_path = "1a血肿体积增加的时间间隔.xlsx"
merged_df.to_excel(result_file_path, index=False)

输出结果

插值求解

思路

1、绝对体积增加、相对面积增加

2、三阶样条插值,并绘图。三种插值区间:不插值、(xmin,48)、(0,48)

通过修改u = np.linspace(x.min(), 48, 1000)中的(x.min(), 48)更改区间

# 用三阶样条插值拟合曲线,指定边界条件
        f = spi.CubicSpline(x, y, bc_type='natural')
        u = np.linspace(x.min(), 48, 1000)  # 生成更多的数据点进行插值
        u1 = np.linspace(0, 48, 1000)  # 生成更多的数据点进行插值
        v = f(u)
        v1= f(u1)

3、合并绝对体积和相对体积的三种插值方式的时间最小值

for x, y in zip(first_increase_times00, first_increase_times10):
    if x is None and y is None:
        result0.append(None)
    elif x is None:
        result0.append(y)
    elif y is None:
        result0.append(x)
    else:
        result0.append(min(x, y))

4、通过发生时间,判断"是否发生血肿扩张"列中的相应行设置为1

# 使用条件语句将"是否发生血肿扩张"列中的相应行设置为1
df5.loc[df5["血肿扩张发生时间"].notna(), "是否发生血肿扩张"] = 1

5、求解个数

count_of_ones = (df5["是否发生血肿扩张"] == 1).sum()
print("不插值,前48h血肿扩张的个数:", count_of_ones)

代码

import pandas as pd
# 读取Excel文件
file_path3 = "1a血肿体积增加的时间间隔.xlsx"
df3 = pd.read_excel(file_path3)
# combined_range = list(range(0, 100))
# 创建两个范围对象
# df3 = df3.drop(range(100, 130))
range1 = range(0, 100)  # 从0到99
range2 = range(130, 160)  # 从129到159
# 合并两个范围
combined_range = list(range1) + list(range2)
print(combined_range)
df3 = df3.iloc[combined_range]
print(df3.shape)
print(list(df3["ID"]))
import matplotlib.pyplot as plt
import scipy.interpolate as spi
import numpy as np
time_intervals = ['发病时间间隔1(h)', '发病时间间隔2(h)', '发病时间间隔3(h)', '发病时间间隔4(h)', '发病时间间隔5(h)', '发病时间间隔6(h)', '发病时间间隔7(h)', '发病时间间隔8(h)']
deltaV0 = ['绝对体积增加1', '绝对体积增加2', '绝对体积增加3', '绝对体积增加4', '绝对体积增加5', '绝对体积增加6', '绝对体积增加7', '绝对体积增加8']
time0 = df3[time_intervals]
deltaV00 = df3[deltaV0]
# 不插值初始化一个列表来存储每个患者的第一次绝对体积增加至少6 mL的时间点
first_increase_times00 = []
# (xmin,48)初始化一个列表来存储每个患者的第一次绝对体积增加至少6 mL的时间点
first_increase_times01 = []
# (0,48)初始化一个列表来存储每个患者的第一次绝对体积增加至少6 mL的时间点
first_increase_times02 = []
flag00 = 0
flag01 = 0
flag02 = 0
# 循环绘制100条曲线
for i in combined_range:
    x0 = time0.loc[i]
    y0 = deltaV00.loc[i]
    # 删除包含NaN值的列,然后重新创建一个DataFrame
    x = x0.dropna().reset_index(drop=True)
    y = y0.dropna().reset_index(drop=True)
    # print(i,x.shape,y.shape)
    # 如果 x 只有一个元素,将 y 设置为恒等于 x
    if len(x) == 1:
        f = np.full_like(x, x[0])
        v = f
        v1 = f
    else:
        # 用三阶样条插值拟合曲线,指定边界条件
        f = spi.CubicSpline(x, y, bc_type='natural')
        u = np.linspace(x.min(), 48, 1000)  # 生成更多的数据点进行插值
        u1 = np.linspace(0, 48, 1000)  # 生成更多的数据点进行插值
        v = f(u)
        v1= f(u1)
    # 寻找插值前第一次绝对体积增加至少6 mL的时间点
    threshold = 6000
    for t, volume in zip(x, y):
        if volume >= threshold and 0 < t <= 48:
            first_increase_times00.append(t)
            flag00 = flag00 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times00.append(None)  # 如果未找到,添加 None
    # 寻找插值后第一次绝对体积增加至少6 mL的时间点
    for t, volume in zip(u, v):
        if volume >= threshold and t <= 48:
            first_increase_times01.append(t)
            flag01 = flag01 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times01.append(None)  # 如果未找到,添加 None
    # 寻找插值后第一次绝对体积增加至少6 mL的时间点
    for t, volume in zip(u1, v1):
        if volume >= threshold and t <= 48:
            first_increase_times02.append(t)
            flag01 = flag02 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times02.append(None)  # 如果未找到,添加 None
print("插值前,前48h绝对体积增加至少6mL的有",flag00,"个")
print(len(first_increase_times00))
print(first_increase_times00)
print("插值后,前48h绝对体积增加至少6mL的有",flag01,"个")
print(len(first_increase_times01))
print(first_increase_times01)
print("(0,48)插值后,前48h绝对体积增加至少6mL的有",flag02,"个")
print(len(first_increase_times02))
print(first_increase_times02)

相对体积

import matplotlib.pyplot as plt
import scipy.interpolate as spi
import numpy as np
deltaV1 = ['相对体积增加1', '相对体积增加2', '相对体积增加3', '相对体积增加4', '相对体积增加5', '相对体积增加6', '相对体积增加7', '相对体积增加8']
time0 = df3[time_intervals]
deltaV01 = df3[deltaV1]
flag10 = 0
flag11 = 0
flag12 = 0
# 初始化一个列表来存储每个患者的第一次相对体积增加至少0.33 mL的时间点
first_increase_times10 = []
first_increase_times11 = []
first_increase_times12 = []
# 循环绘制100条曲线
for i in combined_range:
    x0 = time0.loc[i]
    y0 = deltaV01.loc[i]
    # 删除包含NaN值的行,然后重新创建一个DataFrame
    x = x0.dropna().reset_index(drop=True)
    y = y0.dropna().reset_index(drop=True)
    # 如果 x 只有一个元素,将 y 设置为恒等于 x
    if len(x) == 1:
        f = np.full_like(x, x[0])
        v = f
        v1 = f
    else:
        # 用三阶样条插值拟合曲线,指定边界条件
        f = spi.CubicSpline(x, y, bc_type='natural')
        u = np.linspace(x.min(), 48, 1000)  # 生成更多的数据点进行插值
        u1 = np.linspace(0, 48, 1000)  # 生成更多的数据点进行插值
        v = f(u)
        v1 = f(u1)
    # 寻找插值前第一次相对体积增加至少33%的时间点
    threshold = 0.33
    for t, volume in zip(x,y):
        if volume >= threshold and t <= 48:
            first_increase_times10.append(t)
            flag10 = flag10 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times10.append(None)  # 如果未找到,添加 None
    # 寻找插值后第一次相对体积增加至少33%的时间点
    for t, volume in zip(u, v):
        if volume >= threshold and t <= 48:
            first_increase_times11.append(t)
            flag11 = flag11 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times11.append(None)  # 如果未找到,添加 None
    # 寻找(0,48)插值后第一次相对体积增加至少33%的时间点
    for t, volume in zip(u1, v1):
        if volume >= threshold and t <= 48:
            first_increase_times12.append(t)
            flag12 = flag12 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times12.append(None)  # 如果未找到,添加 None
print("插值前,前48h相对体积增加至少33%的有",flag10,"个")
print(len(first_increase_times10))
print(first_increase_times10)
print("插值后,前48h相对体积增加至少33%的有",flag11,"个")
print(len(first_increase_times11))
print(first_increase_times11)
print("(0,48)插值后,前48h相对体积增加至少33%的有",flag12,"个")
print(first_increase_times12)
print(len(first_increase_times12))
# 合并绝对体积和相对体积
import math
result0 = []
result1 = []
result2 = []
for x, y in zip(first_increase_times00, first_increase_times10):
    if x is None and y is None:
        result0.append(None)
    elif x is None:
        result0.append(y)
    elif y is None:
        result0.append(x)
    else:
        result0.append(min(x, y))
print(result0)
print(len(result0))
for x, y in zip(first_increase_times01, first_increase_times11):
    if x is None and y is None:
        result1.append(None)
    elif x is None:
        result1.append(y)
    elif y is None:
        result1.append(x)
    else:
        result1.append(min(x, y))
print(result1)
print(len(result1))
for x, y in zip(first_increase_times02, first_increase_times12):
    if x is None and y is None:
        result2.append(None)
    elif x is None:
        result2.append(y)
    elif y is None:
        result2.append(x)
    else:
        result2.append(min(x, y))
print(result2)
print(len(result2))

输出结果

绘图

为了求解方便,代码长度缩小方便修改,因此上述代码不包含绘图,下面是绘图示例:

import matplotlib.pyplot as plt
import scipy.interpolate as spi
import numpy as np
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
time_intervals = ['发病时间间隔1(h)', '发病时间间隔2(h)', '发病时间间隔3(h)', '发病时间间隔4(h)', '发病时间间隔5(h)', '发病时间间隔6(h)', '发病时间间隔7(h)', '发病时间间隔8(h)']
deltaV0 = ['绝对体积增加1', '绝对体积增加2', '绝对体积增加3', '绝对体积增加4', '绝对体积增加5', '绝对体积增加6', '绝对体积增加7', '绝对体积增加8']
time0 = df3[time_intervals]
deltaV00 = df3[deltaV0]
# 循环绘制100条曲线
for i in range(100):
    x0 = time0.loc[i]
    y0 = deltaV00.loc[i]
    # 删除包含NaN值的列,然后重新创建一个DataFrame
    x = x0.dropna().reset_index(drop=True)
    y = y0.dropna().reset_index(drop=True)
    # 用三阶样条插值拟合曲线,指定边界条件
    f = spi.CubicSpline(x, y, bc_type='natural')
    u = np.linspace(x.min(), x.max(), 1000)  # 生成更多的数据点进行插值
    v = f(u)
    plt.plot(u, v)
# 设置图表标题和轴标签
plt.title('前100个患者的水肿绝对体积随时间变化曲线')
plt.xlabel('时间间隔(h)')
plt.ylabel('绝对体积增加(10-3ml)')
# 显示图表
plt.show()
import matplotlib.pyplot as plt
import scipy.interpolate as spi
import numpy as np
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.figure(figsize=(5, 10))
flag10 = 0
flag11 = 0
time0 = df3[time_intervals]
deltaV01 = df3[deltaV1]
# 初始化一个列表来存储每个患者的第一次相对体积增加至少0.33 mL的时间点
first_increase_times1 = []
# 循环绘制100条曲线
for i in range(100):
    x0 = time0.loc[i]
    y0 = deltaV01.loc[i]
    # 删除包含NaN值的行,然后重新创建一个DataFrame
    x = x0.dropna().reset_index(drop=True)
    y = y0.dropna().reset_index(drop=True)
    # 绘制原始数据点的散点图
    plt.scatter(x, y, color='red', s=10)  # 设置散点颜色为红色,大小为10
    # 用三阶样条插值拟合曲线,指定边界条件
    f = spi.CubicSpline(x, y, bc_type='natural')
    # u = np.linspace(0,48, 1000)  # 生成更多的数据点进行插值
    # u = np.linspace(x.min(), x.max(), 1000)  # 生成更多的数据点进行插值
    u = np.linspace(x.min(), 48, 1000)  # 生成更多的数据点进行插值
    v = f(u)
    plt.plot(u, v)
    # 寻找插值前第一次相对体积增加至少33%的时间点
    threshold = 0.33
    for t, volume in zip(x,y):
        if volume >= threshold and t <= 48:
            flag10 = flag10 + 1
            break  # 找到后跳出循环
    # 寻找插值后第一次相对体积增加至少33%的时间点
    for t, volume in zip(u, v):
        if volume >= threshold and t <= 48:
            first_increase_times1.append(t)
            flag11 = flag11 + 1
            break  # 找到后跳出循环
    else:
        first_increase_times1.append(None)  # 如果未找到,添加 None
print("插值前,前48h相对体积增加至少33%的有",flag10,"个")
print("插值后,前48h相对体积增加至少33%的有",flag11,"个")
# 设置图表标题和轴标签
plt.title('前100个患者的水肿相对体积随时间变化曲线')
plt.xlabel('时间间隔(h)')
plt.ylabel('相对体积增加(%)')
# 设置 x 轴范围
plt.xlim(0, 48)
plt.ylim(-0.75, 1)
# 绘制虚线
a = np.linspace(0, 48, 1000)
plt.plot(a , np.full_like(a, 0.33), '--', label='y=6000')
# 显示图表
plt.show()
print(first_increase_times1)

绘制3D图(待修改)

问题1b

1、承接1a,分三个插值区域分别进行求解

数据预处理

思路

1、读取表格对应字段

2、对性别、血压进行处理

# 使用replace方法将'男'替换为1,'女'替换为0
final_merged_table['性别'] = final_merged_table['性别'].replace({'男': 1, '女': 0})
# 创建新的'血压高'和'血压低'列,根据'血压'列的值拆分
final_merged_table[['血压高', '血压低']] = final_merged_table['血压'].str.split('/', expand=True)

代码

import pandas as pd
# 读取Excel文件
file_path1 = "表1-患者列表及临床信息.xlsx"
df1 = pd.read_excel(file_path1)
file_path2 = "表2-患者影像信息血肿及水肿的体积及位置.xlsx"
df2 = pd.read_excel(file_path2)
file_path3 = "表3-血肿.xlsx"
df3 = pd.read_excel(file_path3)
file_path4 = "1a血肿扩张发生时间-不插值.xlsx"
df4 = pd.read_excel(file_path4)
file_path5 = "1a血肿扩张发生时间-区间插值.xlsx"
df5 = pd.read_excel(file_path5)
file_path6 = "1a血肿扩张发生时间-0h插值.xlsx"
df6 = pd.read_excel(file_path6)
subset_df1 = df1.iloc[:,[0] + list(range(3, 23))] # 入院首次影像检查流水号+字段E至W
subset_df2 = df2.iloc[:,[0] + list(range(2, 24))] # 字段C至X
subset_df3 = df3.iloc[:,list(range(1, 32))] # 流水号+字段C至AG
# 打印筛选后的数据框(DataFrame)以进行验证
# print(subset_df1)
merged_table0 = pd.merge(df6, subset_df1, on='ID', how='outer')
merged_table = pd.merge(merged_table0, subset_df2, on='ID', how='outer')
final_merged_table = pd.merge(merged_table, subset_df3, left_on='入院首次影像检查流水号',right_on='流水号', how='inner')
# 打印最终合并的表格以进行验证
# print(final_merged_table)
print(final_merged_table.shape)
import pandas as pd
# 使用replace方法将'男'替换为1,'女'替换为0
final_merged_table['性别'] = final_merged_table['性别'].replace({'男': 1, '女': 0})
# 创建新的'血压高'和'血压低'列,根据'血压'列的值拆分
final_merged_table[['血压高', '血压低']] = final_merged_table['血压'].str.split('/', expand=True)
# 使用 drop 方法删除名为"流水号"的列,axis=1 表示按列删除
final_merged_table = final_merged_table.drop(['入院首次影像检查流水号',"流水号","血肿扩张发生时间",'血压'], axis=1)
final_merged_table = final_merged_table.sort_values(by='ID', ascending=True)
# 打印更新后的DataFrame以进行验证
print(final_merged_table)
# 保存结果到新的Excel文件
result_file_path = "1b合并的表.xlsx"
final_merged_table.to_excel(result_file_path, index=False)

模型训练

思路

1、随机森林分类器,分层 K 折交叉验证评估模型性能

2、对比三种数据缩放技术,过采样前后,选择最优的模型

3、最优的技术组合下,随机森林、梯度提升树分类器、SVM三种方法进行网格调参

4、绘制ROC曲线、打印混淆矩阵

代码

from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
import numpy as np
from imblearn.over_sampling import SMOTE
file_path5 = "1b合并的表.xlsx"
df00 = pd.read_excel(file_path5)
df = df00[:100]
print(df.shape)
X = df.drop(["ID","是否发生血肿扩张"], axis=1)
y = df["是否发生血肿扩张"]
# 过采样:使用SMOTE进行过采样
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X, y)
# 标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_resampled)
# 初始化随机森林分类器
classifier = RandomForestClassifier(random_state=42)
# 创建分层 K 折交叉验证对象,确保每个折中的类别分布与整个数据集相似
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# 初始化评估指标的列表
accuracies = []
precisions = []
recalls = []
f1_scores = []
roc_aucs = []
# 使用交叉验证来评估模型性能
for train_idx, test_idx in cv.split(X_scaled, y_resampled):
    X_train, X_test = X_scaled[train_idx], X_scaled[test_idx]
    y_train, y_test = y_resampled[train_idx], y_resampled[test_idx]
    classifier.fit(X_train, y_train)
    y_pred = classifier.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred, zero_division=1)  # 设置zero_division参数
    recall = recall_score(y_test, y_pred, zero_division=1)  # 设置zero_division参数
    f1 = f1_score(y_test, y_pred, zero_division=1)  # 设置zero_division参数
    roc_auc = roc_auc_score(y_test, classifier.predict_proba(X_test)[:, 1])
    accuracies.append(accuracy)
    precisions.append(precision)
    recalls.append(recall)
    f1_scores.append(f1)
    roc_aucs.append(roc_auc)
# 计算平均值
avg_accuracy = np.mean(accuracies)
avg_precision = np.mean(precisions)
avg_recall = np.mean(recalls)
avg_f1 = np.mean(f1_scores)
avg_roc_auc = np.mean(roc_aucs)
# 打印结果
print(f'Accuracy: {avg_accuracy}')
print(f'Precision: {avg_precision}')
print(f'Recall: {avg_recall}')
print(f'F1-Score: {avg_f1}')
print(f'ROC-AUC: {avg_roc_auc}')
# 绘制ROC曲线
fpr, tpr, thresholds = roc_curve(y_test, classifier.predict_proba(X_test)[:, 1])
plt.figure()
plt.plot(fpr, tpr, label=f'ROC Curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC)')
plt.legend(loc='lower right')
plt.show()
# 绘制混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
print('Confusion Matrix:')
print(conf_matrix)

输出结果

(100, 74)

Accuracy: 0.7857142857142858

Precision: 0.7811951447245564

Recall: 0.8142857142857143

F1-Score: 0.7891089305577627

ROC-AUC: 0.835204081632653

Confusion Matrix:

[[10 4]

[ 3 11]]

网格调参代码

## 网格搜索调参
from sklearn.model_selection import GridSearchCV
# 初始化随机森林分类器
classifier = RandomForestClassifier(random_state=42)
# 网格搜索参数
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20, 30],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4]
}
# 创建网格搜索对象
# y_resampled = y_resampled[:100]
grid_search = GridSearchCV(classifier, param_grid, scoring='roc_auc', cv=cv, n_jobs=-1)
grid_search.fit(X_train, y_train)
# 打印最佳参数
print("Best Parameters: ", grid_search.best_params_)
# 使用最佳参数的分类器进行训练和预测
best_classifier = grid_search.best_estimator_
best_classifier.fit(X_train, y_train)
y_pred = best_classifier.predict(X_test)
# 计算性能指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, best_classifier.predict_proba(X_test)[:, 1])
# 打印性能指标
print(f'Accuracy: {accuracy}')
print(f'Precision: {precision}')
print(f'Recall: {recall}')
print(f'F1-Score: {f1}')
print(f'ROC-AUC: {roc_auc}')
# 绘制ROC曲线
fpr, tpr, thresholds = roc_curve(y_test, best_classifier.predict_proba(X_test)[:, 1])
plt.figure()
plt.plot(fpr, tpr, label=f'ROC Curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC)')
plt.legend(loc='lower right')
plt.show()
# 绘制混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
print('Confusion Matrix:')
print(conf_matrix)

输出结果

Best Parameters: {‘max_depth’: 10, ‘min_samples_leaf’: 1, ‘min_samples_split’: 5, ‘n_estimators’: 200}

Accuracy: 0.8928571428571429

Precision: 0.8666666666666667

Recall: 0.9285714285714286

F1-Score: 0.896551724137931

ROC-AUC: 0.9081632653061225

Confusion Matrix:

[[12 2]

[ 1 13]]

目录
相关文章
|
机器学习/深度学习 传感器 安全
2023 年高教社杯全国大学生数学建模B 题 多波束测线问题思路及参考代码
2023 年高教社杯全国大学生数学建模B 题 多波束测线问题思路及参考代码
|
3月前
|
算法 搜索推荐 数据挖掘
【2024年华数杯全国大学生数学建模竞赛】C题:老外游中国 问题思路分析及Python代码实现
本文提供了2024年华数杯全国大学生数学建模竞赛C题“老外游中国”的解题思路分析和Python代码实现,涉及景点评分统计、城市综合评价、游玩路线规划以及特定条件下的旅游优化问题。
628 6
【2024年华数杯全国大学生数学建模竞赛】C题:老外游中国 问题思路分析及Python代码实现
|
3月前
|
决策智能
2024 年江西省研究生数学建模竞赛B题:投标中的竞争策略问题问题分析及实现代码
本文是关于2024年江西省研究生数学建模竞赛B题的解题思路,题目要求建立投标数学模型分析招投标机制,并提出优化策略和设计更合理的投标规则体系,以提高中标概率和招投标过程的公平性和效率。
84 4
|
3月前
|
机器学习/深度学习 数据采集 算法
【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 Python代码实现
本文介绍了2023年华数杯全国大学生数学建模竞赛C题的Python代码实现,探讨母亲身心健康对婴儿成长的影响,包括建立数学模型研究母亲身体和心理指标与婴儿行为特征和睡眠质量的关系,以及通过优化模型分析治疗费用与母亲心理健康状况的关系。
99 0
【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 Python代码实现
|
3月前
【2023 年第三届长三角高校数学建模竞赛】C 题 考研难度知多少 考研情况相关数据下载
本文介绍了2023年第三届长三角高校数学建模竞赛C题的背景和要求,聚焦于分析2023年考研难度及其影响因素,并探讨了自1979年以来考研难度的变化趋势和未来预测,同时提供了相关数据集的详细介绍和获取方式。
25 0
【2023 年第三届长三角高校数学建模竞赛】C 题 考研难度知多少 考研情况相关数据下载
|
3月前
|
机器学习/深度学习 数据采集 算法
【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 45页论文及python代码
本文通过收集390名3至12个月婴儿及其母亲的相关数据,运用结构方程模型、相关性分析和多种机器学习模型,研究了母亲身心健康对婴儿行为特征和睡眠质量的影响,并提出了改善母婴交互质量和提高婴儿睡眠质量的解决方案。
90 0
【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 45页论文及python代码
|
4月前
|
人工智能 自然语言处理 前端开发
来点干货:AI 求职季通义灵码实战经验分享局
4000 份 AI 求职季见面礼限时派发中!通义灵码陪你备战求职季,和你的“AI 冲刺搭子”挑战大厂技术面试真题。
281 13
|
6月前
|
存储 安全 计算机视觉
参加第十二届中国软件杯比赛感想以及经验
今年我作为参赛选手参加了中国软件杯南京线下赛,参加了总决赛答辩环节,下面总结一些参加比赛的经验以及感受
|
算法
2021 年高教社杯全国大学生数学建模竞赛题目(D 题 连铸切割的在线优化)
连铸是将钢水变成钢坯的生产过程,具体流程如下(图 1):钢水连续地从中间包浇入结晶器,并按一定的速度从结晶器向下拉出,进入二冷段。钢水经过结晶器时,与结晶器表面接触的地方形成固态的坯壳。
507 0
2021 年高教社杯全国大学生数学建模竞赛题目(D 题 连铸切割的在线优化)
2021 年高教社杯全国大学生数学建模竞赛题目(B 题 乙醇偶合制备 C4 烯烃)
C4 烯烃广泛应用于化工产品及医药的生产,乙醇是生产制备 C4 烯烃的原料。在制备过程中,催化剂组合(即:Co 负载量、Co/SiO2 和 HAP 装料比、乙醇浓度的组合)与温度对 C4 烯烃的选择性和 C4 烯烃收率将产生影响(名词解释见附录)。
423 0
2021 年高教社杯全国大学生数学建模竞赛题目(B 题 乙醇偶合制备 C4 烯烃)