【数据+代码】使用XGBoost实现回归分析

1、引言

本文涵盖主题:XGBoost 实现回归分析,包括数据准备、模型训练和结果分析三个方面。

 

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

2、数据准备

本例中,我们使用的是1973年至2016年间美国燃烧煤炭发电产生的二氧化碳排放量数据集。

数据帧包含需要分隔为年和月列的列“YYYYMM”。在此步骤中,我们还将删除数据帧中可能存在的任何空值。将特征工程中新增的年、月列替换“YYYYMM”,同时查询数据中是否含有重复值,如有需另作处理,本数据集不涵盖。

data = pd.read_csv('co2.csv')
data['Month'] = data.YYYYMM.astype(str).str[4:6].astype(float)
data['Year'] = data.YYYYMM.astype(str).str[0:4].astype(float)
data.drop(['YYYYMM'], axis=1, inplace=True)
data.replace([np.inf, -np.inf], np.nan, inplace=True)
data.isnull().sum()

将月份和年份作为特征,CO2 排放量作为标签。

X = data.loc[:,['Month', 'Year']].values
y = data.loc[:,'Value'].values

使用 train_test_split 函数来划分出训练集和测试集:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

可视化X、y,观察随时间变化,co2含量变化:

plt.figure(figsize=(10, 5), dpi=300)
sns.lineplot(x='Year', y='Value', data=data,errorbar='sd', err_style='band',color="#ec661f")

如图:

 

3、模型训练

使用 XGBoost 建立回归模型并进行训练。这里需要设置一系列参数,例如 n_estimators(基分类器数量)、learning_rate(学习率)、subsample(子采样比例)、colsample_bytree(列采样比例)、max_depth(树的最大深度)和 gamma(用于控制树的复杂度)等参数。

reg_mod = xgb.XGBRegressor(
    n_estimators=1000,
    learning_rate=0.08,
    subsample=0.75,
    colsample_bytree=1, 
    max_depth=7,
    gamma=0,
)

# 训练模型并指定评估数据集
eval_set = [(X_train, y_train), (X_test, y_test)]
reg_mod.fit(X_train, y_train, eval_set=eval_set, eval_metric='rmse', verbose=False)
# 绘制损失曲线
sns.set_style("white")
palette = sns.color_palette("Set2", n_colors=2) 

plt.plot(reg_mod.evals_result()['validation_0']['rmse'], label='train', color=palette[0], linewidth=2)
plt.plot(reg_mod.evals_result()['validation_1']['rmse'], label='test', color=palette[1], linewidth=2)
plt.xlabel('Iteration')
plt.ylabel('RMSE')
plt.legend()
plt.savefig('Loss.png')
plt.show()

模型损失曲线如图:

同时,模型还需要进行交叉验证和评估指标选择,例如 RMSE 和 R_Squared Score 等。以下是对模型进行训练和评估的代码:

from sklearn.metrics import r2_score
reg_mod.fit(X_train, y_train)
scores = cross_val_score(reg_mod, X_train, y_train,cv=10)
print("Mean cross-validation score: %.2f" % scores.mean())
rmse = np.sqrt(mean_squared_error(y_test, predictions))
print("RMSE: %f" % (rmse))
r2 = np.sqrt(r2_score(y_test, predictions))
print("R_Squared Score : %f" % (r2))

模型评估结果如下:

  • Mean cross-validation score: 0.97

  • RMSE: 4.683184
  • R_Squared Score : 0.989909

通过上述模型评估结果可知,该模型针对此数据能够较好的拟合,通过下述代码,观察测试集拟合效果:

sns.set_style("white") 
palette = sns.color_palette("husl", n_colors=2) 

# 设置画布大小和分辨率
plt.figure(figsize=(10, 5), dpi=300)

# 绘制测试集数据的真实值和模型预测值的折线图
x_ax = range(len(y_test))
plt.plot(x_ax, y_test, label="True Values", color=palette[0], linewidth=1)
plt.plot(x_ax, predictions, label="Predicted Values", color=palette[1], linewidth=1)

# 添加标题和标签
plt.title("Carbon Dioxide Emissions - True vs Predicted Values")
plt.xlabel("Sample Number")
plt.ylabel("CO2 Emissions")

# 显示图例
plt.legend()
plt.savefig('True vs Predicted Values.png')
# 显示图形
plt.show()

拟合曲线如图:

 

通过上图可知,模型拟合效果较好,能够有效预测数据中峰值等信息。

上述各数据及图标表明,该模型具有较高准确率,通过下述代码,观察未来日期内co2含量:

sns.set_style("white") 
palette = sns.color_palette("husl", n_colors=1) 

# 设置画布大小和分辨率
plt.figure(figsize=(10, 5), dpi=300)

# 将预测值转换为DataFrame格式,并添加日期列
df_pred = pd.DataFrame(predictions, columns=['Predicted Values']) 
df_pred['Date'] = pd.date_range(start='8/1/2016', periods=len(df_pred), freq='M')

# 绘制预测值的折线图
sns.lineplot(x='Date', y='Predicted Values', data=df_pred, color=palette[0], linewidth=1)

# 添加标题和标签
plt.title("Carbon Dioxide Emissions - Forecast")
plt.xlabel("Date")
plt.ylabel("CO2 Emissions")
plt.savefig('Emissions - Forecast.png')

# 显示图形
plt.show()

预测曲线如图:

 

感谢您阅读本篇文章!如果您对神经网络与深度学习等方面感兴趣,欢迎关注我们的微信公众号(小Z的科研日常)。

 

