分类 Python 下的文章

假设你正在为一家公司开发一个房价预测模型。请根据以下数据集构建线性回归模型,并使用该模型对新的输入数据进行预测。
数据集:(房间数,房屋面积,卧室数量,价格)
(3, 1500, 2, 450000)
(4, 2200, 3, 650000)
(5, 3000, 4, 875000)
(6, 3500, 5, 950000)
(7, 4000, 6, 1200000)

请编写Python代码来实现此任务,包括:
1、数据加载与预处理
2、模型训练及参数估计
3、新数据的预测及结果输出
注:除非特别说明,否则默认使用numpy和sklearn库。

参考输出格式:
输入数据: [3, 1300, 2]
预测结果为: $426566.98


import numpy as np
from sklearn.linear_model import LinearRegression

#数据集加载和预处理
X=np.array([[3,1500,2],[4,2200,3],[5,3000,4],[6,3500,5],[7,4000,6]])
y=np.array([45000,650000,875000,950000,1200000])

#模型训练和结果输出
lr = LinearRegression()
lr.fit(X, y)

#新数据的预测及结果输出
new_data = np.array([3, 1300, 2]).reshape(1,-1) #注意这里需要将输入样本转换为矩阵形式
prediction =lr.predict(new_data)[0]
print("输入数据:",new_data[0])
print("预测结果为:",pred_label)

赛题背景
火力发电的基本原理是:燃料在燃烧时加热水生成蒸汽,蒸汽压力推动汽轮机旋转,然后汽轮机带动发电机旋转,产生电能。 在这一系列的能量转化中,影响发电效率的核心是锅炉的燃烧效率,即燃料燃烧加热水产生高温高压蒸汽。锅炉的燃烧效率的影响因素很多,包括锅炉的可调参数,如燃烧给量,一二次风,引风,返料风,给水水量;以及锅炉的工况,比如锅炉床温、床压,炉膛温度、压力,过热器的温度等。
赛题描述
经脱敏后的锅炉传感器采集的数据(采集频率是分钟级别),根据锅炉的工况,预测产生的蒸汽量。

zhengqi_train.txt
zhengqi_test.txt


import numpy as np
import pandas as pd

df_train=pd.read_csv(r'.\zhengqi_train.txt',sep='\t')
df_test=pd.read_csv(r'.\zhengqi_test.txt',sep='\t')

# 使用head查看训练集和测试集前5条数据的情况
df_train.head()

df_test.head()

# non-null代表数据中没有缺失值,因此不需要对于数据进行缺失值填充
df_train.info()

df_test.info()

import matplotlib.pyplot as plt
import seaborn as sns

#提取df_train中的特征标签,并将起转换成列表形式
feature_list=list(df_train.columns)
#为方便之后使用,去掉列表中被一并提取出来的target标签,确保仅留特征标签
feature_list.remove('target')
#显示特征标签列表
feature_list

#对于特征标签列表feature_list中的特征标签进行操作,逐个绘制单变量数据分布图,训练集和测试集的相同特征分布情况绘制在同一张图上以方便比对
for i in feature_list:
    sns.distplot(df_train[{i}])
    sns.distplot(df_test[{i}])
    plt.title(i)
    plt.show()

# 去除数据特征分布不一致的数据列
df_train=df_train[['V0','V1','V3','V4','V8','V10','V12','V15','V16','V18','V24','V25','V26','V28','V29','V30','V31','V32','V33','V34','V36','target']]
df_test=df_test[['V0','V1','V3','V4','V8','V10','V12','V15','V16','V18','V24','V25','V26','V28','V29','V30','V31','V32','V33','V34','V36']]

#提取df_train中的特征标签,并将起转换成列表形式
feature_list=list(df_train.columns)
#为方便之后使用,去掉列表中被一并提取出来的target标签,确保仅留特征标签
feature_list.remove('target')
#显示特征标签列表
feature_list

# 相关性分析
# corr的方法,默认的相关系数计算方式就是皮尔逊相关系数
df_train.corr()

# 只分析各特征标签与预测标签(target)之间的相关性,查看上表的最后一列相关系数计算结果,相关系数的绝对值大于0.5的为强相关性,
# 小于0.5的为弱相关性,0附近的为没有相关性,系数为正代表正相关,系数为负代表负相关。

