深度学习基础:神经网络
wabicai
# 深度学习基础:神经网络
# 学习目标
通过本章,你将掌握:
- 神经网络的基本原理
- 前向传播和反向传播
- PyTorch/TensorFlow框架使用
- 在量化交易中应用深度学习
# 什么是深度学习
**深度学习(Deep Learning)**是机器学习的一个分支,使用多层神经网络来学习数据的层次化表示。
# 为什么叫"深度"?
传统机器学习:
输入 → 特征工程(人工) → 简单模型 → 输出
深度学习:
输入 → 多层神经网络(自动学习特征) → 输出
└─ 第1层:低级特征(边缘、颜色)
└─ 第2层:中级特征(形状、纹理)
└─ 第3层:高级特征(对象、概念)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 神经网络基础
# 1. 神经元
# 单个神经元
y = activation(w1*x1 + w2*x2 + ... + wn*xn + b)
# 组成部分:
# - 输入:x1, x2, ..., xn
# - 权重:w1, w2, ..., wn
# - 偏置:b
# - 激活函数:activation
# - 输出:y
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2. 激活函数
import torch
import torch.nn as nn
# Sigmoid:输出0-1
sigmoid = nn.Sigmoid()
# Tanh:输出-1到1
tanh = nn.Tanh()
# ReLU:最常用,输出max(0, x)
relu = nn.ReLU()
# Leaky ReLU:解决ReLU死亡问题
leaky_relu = nn.LeakyReLU(0.01)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# PyTorch快速入门
"""
PyTorch基础:构建第一个神经网络
"""
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
# 1. 定义模型
class SimpleNN(nn.Module):
"""简单的前馈神经网络"""
def __init__(self, input_size, hidden_size, output_size):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, hidden_size)
self.fc3 = nn.Linear(hidden_size, output_size)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
"""前向传播"""
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
x = self.sigmoid(x)
return x
# 2. 准备数据
# 假设我们有10个特征
X = torch.randn(1000, 10) # 1000个样本,10个特征
y = (X.sum(dim=1) > 0).float().unsqueeze(1) # 二分类标签
# 3. 创建模型
model = SimpleNN(input_size=10, hidden_size=64, output_size=1)
# 4. 定义损失函数和优化器
criterion = nn.BCELoss() # 二分类交叉熵
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 5. 训练模型
num_epochs = 100
batch_size = 32
for epoch in range(num_epochs):
# 前向传播
outputs = model(X)
loss = criterion(outputs, y)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 6. 预测
model.eval()
with torch.no_grad():
test_data = torch.randn(10, 10)
predictions = model(test_data)
print(f'\n预测结果: {predictions.squeeze()}')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 实战:股票价格预测
"""
使用神经网络预测股票价格
"""
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import yfinance as yf
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
class StockPricePredictor(nn.Module):
"""股票价格预测模型"""
def __init__(self, input_size, hidden_sizes=[128, 64, 32]):
super(StockPricePredictor, self).__init__()
layers = []
prev_size = input_size
# 构建隐藏层
for hidden_size in hidden_sizes:
layers.append(nn.Linear(prev_size, hidden_size))
layers.append(nn.ReLU())
layers.append(nn.Dropout(0.2)) # 防止过拟合
prev_size = hidden_size
# 输出层
layers.append(nn.Linear(prev_size, 1))
self.network = nn.Sequential(*layers)
def forward(self, x):
return self.network(x)
class DeepLearningTrader:
"""深度学习交易系统"""
def __init__(self, symbol, lookback=20):
self.symbol = symbol
self.lookback = lookback
self.model = None
self.scaler = StandardScaler()
self.data = None
def prepare_data(self, start_date, end_date):
"""准备数据"""
# 下载数据
df = yf.download(self.symbol, start=start_date, end=end_date)
# 创建特征
df['return'] = df['Close'].pct_change()
for window in [5, 10, 20]:
df[f'ma{window}'] = df['Close'].rolling(window).mean()
df[f'std{window}'] = df['Close'].rolling(window).std()
df = df.dropna()
# 创建时间序列数据
X, y = [], []
for i in range(self.lookback, len(df)):
# 特征:过去lookback天的价格和指标
features = df.iloc[i-self.lookback:i][[
'Close', 'return', 'ma5', 'ma10', 'ma20', 'std5', 'std10', 'std20'
]].values.flatten()
X.append(features)
# 标签:下一天的收盘价
y.append(df.iloc[i]['Close'])
X = np.array(X)
y = np.array(y).reshape(-1, 1)
# 标准化
X_scaled = self.scaler.fit_transform(X)
# 划分训练集和测试集
split = int(len(X) * 0.8)
X_train = torch.FloatTensor(X_scaled[:split])
y_train = torch.FloatTensor(y[:split])
X_test = torch.FloatTensor(X_scaled[split:])
y_test = torch.FloatTensor(y[split:])
self.data = {
'X_train': X_train,
'y_train': y_train,
'X_test': X_test,
'y_test': y_test,
'dates': df.index[self.lookback:]
}
return self
def train(self, epochs=100, lr=0.001):
"""训练模型"""
input_size = self.data['X_train'].shape[1]
self.model = StockPricePredictor(input_size)
criterion = nn.MSELoss()
optimizer = optim.Adam(self.model.parameters(), lr=lr)
train_losses = []
test_losses = []
for epoch in range(epochs):
# 训练模式
self.model.train()
optimizer.zero_grad()
# 前向传播
outputs = self.model(self.data['X_train'])
loss = criterion(outputs, self.data['y_train'])
# 反向传播
loss.backward()
optimizer.step()
# 评估
self.model.eval()
with torch.no_grad():
test_outputs = self.model(self.data['X_test'])
test_loss = criterion(test_outputs, self.data['y_test'])
train_losses.append(loss.item())
test_losses.append(test_loss.item())
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], '
f'Train Loss: {loss.item():.4f}, '
f'Test Loss: {test_loss.item():.4f}')
# 绘制学习曲线
plt.figure(figsize=(10, 6))
plt.plot(train_losses, label='训练损失')
plt.plot(test_losses, label='测试损失')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.title('学习曲线')
plt.savefig('learning_curve.png', dpi=300)
plt.show()
return self
def evaluate(self):
"""评估模型"""
self.model.eval()
with torch.no_grad():
predictions = self.model(self.data['X_test'])
# 转为numpy
y_true = self.data['y_test'].numpy()
y_pred = predictions.numpy()
# 计算误差
mse = np.mean((y_true - y_pred) ** 2)
rmse = np.sqrt(mse)
mae = np.mean(np.abs(y_true - y_pred))
print(f'\n模型评估:')
print(f' MSE: {mse:.4f}')
print(f' RMSE: {rmse:.4f}')
print(f' MAE: {mae:.4f}')
# 绘制预测结果
split = int(len(self.data['dates']) * 0.8)
test_dates = self.data['dates'][split:]
plt.figure(figsize=(12, 6))
plt.plot(test_dates, y_true, label='真实价格', linewidth=2)
plt.plot(test_dates, y_pred, label='预测价格', linewidth=2, alpha=0.7)
plt.xlabel('日期')
plt.ylabel('价格')
plt.title(f'{self.symbol} 价格预测')
plt.legend()
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('predictions.png', dpi=300)
plt.show()
return {'mse': mse, 'rmse': rmse, 'mae': mae}
# 使用示例
trader = DeepLearningTrader('AAPL', lookback=20)
trader.prepare_data('2020-01-01', '2023-12-31') \
.train(epochs=100, lr=0.001) \
.evaluate()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# 关键概念
# 1. 前向传播 (Forward Propagation)
输入层 → 隐藏层1 → 隐藏层2 → ... → 输出层
每一层:
output = activation(weights @ input + bias)
1
2
3
4
2
3
4
# 2. 反向传播 (Backpropagation)
1. 计算损失
2. 计算损失对输出层的梯度
3. 逐层向后传播梯度
4. 更新每层的权重
1
2
3
4
2
3
4
# 3. 优化器
# SGD:随机梯度下降
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# Adam:自适应学习率(最常用)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# RMSprop
optimizer = optim.RMSprop(model.parameters(), lr=0.001)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 常见问题
# Q1: 如何选择网络结构?
经验法则:
- 输入层:特征数量
- 隐藏层:2-3层通常足够
- 隐藏层神经元:输入层的2-10倍
- 输出层:1(回归)或类别数(分类)
实践: 从简单开始,逐步增加复杂度
# Q2: 如何防止过拟合?
方法:
- Dropout
- L1/L2正则化
- Early Stopping
- 数据增强
- 简化网络
# Q3: 学习率如何设置?
建议:
- 初始:0.001(Adam)或0.01(SGD)
- 使用学习率衰减
- 学习率过大:损失震荡
- 学习率过小:收敛慢
# 进阶资源
# 推荐课程
- fast.ai深度学习 - 实战导向
- 吴恩达深度学习 - Coursera
- PyTorch官方教程
# 推荐书籍
- 《深度学习》 - Ian Goodfellow
- 《动手学深度学习》 - 李沐
- 《深度学习入门》 - 斋藤康毅
# 下一步
深入学习
实战练习
- 优化网络结构
- 尝试不同激活函数
- 对比传统ML和DL效果
深度学习是强大的工具,但要记住:数据质量>模型复杂度!
上一篇:机器学习快速入门 | 下一篇:LSTM与时间序列预测