<think>嗯,用户想了解C语言中匿名枚举的用法,特别是匿名枚举的使用方法和示例。首先,我需要回忆一下C语言中枚举的基本知识,然后看看匿名枚举和普通枚举的区别。 根据之前的引用资料,枚举在C语言中用于符号化数字,提高代码可读性。普通枚举需要先定义类型,再声明变量,比如enum Color { RED, GREEN, BLUE }; enum Color c = RED;。而匿名枚举可能不需要定义类型名,直接使用枚举成员的值,这应该就是匿名枚举的特点。 用户的问题是关于匿名枚举的使用方法,我需要确定C语言是否支持匿名枚举。根据C标准,C语言中的枚举必须要有标签或者变量,但有时候可以通过省略标签来创建匿名枚举,同时声明变量。例如:enum { RED, GREEN, BLUE } color; 这里的color变量就是这个匿名枚举类型的实例。这种情况下,枚举没有类型名,所以之后不能再定义其他同类型的变量,但color可以直接使用RED、GREEN等值。 接下来需要举出示例,说明匿名枚举的典型用法。比如在结构体中定义常量,或者在全局作用域中定义一组常量。例如: struct Config { enum { MAX_SIZE = 100, TIMEOUT = 30 }; int size; }; 这样,结构体中的MAX_SIZE和TIMEOUT可以作为常量使用。但要注意,这可能不是所有编译器都支持,尤其是旧版本的编译器,所以可能需要使用更通用的方法,比如在全局作用域中定义匿名枚举常量: enum { BUFFER_SIZE = 1024, MAX_USERS = 50 }; 这样,BUFFER_SIZE和MAX_USERS就可以作为整型常量使用,而无需指定枚举类型名。 另外,用户可能遇到的问题包括作用域问题,比如匿名枚举的成员是否会影响其他同名常量,或者如何在不同的作用域中使用匿名枚举。需要提醒用户注意枚举成员的作用域,比如在结构体内部定义的匿名枚举成员可能只在该结构体内有效,或者在全局作用域中定义的可能会污染全局命名空间。 还要注意匿名枚举与普通枚举的区别,匿名枚举通常用于一次性的变量或常量定义,无法复用类型,而普通枚举可以多次声明变量。此外,匿名枚举的成员在C语言中是作为整型常量存在的,可以直接使用,不需要通过枚举变量来访问。 可能用户在使用匿名枚举时遇到编译错误,比如重复定义或者作用域问题,需要给出解决方法,比如检查是否有重复的枚举成员名称,或者确认编译器是否支持匿名枚举的某些特性。 总结回答结构:先解释匿名枚举的概念,与普通枚举的区别,使用场景,然后给出具体的使用示例,包括全局作用域、结构体内、与宏定义的对比,最后说明注意事项和常见问题。</think>### C语言匿名枚举使用方法详解 #### 一、基本概念 匿名枚举是**没有明确类型名称的枚举类型**,常用于定义**一次性使用的整型常量集合**。与普通枚举不同,它**直接声明常量值而不创建可复用的枚举类型**[^1]。 #### 二、核心语法 ```c // 匿名枚举标准语法 enum { 常量1 = 值1, 常量2 = 值2, //... } 变量名; // 可选变量声明 ``` #### 三、典型使用场景 1. **全局作用域常量定义** ```c enum { MAX_BUFFER = 1024, TIMEOUT_MS = 5000 }; // 直接使用常量 char buffer[MAX_BUFFER]; ``` 2. **结构体/联合体内置常量** ```c struct NetworkConfig { enum { MIN_PORT = 1024, MAX_PORT = 65535 }; int current_port; }; ``` 3. **替代宏定义** ```c // 优于 #define ERROR_CODE 1 enum { ERROR_CODE = 1, SUCCESS_CODE = 0 }; ``` #### 四、完整示例 ```c #include <stdio.h> // 定义匿名枚举常量 enum { LOG_DEBUG = 1, LOG_WARNING = 2, LOG_ERROR = 4 }; int main() { int log_level = LOG_DEBUG; switch(log_level) { case LOG_DEBUG: printf("Debug mode activated\n"); break; case LOG_WARNING: printf("Warning mode\n"); break; case LOG_ERROR: printf("System error!\n"); break; } return 0; } ``` #### 五、注意事项 1. **作用域规则**:枚举常量具有**与声明位置匹配的作用域**(全局/局部) 2. **类型安全**:C语言枚举本质是int类型,匿名枚举不提供额外类型检查 3. **编译器差异**:部分旧编译器(如C89)可能要求枚举必须关联变量名 4. **常量冲突**:避免与其他作用域的同名常量产生冲突 #### 六、与普通枚举对比 | 特性 | 匿名枚举 | 普通枚举 | |-----------------|---------------------|---------------------| | 类型名称 | 无 | 需要明确声明 | | 作用域 | 声明位置决定 | 类型全局可见 | | 重复使用性 | 单次使用 | 可多次实例化 | | 内存占用 | 无类型元数据 | 包含类型信息 | #### 七、常见问题解决 **问题1:出现"redeclaration of enumerator"错误** ```c enum { A = 1 }; enum { A = 2 }; // 错误!重复定义 ``` **解决方案**:统一管理全局常量定义 **问题2:结构体内匿名枚举访问失败** ```c struct S { enum { SIZE=100 }; }; printf("%d", SIZE); // 错误!应使用struct S::SIZE (C++语法) ``` **C语言解决方案**: ```c printf("%d", (struct S){0}.SIZE); // 通过临时变量访问 ```
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小Z的科研日常

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

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

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

打赏作者

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

抵扣说明:

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

余额充值