基于多数据科学模型预测最安全股票投资板块的实现与评估
问题梳理
基于包含股票板块(Misc.、Tech、Real Estate等)的DataFrame,以标准差/波动率为核心连续变量,构建并评估6类模型(线性回归、随机森林、K-Nearest Neighbors、支持向量机、RNN、LSTM),用于预测波动率最低的「最安全」股票投资板块。
修正核心数据处理逻辑
你现有代码用「平均日涨跌幅最低」定义「最安全」,这和需求中「以标准差/波动率为核心变量」不符。真正的「安全」应对应波动率最低(日涨跌幅的标准差越小,板块波动越稳定),先修正数据处理流程:
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score from sklearn.preprocessing import StandardScaler # 加载数据集 combined_df = pd.read_csv('/filepath...') # 计算单只股票日涨跌幅 combined_df['Daily_pct_change'] = combined_df.groupby(['Sector', 'Symbol'])['Close'].pct_change() # 剔除首日无涨跌幅的NaN值 combined_df = combined_df.dropna(subset=['Daily_pct_change']) # 计算板块波动率(日涨跌幅的标准差)—— 核心安全指标 sector_volatility = combined_df.groupby('Sector')['Daily_pct_change'].std() # 确定波动率最低的最安全板块 safest_sector = sector_volatility.idxmin() # 构建标签:属于最安全板块标记为1,其他为0 y = combined_df['Sector'].apply(lambda x: 1 if x == safest_sector else 0) # 构建特征:加入单只股票的20日滚动波动率(可根据需求调整窗口) combined_df['Stock_volatility'] = combined_df.groupby(['Sector', 'Symbol'])['Daily_pct_change'].rolling(20).std().reset_index(0, drop=True) combined_df = combined_df.dropna(subset=['Stock_volatility']) # 选择特征列(示例保留收盘价、成交量、滚动波动率,可根据数据补充其他特征) X = combined_df[['Close', 'Volume', 'Stock_volatility']] # 特征缩放(对KNN、SVM、线性模型至关重要) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 分层划分训练/测试集(避免样本分布失衡) X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42, stratify=y)
各模型的构建与评估
1. 线性回归(Linear Regression)
线性回归本质是回归模型,用于二分类需手动设定阈值,更推荐用逻辑回归,但按需求实现:
from sklearn.linear_model import LinearRegression lr_model = LinearRegression() lr_model.fit(X_train, y_train) # 评估指标 train_r2 = lr_model.score(X_train, y_train) test_r2 = lr_model.score(X_test, y_test) y_pred_lr = lr_model.predict(X_test) y_pred_lr_bin = [1 if pred >= 0.5 else 0 for pred in y_pred_lr] print("=== 线性回归评估 ===") print(f"训练集R²: {train_r2:.3f}") print(f"测试集R²: {test_r2:.3f}") print(f"准确率: {accuracy_score(y_test, y_pred_lr_bin):.3f}") print(f"精确率: {precision_score(y_test, y_pred_lr_bin):.3f}") print(f"召回率: {recall_score(y_test, y_pred_lr_bin):.3f}") print(f"F1分数: {f1_score(y_test, y_pred_lr_bin):.3f}") print(f"AUC值: {roc_auc_score(y_test, y_pred_lr):.3f}")
2. 随机森林(Random Forest)
树模型无需特征缩放,自带特征重要性分析,适合分类任务:
from sklearn.ensemble import RandomForestClassifier rf_model = RandomForestClassifier(n_estimators=100, random_state=42) rf_model.fit(X_train, y_train) y_pred_rf = rf_model.predict(X_test) y_pred_rf_proba = rf_model.predict_proba(X_test)[:, 1] print("\n=== 随机森林评估 ===") print(f"准确率: {accuracy_score(y_test, y_pred_rf):.3f}") print(f"精确率: {precision_score(y_test, y_pred_rf):.3f}") print(f"召回率: {recall_score(y_test, y_pred_rf):.3f}") print(f"F1分数: {f1_score(y_test, y_pred_rf):.3f}") print(f"AUC值: {roc_auc_score(y_test, y_pred_rf_proba):.3f}") print("特征重要性: ", rf_model.feature_importances_)
3. K近邻(K-Nearest Neighbors)
对特征缩放高度敏感,必须使用标准化后的数据:
from sklearn.neighbors import KNeighborsClassifier # 示例用k=5,可通过网格搜索选择最优k值 knn_model = KNeighborsClassifier(n_neighbors=5) knn_model.fit(X_train, y_train) y_pred_knn = knn_model.predict(X_test) y_pred_knn_proba = knn_model.predict_proba(X_test)[:, 1] print("\n=== K近邻评估 ===") print(f"准确率: {accuracy_score(y_test, y_pred_knn):.3f}") print(f"精确率: {precision_score(y_test, y_pred_knn):.3f}") print(f"召回率: {recall_score(y_test, y_pred_knn):.3f}") print(f"F1分数: {f1_score(y_test, y_pred_knn):.3f}") print(f"AUC值: {roc_auc_score(y_test, y_pred_knn_proba):.3f}")
4. 支持向量机(Support Vector Machine)
适合高维数据,同样依赖特征缩放:
from sklearn.svm import SVC svm_model = SVC(probability=True, random_state=42) svm_model.fit(X_train, y_train) y_pred_svm = svm_model.predict(X_test) y_pred_svm_proba = svm_model.predict_proba(X_test)[:, 1] print("\n=== 支持向量机评估 ===") print(f"准确率: {accuracy_score(y_test, y_pred_svm):.3f}") print(f"精确率: {precision_score(y_test, y_pred_svm):.3f}") print(f"召回率: {recall_score(y_test, y_pred_svm):.3f}") print(f"F1分数: {f1_score(y_test, y_pred_svm):.3f}") print(f"AUC值: {roc_auc_score(y_test, y_pred_svm_proba):.3f}")
5. RNN模型
适合时序数据,需将数据转换为「过去N天特征→当天标签」的序列格式:
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import SimpleRNN, Dense # 构建时序数据函数 def create_sequences(X, y, time_steps=20): X_seq, y_seq = [], [] for i in range(len(X) - time_steps): X_seq.append(X[i:i+time_steps]) y_seq.append(y.iloc[i+time_steps]) return np.array(X_seq), np.array(y_seq) # 生成时序输入(用过去20天特征预测第21天标签) time_steps = 20 X_train_seq, y_train_seq = create_sequences(X_train, y_train.reset_index(drop=True), time_steps) X_test_seq, y_test_seq = create_sequences(X_test, y_test.reset_index(drop=True), time_steps) # 构建RNN模型 rnn_model = Sequential([ SimpleRNN(32, input_shape=(time_steps, X_train.shape[1])), Dense(1, activation='sigmoid') ]) rnn_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) history = rnn_model.fit(X_train_seq, y_train_seq, epochs=10, batch_size=32, validation_split=0.1, verbose=1) # 评估 loss, accuracy = rnn_model.evaluate(X_test_seq, y_test_seq, verbose=0) y_pred_rnn_proba = rnn_model.predict(X_test_seq, verbose=0) y_pred_rnn_bin = (y_pred_rnn_proba >= 0.5).astype(int).flatten() print("\n=== RNN评估 ===") print(f"测试集损失: {loss:.3f}") print(f"准确率: {accuracy:.3f}") print(f"精确率: {precision_score(y_test_seq, y_pred_rnn_bin):.3f}") print(f"召回率: {recall_score(y_test_seq, y_pred_rnn_bin):.3f}") print(f"F1分数: {f1_score(y_test_seq, y_pred_rnn_bin):.3f}") print(f"AUC值: {roc_auc_score(y_test_seq, y_pred_rnn_proba):.3f}")
6. LSTM模型
改进型RNN,解决长时序梯度消失问题,适合挖掘长期依赖:
from tensorflow.keras.layers import LSTM # 构建LSTM模型 lstm_model = Sequential([ LSTM(64, input_shape=(time_steps, X_train.shape[1])), Dense(32, activation='relu'), Dense(1, activation='sigmoid') ]) lstm_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) history_lstm = lstm_model.fit(X_train_seq, y_train_seq, epochs=15, batch_size=32, validation_split=0.1, verbose=1) # 评估 loss_lstm, accuracy_lstm = lstm_model.evaluate(X_test_seq, y_test_seq, verbose=0) y_pred_lstm_proba = lstm_model.predict(X_test_seq, verbose=0) y_pred_lstm_bin = (y_pred_lstm_proba >= 0.5).astype(int).flatten() print("\n=== LSTM评估 ===") print(f"测试集损失: {loss_lstm:.3f}") print(f"准确率: {accuracy_lstm:.3f}") print(f"精确率: {precision_score(y_test_seq, y_pred_lstm_bin):.3f}") print(f"召回率: {recall_score(y_test_seq, y_pred_lstm_bin):.3f}") print(f"F1分数: {f1_score(y_test_seq, y_pred_lstm_bin):.3f}") print(f"AUC值: {roc_auc_score(y_test_seq, y_pred_lstm_proba):.3f}")
模型对比建议
- 传统机器学习模型(线性回归、随机森林、KNN、SVM)训练快、解释性强,适合快速验证思路;其中随机森林的特征重要性可帮你定位核心影响因子。
- 深度学习模型(RNN、LSTM)适合挖掘时序数据中的长期依赖,但需要更多数据、更长训练时间,且解释性弱。
- 评估时不要仅看准确率:若最安全板块样本占比低,准确率会有误导性,需重点关注精确率、召回率、F1分数、AUC值。
内容的提问来源于stack exchange,提问作者Jason Bradley
相关产品推荐
相关产品推荐

