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

news2024/10/7 13:15:40

2023年华为杯数学建模E题 代码复盘

  • 写在最前面
  • 目录
  • 问题1a
    • 计算时间间隔
      • 思路说明
      • 代码
      • 输出结果
    • 插值求解
      • 思路
      • 代码
      • 输出结果
    • 绘图
    • 绘制3D图(待修改)
  • 问题1b
    • 数据预处理
      • 思路
      • 代码
    • 模型训练
      • 思路
      • 代码
      • 输出结果
      • 网格调参代码
      • 输出结果

写在最前面

超开心又有点遗憾
结果上来看 国二很可以了 顺便买个策略的教训
和数统专业队友——文月宝 配合相当默契 ~ 主要负责写代码,第一次建模比赛可以几乎不写论文,说一下思路就行,真的好爽啊;还能帮我把绘图优化,流程图也真的好好看

其他;

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

每次数模建模有点像是一年一次的摸底考,通过实践感受自身的进步。
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]]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1208556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

matlab二维曲面散点图插值方法

在 MATLAB 中&#xff0c;你可以使用以下函数进行二维曲面散点插值&#xff1a; griddata: 该函数可以在散点数据上进行二维插值&#xff0c;生成平滑的曲面。它支持多种插值方法&#xff0c;包括三次样条插值、最近邻插值、线性插值和自然邻近法插值。 scatteredInterpolant:…

《RT-DETR魔术师》专栏介绍 CSDN独家改进创新实战 专栏目录

RT-DETR魔术师专栏介绍&#xff1a; https://blog.csdn.net/m0_63774211/category_12497375.html ✨✨✨魔改创新RT-DETR &#x1f680;&#x1f680;&#x1f680;引入前沿顶会创新&#xff08;CVPR2023&#xff0c;ICCV2023等&#xff09;&#xff0c;助力RT-DETR &#…

专题知识点-二叉树-(非常有意义的一篇文章)

这里写目录标题 二叉树的基础知识知识点一(二叉树性质 )树与二叉树的相互转换二叉树的遍历层次优先遍历树的深度和广度优先遍历中序线索二叉树二叉树相关遍历代码顺序存储和链式存储二叉树的遍历二叉树的相关例题左右两边表达式求值求树的深度找数找第k个数二叉树非递归遍历代码…

微信小程序 生命周期方法 页面路由 开发示例 自定义全局数据 链接跳转

目录 1. 生命周期方法 2. 页面路由 3. 开发示例 3.1 自定义全局数据 3.2 链接跳转 1. 生命周期方法 打开app.js Page生命周期函数 下面的Page生命周期图与上面的Page生命周期函数进行对比便于理解&#xff1a; 视图线程和应用服务线程会同时运行&#xff0c;应用服务线程…

微信个人号api接口开发

请求URL&#xff1a; http://域名地址/sendFile 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是string登录实例标识wcId是string接收…

【保姆级教程】Linux安装JDK8

本文以centos7为例&#xff0c;一步一步进行jdk1.8的安装。 1. 下载安装 官网下载链接&#xff1a; https://www.oracle.com/cn/java/technologies/downloads/#java8 上传jdk的压缩包到服务器的/usr/local目录下 在当前目录解压jdk压缩包&#xff0c;如果是其它版本&#xf…

Nessus漏洞扫描工具

Nessus 1、官网下载安装包2、centos7 安装Nessus3、启动Nessus4、网页访问88435、离线激活工具6、其他问题7、漏洞扫描使用 Nessus 是全世界最多人使用的系统漏洞扫描与分析软件。总共有超过75,000个机构使用Nessus 作为扫描该机构电脑系统的软件。 1、官网下载安装包 官网下载…

【Linux】Ubuntu16.04下完美安装python高版本及对应版本的pip

Ubuntu16.04下完美安装python高版本及对应版本的pip 方法一:直接用命令安装python3.6&#xff08;但我没安装成功&#xff09; 好像是因为Ubuntu16.04的软件仓库&#xff08;源&#xff09;中python的最高版本就是python3.5&#xff0c;所以无法直接用apt来安装 #方法一 sudo…

【开源】基于Vue.js的校园失物招领管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目详细录屏 二、研究内容2.1 招领管理模块2.2 寻物管理模块2.3 系统公告模块2.4 感谢留言模块 三、界面展示3.1 登录注册3.2 招领模块3.3 寻物模块3.4 公告模块3.5 感谢留言模块3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 基于Vue…

