Học máy
Các phương pháp này được sử dụng trong học máy.
Hàm kích hoạt mạng nơ-ron xác định giá trị đầu ra của một nơ-ron dựa trên tổng trọng số của các đầu vào. Việc lựa chọn hàm kích hoạt có tác động lớn đến hiệu suất của mạng nơ-ron. Các phần khác nhau của mô hình (các lớp) có thể sử dụng các hàm kích hoạt khác nhau.
Ngoài tất cả các hàm kích hoạt đã biết, MQL5 còn cung cấp đạo hàm của chúng. Đạo hàm của hàm cho phép cập nhật hiệu quả các tham số mô hình dựa trên sai số nhận được trong quá trình học.
Mạng nơ-ron nhằm tìm một thuật toán giảm thiểu sai số trong quá trình học, và để làm điều này, hàm mất mát được sử dụng. Giá trị của hàm mất mát cho biết giá trị dự đoán bởi mô hình sai lệch bao nhiêu so với giá trị thực tế. Các hàm mất mát khác nhau được sử dụng tùy thuộc vào bài toán. Ví dụ, Sai số Bình phương Trung bình (MSE
) được dùng cho các bài toán hồi quy, và Entropy Chéo Nhị phân (BCE
) được dùng cho mục đích phân loại nhị phân.
Hàm | Tác dụng |
---|---|
Activation | Tính giá trị hàm kích hoạt và ghi chúng vào vector/ma trận được truyền vào |
Derivative | Tính giá trị đạo hàm của hàm kích hoạt và ghi chúng vào vector/ma trận được truyền vào |
Loss | Tính giá trị hàm mất mát và ghi chúng vào vector/ma trận được truyền vào |
LossGradient | Tính vector hoặc ma trận gradient của hàm mất mát |
RegressionMetric | Tính chỉ số hồi quy dưới dạng sai số lệch khỏi đường hồi quy được xây dựng trên mảng dữ liệu chỉ định |
ConfusionMatrix | Tính ma trận nhầm lẫn. Phương thức này được áp dụng cho vector các giá trị dự đoán |
ConfusionMatrixMultilabel | Tính ma trận nhầm lẫn cho mỗi nhãn. Phương thức này được áp dụng cho vector các giá trị dự đoán |
ClassificationMetric | Tính chỉ số phân loại để đánh giá chất lượng dữ liệu dự đoán so với dữ liệu thực tế. Phương thức này được áp dụng cho vector các giá trị dự đoán |
ClassificationScore | Tính chỉ số phân loại để đánh giá chất lượng dữ liệu dự đoán so với dữ liệu thực tế |
PrecisionRecall | Tính các giá trị để xây dựng đường cong precision-recall. Tương tự như ClassificationScore , phương thức này được áp dụng cho vector các giá trị thực tế |
ReceiverOperatingCharacteristic | Tính các giá trị để xây dựng đường cong Đặc tính Hoạt động Nhận (ROC). Tương tự như ClassificationScore , phương thức này được áp dụng cho vector các giá trị thực tế |
Ví dụ
Ví dụ này thể hiện việc huấn luyện một mô hình sử dụng các phép toán ma trận. Mô hình được huấn luyện cho hàm (a + b + c)^2 / (a^2 + b^2 + c^2)
. Chúng ta nhập ma trận dữ liệu ban đầu, trong đó a
, b
và c
được chứa trong các cột khác nhau. Kết quả của hàm được thu tại đầu ra của mô hình.
matrix weights1, weights2, weights3; // ma trận các trọng số
matrix output1, output2, result; // ma trận các đầu ra của lớp nơ-ron
input int layer1 = 200; // kích thước của lớp ẩn đầu tiên
input int layer2 = 200; // kích thước của lớp ẩn thứ hai
input int Epochs = 20000; // số lượng epoch huấn luyện
input double lr = 3e-6; // tốc độ học
input ENUM_ACTIVATION_FUNCTION ac_func = AF_SWISH; // hàm kích hoạt
//+------------------------------------------------------------------+
//| Hàm bắt đầu script |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int train = 1000; // kích thước mẫu huấn luyện
int test = 10; // kích thước mẫu kiểm tra
matrix m_data, m_target;
//--- tạo mẫu huấn luyện
if(!CreateData(m_data, m_target, train))
return;
//--- huấn luyện mô hình
if(!Train(m_data, m_target, Epochs))
return;
//--- tạo mẫu kiểm tra
if(!CreateData(m_data, m_target, test))
return;
//--- kiểm tra mô hình
Test(m_data, m_target);
}
//+------------------------------------------------------------------+
//| Phương thức tạo mẫu |
//+------------------------------------------------------------------+
bool CreateData(matrix &data, matrix &target, const int count)
{
//--- khởi tạo ma trận dữ liệu ban đầu và kết quả
if(!data.Init(count, 3) || !target.Init(count, 1))
return false;
//--- điền ma trận dữ liệu ban đầu với các giá trị ngẫu nhiên
data.Random(-10, 10);
//--- tính giá trị mục tiêu cho mẫu huấn luyện
vector X1 = MathPow(data.Col(0) + data.Col(1) + data.Col(1), 2);
vector X2 = MathPow(data.Col(0), 2) + MathPow(data.Col(1), 2) + MathPow(data.Col(2), 2);
if(!target.Col(X1 / X2, 0))
return false;
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
//| Phương thức huấn luyện mô hình |
//+------------------------------------------------------------------+
bool Train(matrix &data, matrix &target, const int epochs = 10000)
{
//--- tạo mô hình
if(!CreateNet())
return false;
//--- huấn luyện mô hình
for(int ep = 0; ep < epochs; ep++)
{
//--- truyền xuôi
if(!FeedForward(data))
return false;
PrintFormat("Epoch %d, loss %.5f", ep, result.Loss(target, LOSS_MSE));
//--- lan truyền ngược và cập nhật ma trận trọng số
if(!Backprop(data, target))
return false;
}
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
//| Phương thức tạo mạng |
//+------------------------------------------------------------------+
bool CreateNet()
{
//--- khởi tạo ma trận trọng số
if(!weights1.Init(4, layer1) || !weights2.Init(layer1 + 1, layer2) || !weights3.Init(layer2 + 1, 1))
return false;
//--- điền ma trận trọng số với các giá trị ngẫu nhiên
weights1.Random(-0.1, 0.1);
weights2.Random(-0.1, 0.1);
weights3.Random(-0.1, 0.1);
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
//| Phương thức truyền xuôi |
//+------------------------------------------------------------------+
bool FeedForward(matrix &data)
{
//--- kiểm tra kích thước dữ liệu ban đầu
if(data.Cols() != weights1.Rows() - 1)
return false;
//--- tính lớp nơ-ron đầu tiên
matrix temp = data;
if(!temp.Resize(temp.Rows(), weights1.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights1.Rows() - 1))
return false;
output1 = temp.MatMul(weights1);
//--- tính hàm kích hoạt
if(!output1.Activation(temp, ac_func))
return false;
//--- tính lớp nơ-ron thứ hai
if(!temp.Resize(temp.Rows(), weights2.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights2.Rows() - 1))
return false;
output2 = temp.MatMul(weights2);
//--- tính hàm kích hoạt
if(!output2.Activation(temp, ac_func))
return false;
//--- tính lớp nơ-ron thứ ba
if(!temp.Resize(temp.Rows(), weights3.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights3.Rows() - 1))
return false;
result = temp.MatMul(weights3);
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
//| Phương thức lan truyền ngược |
//+------------------------------------------------------------------+
bool Backprop(matrix &data, matrix &target)
{
//--- kiểm tra kích thước ma trận giá trị mục tiêu
if(target.Rows() != result.Rows() ||
target.Cols() != result.Cols())
return false;
//--- xác định độ lệch của giá trị tính toán so với mục tiêu
matrix loss = (target - result) * 2;
//--- lan truyền gradient về lớp trước
matrix gradient = loss.MatMul(weights3.Transpose());
//--- cập nhật ma trận trọng số của lớp cuối
matrix temp;
if(!output2.Activation(temp, ac_func))
return false;
if(!temp.Resize(temp.Rows(), weights3.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights3.Rows() - 1))
return false;
weights3 = weights3 + temp.Transpose().MatMul(loss) * lr;
//--- điều chỉnh gradient sai số bằng đạo hàm của hàm kích hoạt
if(!output2.Derivative(temp, ac_func))
return false;
if(!gradient.Resize(gradient.Rows(), gradient.Cols() - 1))
return false;
loss = gradient * temp;
//--- lan truyền gradient xuống lớp thấp hơn
gradient = loss.MatMul(weights2.Transpose());
//--- cập nhật ma trận trọng số của lớp ẩn thứ hai
if(!output1.Activation(temp, ac_func))
return false;
if(!temp.Resize(temp.Rows(), weights2.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights2.Rows() - 1))
return false;
weights2 = weights2 + temp.Transpose().MatMul(loss) * lr;
//--- điều chỉnh gradient sai số bằng đạo hàm của hàm kích hoạt
if(!output1.Derivative(temp, ac_func))
return false;
if(!gradient.Resize(gradient.Rows(), gradient.Cols() - 1))
return false;
loss = gradient * temp;
//--- cập nhật ma trận trọng số của lớp ẩn đầu tiên
temp = data;
if(!temp.Resize(temp.Rows(), weights1.Rows()) ||
!temp.Col(vector::Ones(temp.Rows()), weights1.Rows() - 1))
return false;
weights1 = weights1 + temp.Transpose().MatMul(loss) * lr;
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
//| Phương thức kiểm tra mô hình |
//+------------------------------------------------------------------+
bool Test(matrix &data, matrix &target)
{
//--- truyền xuôi trên dữ liệu kiểm tra
if(!FeedForward(data))
return false;
//--- ghi lại kết quả tính toán của mô hình và giá trị thực
PrintFormat("Test loss %.5f", result.Loss(target, LOSS_MSE));
ulong total = data.Rows();
for(ulong i = 0; i < total; i++)
PrintFormat("(%.2f + %.2f + %.2f)^2 / (%.2f^2 + %.2f^2 + %.2f^2) = Net %.2f, Target %.2f", data[i, 0], data[i, 1], data[i, 2],
data[i, 0], data[i, 1], data[i, 2], result[i, 0], target[i, 0]);
//--- trả về kết quả
return true;
}
//+------------------------------------------------------------------+
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