前言
自用。知识点跳跃且不适合Python或是编程0基础的同学看
主要是对现有代码的理解(审计)
本策略和金融没太大关系,主要是计算机和数学
1理论部分(可忽略)
- 回归问题
是机器学习中的一类问题,其中的目标是预测连续型的数值输出。换句话说,回归问题是一种建立输入变量与连续型输出变量之间关系的问题。
- K折交叉验证
在你的代码中,如果使用的是 K 折交叉验证且设置了 shuffle=False,那么每个样本确实会且仅会出现一次,但在不同的测试集中。
2 读取文件和数据标准化
读文件源程序
`# 读取 Excel 文件
df = pd.read_excel('E:\谷歌浏览器下载的文件\参考文献\Yinzi.xlsx')
# 对整个 DataFrame 进行线性插值
df_interpolated = df.interpolate(method='linear', axis=0)
df_interpolated.to_excel('E:\谷歌浏览器下载的文件\参考文献\merged_d123ta.xlsx', index=False)
# 检查是否存在缺失值
missing_values = df_interpolated.isnull().sum()
# 打印每列的缺失值数量
print(missing_values)
`
2.1read_excel
当你使用Pandas库中的read_excel()
函数从Excel文件中读取数据时,Pandas会将Excel文件中的每个工作表(sheet)解析为一个DataFrame对象。DataFrame是一个二维的数据结构,类似于电子表格,由行和列组成。让我详细解释一下数据在读取和处理过程中可能的格式转换:
-
数据类型推断:
-
Pandas会尝试根据每列的内容推断数据类型。例如,如果一列包含数字,Pandas会将其识别为数值型数据,如果一列包含字符串,Pandas会将其识别为对象(字符串)数据类型。
-
但有时候,Pandas可能会将数据错误地推断为不正确的数据类型。因此,可以通过
dtype
参数手动指定数据类型,以确保正确地解析数据。 -
缺失值处理:
-
在Excel文件中,可能会存在一些空单元格,这些空单元格在读取后会被Pandas解析为缺失值(NaN)。Pandas提供了许多方法来处理缺失值,如填充、删除或插值。
-
日期时间数据的解析:
-
如果Excel文件中包含日期时间数据,Pandas会尝试将其解析为日期时间数据类型。这使得可以对日期时间进行各种操作,如筛选、分组和计算时间间隔。
-
索引处理:
-
默认情况下,Pandas会自动生成一个整数索引,从0开始递增。但是,你也可以通过
index_col
参数指定一个列作为DataFrame的索引,或者在读取后通过set_index()
方法设置索引。 -
数据转换:
-
在DataFrame中,每列的数据类型可能不同,可以使用Pandas提供的方法对数据进行转换。例如,可以使用
astype()
方法将某一列的数据类型转换为其他类型。
标准化源程序
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from scipy.stats import boxcox
# 读取金融股票数据,假设数据已经存储在一个名为 'stock_data.csv' 的文件中
df = pd.read_excel('E:\谷歌浏览器下载的文件\参考文献\merged_d12s3ta.xlsx')
df = df.fillna(df.mean())
# 排除 'Symbol' 和 'TradingDate' 列
exclude_columns = ['Symbol', 'TradingDate' ,'ShortName_x','SecurityID_x','BuySymbol','LimitStatus']
numeric_columns = df.select_dtypes(include=['float64', 'int64']).columns
features_to_standardize = [col for col in numeric_columns if col not in exclude_columns]
2.2 features_to_standardize = [col for col in numeric_columns if col not
in exclude_columns]
在 Python 中,列表推导式中的条件语句可以跨越多行,不需要显式地使用换行符。Python 解释器会根据缩进来确定条件语句的范围。因此,你可以在一行中编写条件语句,也可以将其分成多行以提高可读性,但要确保缩进正确。例如:
features_to_standardize = [
col for col in numeric_columns if col not in exclude_columns
]
或者,如果条件语句较长,可以使用括号将其括起来:
features_to_standardize = [
col for col in numeric_columns
if (col not in exclude_columns and
some_other_condition)
]
这种写法更容易阅读和维护。
举个例子
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)
#even_squares=[0, 4, 16, 36, 64]
2.3 df[features_to_standardize] =
min_max_scaler.fit_transform(df[features_to_standardize])
可能情况为
df[['1', '11']] = min_max_scaler.fit_transform(df[['1', '11']])
说明这个方法是对多个列进行标准化的过程,而不是单个列
3模型训练-以SVM模型为例
以下为源程序
#SVM
import pandas as pd
from sklearn.model_selection import GridSearchCV, KFold
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, mean_absolute_error
from datetime import timedelta
import joblib
# 读取数据
data = pd.read_excel(r'E:\谷歌浏览器下载的文件\参考文献\SVM\t.xlsx')
# 提取特征和标签
X = data.drop(columns=['Symbol','TradingDate','ClosePrice', 'SecurityID_x']) # 解释变量
y = data['ClosePrice'] # 被解释变量
# 定义交叉验证
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# 定义SVM模型
svm_model = SVR()
# 定义要调优的参数空间
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': [0.001, 0.01, 0.1, 1],
'kernel': ['linear', 'rbf', 'poly']
}
# 定义评价指标
def rmse(y_true, y_pred):
return mean_squared_error(y_true, y_pred, squared=False)
# 计算平均绝对误差
def mae(y_true, y_pred):
return mean_absolute_error(y_true, y_pred)
# 定义用于滚动预测的函数
def rolling_predict(model, X, y, cv):
y_true = []
y_pred = []
for train_index, test_index in cv.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred.extend(model.predict(X_test))
y_true.extend(y_test)
return y_true, y_pred
# 执行交叉验证和参数优化
grid_search = GridSearchCV(svm_model, param_grid, cv=kf, scoring='neg_mean_squared_error', n_jobs=1)
grid_search.fit(X, y)
# 输出SVM默认参数
print("SVM默认参数:", svm_model.get_params())
svm_model.fit(X, y)
# 输出默认参数下的评价指标
default_predictions = svm_model.predict(X)
default_mse = mean_squared_error(y, default_predictions)
default_rmse = rmse(y, default_predictions)
default_mae = mae(y, default_predictions)
print("默认参数下的MSE:", default_mse)
print("默认参数下的RMSE:", default_rmse)
print("默认参数下的MAE:", default_mae)
# 输出最优参数和对应的评价指标
print("最优参数:", grid_search.best_params_)
print("最优评价指标(均方根误差):", abs(grid_search.best_score_) ** 0.5)
# 使用最优参数训练最终模型
best_model = grid_search.best_estimator_
# 保存最优参数的模型到.pkl文件中
joblib.dump(best_model, 'best_svm_model.pkl')
# 滚动预测
y_true, y_pred = rolling_predict(best_model, X, y, kf)
# 计算评价指标
mse = mean_squared_error(y_true, y_pred)
rmse_value = rmse(y_true, y_pred)
mae_value = mae(y_true, y_pred)
print("参数优化后的MSE:", mse)
print("参数优化后的RMSE:", rmse_value)
print("参数优化后的MAE:", mae_value)
# 输出参数优化后的模型到.pkl文件中
joblib.dump(best_model, 'best_svm_model.pkl')
print("参数优化后的模型已保存到 best_svm_model.pkl 文件中")
3.1 kf = KFold(n_splits=5, shuffle=True, random_state=42)
在这段代码中,`KFold` 对象被用于定义交叉验证的方式。让我解释一下其中的参数:
-
n_splits: 这是将数据分成的折数(即将数据集分成多少份)。在这个例子中,
n_splits=5
表示将数据集分成了 5 折交叉验证。 -
shuffle: 这是一个布尔值参数,表示在分割数据前是否要对数据进行洗牌。如果设置为True,那么在每次分割前都会打乱数据集的顺序。这有助于避免某些特定顺序对模型的影响,并且在数据分布不均匀的情况下可以提高模型的稳定性。在这个例子中,
shuffle=True
表示在分割数据之前要对数据进行洗牌。 -
random_state: 这是一个随机种子参数,用于控制数据的洗牌过程。如果两次分割数据时指定了相同的随机种子,那么得到的结果将是相同的。这有助于使实验结果具有可重复性。在这个例子中,
random_state=42
表示指定了随机种子为42。
3.2 param_grid (How to 参数设定)
以随机森林模型为例,你可以这样来查看参数及其含义:
from sklearn.ensemble import RandomForestRegressor
# 使用 help() 函数查看随机森林模型的参数
help(RandomForestRegressor)
得到一个返回文档。。。
这段文档提供了关于 RandomForestRegressor
类的参数说明。让我来逐一解释一下:
-
n_estimators: (default=100) 随机森林中树的数量(即决策树的个数)。更多的树可以提高模型的稳定性和准确性,但会增加计算成本。
-
criterion: (default=‘squared_error’) 衡量分裂质量的标准。对于回归问题,一般使用均方误差 (‘mse’) 或均绝对误差 (‘mae’)。
-
max_depth: (default=None) 决策树的最大深度。如果不设置,则树会一直生长,直到每个叶节点都包含少于min_samples_split个样本。
-
min_samples_split: (default=2) 节点在分裂之前所需的最小样本数。如果节点的样本数量小于该值,则不会进行分裂。
-
min_samples_leaf: (default=1) 叶节点所需的最小样本数。如果叶节点的样本数量小于该值,则不会继续分裂。
-
min_weight_fraction_leaf: (default=0.0) 叶节点的最小权重总和的分数。如果设置了sample_weight,则样本的权重会按照样本数量的比例计算。
-
max_features: (default=‘auto’) 在每个节点处进行分裂时考虑的特征数。可以设置为 ‘auto’、‘sqrt’、‘log2’ 或具体的整数值。 ‘auto’ 表示使用所有特征, ‘sqrt’ 表示使用 sqrt(n_features),‘log2’ 表示使用 log2(n_features)。
-
max_leaf_nodes: (default=None) 最大叶节点数量。如果不为None,则树会在达到该数量后停止生长。
-
min_impurity_decrease: (default=0.0) 节点分裂的最小不纯度减少量。分裂后的不纯度减少量必须大于等于该值才会执行分裂。
-
bootstrap: (default=True) 是否使用自助法 (bootstrap) 来构建树。如果为True,则每棵树都是从数据集中有放回地随机抽样得到的。
-
oob_score: (default=False) 是否计算 out-of-bag (OOB) 评分。如果为True,则模型会在拟合后自动计算并保存在属性 oob_score_ 中。
-
n_jobs: (default=None) 并行运行的作业数量。如果设置为-1,则使用所有可用的处理器。
-
random_state: (default=None) 随机种子用于控制随机数生成。
-
verbose: (default=0) 控制拟合过程的详细程度。如果大于0,则会输出拟合进度。
-
warm_start: (default=False) 是否使用热启动策略。如果为True,则在调用 fit() 方法时,会从先前的拟合结果继续训练。
-
ccp_alpha: (default=0.0) 防止过度剪枝的复杂性参数。在每个节点的成本复杂性修剪(Cost-Complexity Pruning)中使用。
-
max_samples: (default=None) 每棵树的最大样本数。如果设置为整数,则使用每个子样本集合的样本数。
3.3 追寻最优参数
grid_search = GridSearchCV(svm_model, param_grid, cv=kf, scoring='neg_mean_squared_error', n_jobs=1)
grid_search.fit(X, y)
GridSearchCV 函数是 scikit-learn(sklearn)库中的一个模型调优工具。
GridSearchCV
是用于系统地遍历多种参数组合,通过交叉验证来确定最佳参数的工具。下面详细解释一下 GridSearchCV
函数的各个参数和功能:
参数解释:
-
estimator:即要使用的模型,可以是任何实现了
fit
和predict
方法的对象。通常是一个分类器或回归器。在你的例子中,就是svm_model
,一个支持向量机模型的实例。 -
param_grid:一个字典或列表,用于指定要搜索的参数及其可能的取值范围。字典的键是参数名称,值是参数的可能取值列表。例如,
{'C': [0.1, 1, 10], 'kernel': ['rbf', 'linear']}
表示要搜索C
和kernel
两个参数,它们的取值分别为[0.1, 1, 10]
和['rbf', 'linear']
。 -
scoring:评分指标,用于评估模型的性能。可以是字符串(预定义的评分指标名称,比如
'accuracy'
、'precision'
、'recall'
等),或是可调用对象(自定义的评分函数)。在你的例子中,是'neg_mean_squared_error'
,即负均方误差。 -
cv:交叉验证生成器或可迭代的次数。如果是整数,则表示 K 折交叉验证。如果是交叉验证生成器(比如
KFold
对象),则用于指定交叉验证的策略。在你的例子中,是kf
,一个 KFold 对象。 -
n_jobs:并行作业数量,用于加速参数搜索。如果是 -1,则使用所有可用的 CPU 核心进行计算。在你的例子中,是 1,表示仅使用一个 CPU 核心进行计算。
其他重要属性和方法:
-
best_params_:返回一个字典,包含使模型性能最佳的参数组合。
-
best_estimator_:返回使用最佳参数组合训练的最佳模型对象。
-
cv_results_:返回一个字典,包含交叉验证的详细结果,包括每个参数组合的评分、拟合时间等信息。
-
fit(X, y):执行参数搜索和交叉验证的过程。
-
predict(X):使用最佳模型对新数据进行预测。
参数里的解释:
scoring=‘neg_mean_squared_error’ 设置了评分指标为负均方误差,即模型预测值与真实值之间的均方误差的相反数。这里采用了负数是因为 GridSearchCV 会尝试最大化评分指标,而我们通常希望均方误差越小越好,所以采用了相反数。
功能解释:
GridSearchCV
遍历参数字典中指定的所有参数组合,并针对每个组合执行交叉验证。对于每个参数组合,它在指定的交叉验证集上拟合模型,并在验证集上计算所选的评分指标。然后,它选择具有最佳评分的参数组合,并使用这些参数在整个训练集上拟合最终模型。
总之,GridSearchCV
是一个功能强大的工具,可以帮助你系统地寻找模型的最佳参数组合,从而提高模型的性能。
此时就可以输出一下最优参数了
# 输出最优参数和对应的评价指标
print("最优参数:", grid_search.best_params_)
print("最优评价指标(均方根误差):", abs(grid_search.best_score_) ** 0.5)
4交叉预测-以SVM模型为例
源代码
kf = KFold(n_splits=5, shuffle=True, random_state=42)
def rolling_predict(model, X, y, cv):
y_true = []
y_pred = []
for train_index, test_index in cv.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred.extend(model.predict(X_test))
y_true.extend(y_test)
return y_true, y_pred
best_model = grid_search.best_estimator_
y_true, y_pred = rolling_predict(best_model, X, y, kf)
# 计算评价指标
mse = mean_squared_error(y_true, y_pred)
rmse_value = rmse(y_true, y_pred)
mae_value = mae(y_true, y_pred)
print("参数优化后的MSE:", mse)
print("参数优化后的RMSE:", rmse_value)
print("参数优化后的MAE:", mae_value)
4.1第二段的cv.split(X):
cv.split(X) 返回的是一个生成器,该生成器会产生一系列元组 (train_index, test_index),其中 train_index 是训练集的索引数组,test_index 是测试集的索引数组。在循环中,每次迭代都会返回一对这样的索引数组,然后可以使用这些索引数组来从数据集 X 中提取对应的训练集和测试集。
因此,循环 for train_index, test_index in cv.split(X): 允许你在每次迭代中获得一个新的训练集和测试集的索引数组,然后你可以使用这些索引数组来提取相应的数据子集,并在模型上进行训练和评估。
4.2 第二段的iloc:
X.iloc[1] # 选择第2行的所有列数据
X.iloc[:, 1] # 选择所有行的第2列数据