# 绘制特征标签与预测标签(target)的散点图,与相关系数的计算结果进行相互校对
for i in feature_list:
    sns.scatterplot(df_train[f'{i}'],df_train['target'])
    plt.show()

# 以0.5为界限,同时在训练集和测试集中去除相关系数绝对值低于0.5的特征,确保被输入模型进行训练的特征与预测目标值有较强的相关性。
df_train=df_train[['V0','V1','V3','V4','V8','V12','V16','V31','target']]
df_test=df_test[['V0','V1','V3','V4','V8','V12','V16','V31']]
#提取df_train中的特征标签,并将起转换成列表形式
feature_list=list(df_train.columns)
#为方便之后使用,去掉列表中被一并提取出来的target标签,确保仅留特征标签
feature_list.remove('target')
#显示特征标签列表
feature_list

# 正态分布检验

# 检验各个特征中数据的偏度,偏度定义中包括正态分布(偏度=0),右偏分布(也叫正偏分布,其偏度>0),左偏分布(也叫负偏分布,其偏度<0)
from scipy import stats
for i in feature_list:
    skew = stats.skew(df_train[f'{i}'])
    print(f'the skew value of feture {i} is {skew}')

# 检验各个特征中数据的峰度。若峰度≈0,分布的峰态服从正态分布;若峰度>0,分布的峰态陡峭(高尖);若峰度<0,分布的峰态平缓(矮胖)
for i in feature_list:
    kurtosis = stats.kurtosis(df_train[f'{i}'])
    print(f'the kurtosis value of feture {i} is {kurtosis}')

# 绘制偏度分布图
for feature in feature_list:
    skew_value = df_train[feature].skew()
    sns.distplot(df_train[feature], kde=True)
    plt.show()
    
# 各特征数据基本符合正态分布

# 数据集拆分
from sklearn.model_selection import train_test_split
df_train_value = df_train.drop('target', axis=1)
df_train_target = df_train['target']
df_train_value, df_vali_value, df_train_target, df_vali_target=train_test_split(df_train_value, df_train_target, test_size=0.25,random_state=1)

# df_train_value:训练集特征数据集(总数据的75%)

# df_train_target:训练集的预测目标数据(总数据的75%)

# df_vali_value:交叉验证集特征数据集(总数据的25%)

# df_vali_target:交叉验证集的预测目标数据(总数据的25%)

# 对于df_train_value,df_train_target,df_vali_value,df_vali_target的index进行重置,确保所有数据都从第0条开始排序
df_train_value=df_train_value.reset_index(drop=True)
df_vali_value=df_vali_value.reset_index(drop=True)
df_train_target=df_train_target.reset_index(drop=True)
df_vali_target=df_vali_target.reset_index(drop=True)

# 转换为np矩阵形式
df_train_value=np.array(df_train_value)
df_vali_value=np.array(df_vali_value)
df_train_target=np.array(df_train_target)
df_vali_target=np.array(df_vali_target)

# 验证指标MSE
from sklearn.metrics import mean_squared_error

# 随机森林算法
from sklearn.ensemble import RandomForestRegressor
# 建立模型
model_RF=RandomForestRegressor(n_estimators=200, random_state=0)
# 训练模型
model_RF.fit(df_train_value,df_train_target)

# 对于交叉验证集特征数据集df_vali_value进行预测
predict_RF=model_RF.predict(df_vali_value)
mean_squared_error(df_vali_target,predict_RF)

# 抽取交叉验证集的100组数据采用可视化手段直观检验预测效果
plt.plot(df_vali_target[0:101])
plt.plot(predict_RF[0:101])

df_test=df_test.reset_index(drop=True)
df_test=np.array(df_test)

# 对测试数据df_test进行预测
predict_RF=model_RF.predict(df_test)
# 抽取test数据集中100条可视化
plt.plot(predict_RF[0:101])

# XGBoost
import xgboost as xgb
model_xgb=xgb.XGBRegressor(max_depth=5, learning_rate=0.1, n_estimators=160, silent=True, objective='reg:linear')
model_xgb.fit(df_train_value,df_train_target)
predict_xgb=model_xgb.predict(df_vali_value)
print(mean_squared_error(df_vali_target,predict_BR))
plt.plot(df_vali_target[0:101])
plt.plot(predict_xgb[0:101])