【软考篇】中级软件设计师 第二部分(一)

中级软件设计师 第二部分&#xff08;一&#xff09; 八. 层次化结构8.1 局部性原理8.2 体系8.3 分类8.3.1 存取方式8.3.2 工作方式 8.4 Cache8.4.1 例题 8.5 地址映像 九. 主存编址9.1 例题一 十. 可靠性10.1 串联系统和并联系统 十一. 网络安全11.1 保密性11.2 完整性&#x…

金财数科无代码开发平台:轻松实现电商、CRM、广告推广系统的集成连接

连接与集成&#xff1a;挖掘电商平台的潜力 金财数科是一家领先的信息技术公司&#xff0c;专注于利用前沿技术如互联网、人工智能、大数据和区块链等&#xff0c;为传统财税信息化方案和产品提供升级改造&#xff0c;并打造新一代智能财税SaaS平台。我们的目标是帮助企业通过…

Python接口测试框架选择之pytest+yaml+Allure!

一、为什么选择pytest&#xff1f; pytest完全兼容python自带的unittest pytest让单元测试更简单&#xff0c;能很好的管理测试用例。 对于实现接口测试的复杂场景&#xff0c;pytest的fixture、PDB等高阶用法都能实现需求。 入门简单&#xff0c;对于代码基础薄弱的团队人…

UWB基础——IEEE 802.15.4z中可选波形

在前面的文章&#xff1a;UWB基础——基带简介中介绍了关于UWB基带脉冲波形以及相关的定义&#xff0c;本文继续介绍在IEEE 802.15.4z-2020标准中新增的一些兼容脉冲形状。 1. 基带脉冲响应 传输脉冲形状p(t)受到与标准参考脉冲r(t)的互相关函数形状的限制。 两个脉冲之间归一…

Spring面试题:(七)Spring AOP思想及实现

AOP思想的概念 AOP的实现&#xff1a;动态代理技术 通过spring容器获取目标对象和增强对象&#xff0c;通过动态代理生产代理对象&#xff0c;在目标对象的目标方法执行增强方法&#xff0c;返回生成代理对象给spring容器&#xff0c;在获取bean时则获取代理对象。 JDK代理和…

【备忘】ChromeDriver 官方下载地址 Selenium,pyppetter依赖

https://googlechromelabs.github.io/chrome-for-testing/#stable windows系统选择win64版本下载即可

ctf之流量分析学习

链接&#xff1a;https://pan.baidu.com/s/1e3ZcfioIOmebbUs-xGRnUA?pwd9jmc 提取码&#xff1a;9jmc 前几道比较简单&#xff0c;是经常见、常考到的类型 1.pcap——zip里 流量分析里有压缩包 查字符串或者正则表达式&#xff0c;在包的最底层找到flag的相关内容 我们追踪…

Vue3 watch监视和watchEffect函数

Vue3 中的watch使用效果和Vue2 中配置watch配置项的使用效果是一致的。 使用watch监视之前&#xff0c;需要先对watch进行引入。 import {watch} from vue; 一、监视一个ref对象 以下情况只适用于监视一个ref对象。 watch(监视对象, (newValue, oldValue) > { // 监视操作…

C++设计实现日志系统

转载&#xff1a;C设计实现日志系统 - 知乎 (zhihu.com) 日志系统几乎是每一个实际的软件项目从开发、测试到交付&#xff0c;再到后期的维护过程中极为重要的 查看软件代码运行流程、 还原错误现场、 记录运行错误位置及上下文等的重要依据。一个高性能的日志系统&#xff0c…

Spring Cloud学习(八)【RabbitMQ 服务异步通讯】

文章目录 初识 MQ同步通讯异步通讯MQ 常见框架 RabbitMQ 快速入门RabbitMQ 单机部署RabbitMQ概述常见消息模型 SpringAMQPSimpleQueue 模型WorkQueue 模型发布订阅模型发布订阅-Fanout Exchange发布订阅-DirectExchange发布订阅-TopicExchange消息转换器 初识 MQ 同步通讯 同步…

[Linux] DHCP网络

一、DHCP服务 1.1 DHCP的简介 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;通常被应用在大型的局域网络环境中&#xff0c;主要作用是集中地管理、分配IP地址&#xff0c;使网络环境中的主机动态的获得IP地址、Gateway地址…