# 线性回归
from sklearn.linear_model import LinearRegression
model_LR=LinearRegression()
model_LR.fit(df_train_value,df_train_target)
predict_LR=model_LR.predict(df_vali_value)
print(mean_squared_error(df_vali_target,predict_BR))
plt.plot(df_vali_target[0:101])
plt.plot(predict_LR[0:101])

# 贝叶斯
from sklearn import linear_model
model_BR=linear_model.BayesianRidge()
model_BR.fit(df_train_value,df_train_target)
predict_BR=model_BR.predict(df_vali_value)
print(mean_squared_error(df_vali_target,predict_BR))
plt.plot(df_vali_target[0:101])
plt.plot(predict_BR[0:101])

以下是使用SARSA算法修改后的代码:

# 开始训练Q表格
all_episode_reward = []  # 用于记录每次迭代的总奖励,这样就可以知道智能体是否有进步了
for i in range(num_episodes):
    ## 初始化环境,得到初始状态
    s, _= env.reset()  # 初始状态值
    rAll = 0  # 用于记录这次游戏的总奖励,这里先初始化为0
    ## The SARSA algorithm
    ## 首先,根据epsilon-greedy选择当前状态s下的动作a
    a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
    for j in range(99):
        if render: env.render()
        ## 与环境交互得到下一个状态s1和即时奖励r
        s1, r, d, _, _ = env.step(a)
        ## 根据epsilon-greedy选择在状态s1下的下一个动作a1
        a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
        ## 使用SARSA更新Q表格
        Q[s, a] = Q[s, a] + lr * (r + lambd * Q[s1, a1] - Q[s, a])
        ## 更新当前状态和动作
        rAll += r
        s = s1
        a = a1
        if d is True:
            break
    if i == 0:
        all_episode_reward.append(rAll)
    else:
        all_episode_reward.append(all_episode_reward[-1] * 0.99 + rAll * 0.01)
    print(
    'Training  | Episode: {}/{}  | Episode Reward: {:.4f}  | all_episode_reward: {:.4f} | Running Time: {:.4f}'.format(
        i + 1, num_episodes, rAll, all_episode_reward[i], time.time() - t0
        )
    )

# 保存Q表格
path = os.path.join('model', '_'.join([alg_name, env_id]))
if not os.path.exists(path):
    os.makedirs(path)
np.save(os.path.join(path, 'Q_table.npy'), Q)

# 绘制迭代的总奖励
plt.plot(all_episode_reward)
if not os.path.exists('image'):
    os.makedirs('image')
plt.savefig(os.path.join('image', '_'.join([alg_name, env_id])))

# 打印Q表格
print("Final Q-Table Values:/n %s" % Q)

相对于原始代码,使用SARSA算法修改后的主要变化是:

在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
使用SARSA更新Q表格时,将下一个状态和动作的Q值Q[s1, a1]考虑进去。
这样就能够实现SARSA算法来训练Q表格,从而实现强化学习任务。


以下是使用SARSA算法修改后的代码:


# 模型评估
path = os.path.join('model', '_'.join([alg_name, env_id]))
Q = np.load(os.path.join(path, 'Q_table.npy'))
sum_rAll = 0
for i in range(num_episodes):
    ## 初始化环境,得到初始状态
    s, _ = env.reset()
    rAll = 0
    ## The SARSA algorithm
    ## 首先,根据epsilon-greedy选择当前状态s下的动作a
    a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
    for j in range(99):
        ## 与环境交互得到下一个状态s1和即时奖励r
        s1, r, d, _, _ = env.step(a)
        ## 根据epsilon-greedy选择在状态s1下的下一个动作a1
        a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
        ## 更新当前状态和动作
        rAll += r
        s = s1
        a = a1
        if d is True:
            break
    print(
        'Testing  | Episode: {}/{}  | Episode Reward: {:.4f}  | Running Time: {:.4f}'.format(
            i + 1, num_episodes, rAll,
            time.time() - t0
        )
    )
    sum_rAll += rAll
print('游戏中成功闯关比例: {:.4f}'.format(sum_rAll/num_episodes))

相对于原始代码,使用SARSA算法修改后的主要变化是:

在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
在模型评估时,使用SARSA算法更新当前状态和动作,并且在选择动作时也根据epsilon-greedy进行选择。