TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
adaline_learning.cpp
Go to the documentation of this file.
1
28
29
#include <array>
30
#include <cassert>
31
#include <climits>
32
#include <cmath>
33
#include <cstdlib>
34
#include <ctime>
35
#include <iostream>
36
#include <numeric>
37
#include <vector>
38
40
constexpr
int
MAX_ITER
= 500;
// INT_MAX
41
45
namespace
machine_learning
{
46
class
adaline
{
47
public
:
55
explicit
adaline
(
int
num_features,
const
double
eta
= 0.01f,
56
const
double
accuracy
= 1e-5)
57
:
eta
(
eta
),
accuracy
(
accuracy
) {
58
if
(
eta
<= 0) {
59
std::cerr <<
"learning rate should be positive and nonzero"
60
<< std::endl;
61
std::exit(EXIT_FAILURE);
62
}
63
64
weights
= std::vector<double>(
65
num_features +
66
1);
// additional weight is for the constant bias term
67
68
// initialize with random weights in the range [-50, 49]
69
for
(
double
&weight :
weights
) weight = 1.f;
70
// weights[i] = (static_cast<double>(std::rand() % 100) - 50);
71
}
72
76
friend
std::ostream &
operator<<
(std::ostream &out,
const
adaline
&ada) {
77
out <<
"<"
;
78
for
(
int
i = 0; i < ada.
weights
.size(); i++) {
79
out << ada.
weights
[i];
80
if
(i < ada.
weights
.size() - 1) {
81
out <<
", "
;
82
}
83
}
84
out <<
">"
;
85
return
out;
86
}
87
95
int
predict
(
const
std::vector<double> &x,
double
*out =
nullptr
) {
96
if
(!
check_size_match
(x)) {
97
return
0;
98
}
99
100
double
y =
weights
.back();
// assign bias value
101
102
// for (int i = 0; i < x.size(); i++) y += x[i] * weights[i];
103
y = std::inner_product(x.begin(), x.end(),
weights
.begin(), y);
104
105
if
(out !=
nullptr
) {
// if out variable is provided
106
*out = y;
107
}
108
109
return
activation
(y);
// quantizer: apply ADALINE threshold function
110
}
111
119
double
fit
(
const
std::vector<double> &x,
const
int
&y) {
120
if
(!
check_size_match
(x)) {
121
return
0;
122
}
123
124
/* output of the model with current weights */
125
int
p =
predict
(x);
126
int
prediction_error = y - p;
// error in estimation
127
double
correction_factor =
eta
* prediction_error;
128
129
/* update each weight, the last weight is the bias term */
130
for
(
int
i = 0; i < x.size(); i++) {
131
weights
[i] += correction_factor * x[i];
132
}
133
weights
[x.size()] += correction_factor;
// update bias
134
135
return
correction_factor;
136
}
137
144
template
<
size_t
N>
145
void
fit
(std::array<std::vector<double>, N>
const
&X,
146
std::array<int, N>
const
&Y) {
147
double
avg_pred_error = 1.f;
148
149
int
iter = 0;
150
for
(iter = 0; (iter <
MAX_ITER
) && (avg_pred_error >
accuracy
);
151
iter++) {
152
avg_pred_error = 0.f;
153
154
// perform fit for each sample
155
for
(
int
i = 0; i < N; i++) {
156
double
err =
fit
(X[i], Y[i]);
157
avg_pred_error += std::abs(err);
158
}
159
avg_pred_error /= N;
160
161
// Print updates every 200th iteration
162
// if (iter % 100 == 0)
163
std::cout <<
"\tIter "
<< iter <<
": Training weights: "
<< *
this
164
<<
"\tAvg error: "
<< avg_pred_error << std::endl;
165
}
166
167
if
(iter <
MAX_ITER
) {
168
std::cout <<
"Converged after "
<< iter <<
" iterations."
169
<< std::endl;
170
}
else
{
171
std::cout <<
"Did not converge after "
<< iter <<
" iterations."
172
<< std::endl;
173
}
174
}
175
186
int
activation
(
double
x) {
return
x > 0 ? 1 : -1; }
187
188
private
:
196
bool
check_size_match
(
const
std::vector<double> &x) {
197
if
(x.size() != (
weights
.size() - 1)) {
198
std::cerr << __func__ <<
": "
199
<<
"Number of features in x does not match the feature "
200
"dimension in model!"
201
<< std::endl;
202
return
false
;
203
}
204
return
true
;
205
}
206
207
const
double
eta
;
208
const
double
accuracy
;
209
std::vector<double>
weights
;
210
};
211
212
}
// namespace machine_learning
213
214
using
machine_learning::adaline
;
215
217
224
void
test1
(
double
eta = 0.01) {
225
adaline
ada(2, eta);
// 2 features
226
227
const
int
N = 10;
// number of sample points
228
229
std::array<std::vector<double>, N> X = {
230
std::vector<double>({0, 1}), std::vector<double>({1, -2}),
231
std::vector<double>({2, 3}), std::vector<double>({3, -1}),
232
std::vector<double>({4, 1}), std::vector<double>({6, -5}),
233
std::vector<double>({-7, -3}), std::vector<double>({-8, 5}),
234
std::vector<double>({-9, 2}), std::vector<double>({-10, -15})};
235
std::array<int, N> y = {1, -1, 1, -1, -1,
236
-1, 1, 1, 1, -1};
// corresponding y-values
237
238
std::cout <<
"------- Test 1 -------"
<< std::endl;
239
std::cout <<
"Model before fit: "
<< ada << std::endl;
240
241
ada.
fit
<N>(X, y);
242
std::cout <<
"Model after fit: "
<< ada << std::endl;
243
244
int
predict = ada.
predict
({5, -3});
245
std::cout <<
"Predict for x=(5,-3): "
<< predict;
246
assert(predict == -1);
247
std::cout <<
" ...passed"
<< std::endl;
248
249
predict = ada.
predict
({5, 8});
250
std::cout <<
"Predict for x=(5,8): "
<< predict;
251
assert(predict == 1);
252
std::cout <<
" ...passed"
<< std::endl;
253
}
254
262
void
test2
(
double
eta = 0.01) {
263
adaline
ada(2, eta);
// 2 features
264
265
const
int
N = 50;
// number of sample points
266
267
std::array<std::vector<double>, N> X;
268
std::array<int, N> Y{};
// corresponding y-values
269
270
// generate sample points in the interval
271
// [-range2/100 , (range2-1)/100]
272
int
range = 500;
// sample points full-range
273
int
range2 = range >> 1;
// sample points half-range
274
for
(
int
i = 0; i < N; i++) {
275
double
x0 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
276
double
x1 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
277
X[i] = std::vector<double>({x0, x1});
278
Y[i] = (x0 + 3. * x1) > -1 ? 1 : -1;
279
}
280
281
std::cout <<
"------- Test 2 -------"
<< std::endl;
282
std::cout <<
"Model before fit: "
<< ada << std::endl;
283
284
ada.
fit
(X, Y);
285
std::cout <<
"Model after fit: "
<< ada << std::endl;
286
287
int
N_test_cases = 5;
288
for
(
int
i = 0; i < N_test_cases; i++) {
289
double
x0 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
290
double
x1 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
291
292
int
predict = ada.
predict
({x0, x1});
293
294
std::cout <<
"Predict for x=("
<< x0 <<
","
<< x1 <<
"): "
<< predict;
295
296
int
expected_val = (x0 + 3. * x1) > -1 ? 1 : -1;
297
assert(predict == expected_val);
298
std::cout <<
" ...passed"
<< std::endl;
299
}
300
}
301
313
void
test3
(
double
eta = 0.01) {
314
adaline
ada(6, eta);
// 2 features
315
316
const
int
N = 100;
// number of sample points
317
318
std::array<std::vector<double>, N> X;
319
std::array<int, N> Y{};
// corresponding y-values
320
321
// generate sample points in the interval
322
// [-range2/100 , (range2-1)/100]
323
int
range = 200;
// sample points full-range
324
int
range2 = range >> 1;
// sample points half-range
325
for
(
int
i = 0; i < N; i++) {
326
double
x0 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
327
double
x1 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
328
double
x2 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
329
X[i] = std::vector<double>({x0, x1, x2, x0 * x0, x1 * x1, x2 * x2});
330
Y[i] = ((x0 * x0) + (x1 * x1) + (x2 * x2)) <= 1.f ? 1 : -1;
331
}
332
333
std::cout <<
"------- Test 3 -------"
<< std::endl;
334
std::cout <<
"Model before fit: "
<< ada << std::endl;
335
336
ada.
fit
(X, Y);
337
std::cout <<
"Model after fit: "
<< ada << std::endl;
338
339
int
N_test_cases = 5;
340
for
(
int
i = 0; i < N_test_cases; i++) {
341
double
x0 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
342
double
x1 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
343
double
x2 = (
static_cast<
double
>
(std::rand() % range) - range2) / 100.f;
344
345
int
predict = ada.
predict
({x0, x1, x2, x0 * x0, x1 * x1, x2 * x2});
346
347
std::cout <<
"Predict for x=("
<< x0 <<
","
<< x1 <<
","
<< x2
348
<<
"): "
<< predict;
349
350
int
expected_val = ((x0 * x0) + (x1 * x1) + (x2 * x2)) <= 1.f ? 1 : -1;
351
assert(predict == expected_val);
352
std::cout <<
" ...passed"
<< std::endl;
353
}
354
}
355
357
int
main
(
int
argc,
char
**argv) {
358
std::srand(std::time(
nullptr
));
// initialize random number generator
359
360
double
eta = 0.1;
// default value of eta
361
if
(argc == 2) {
// read eta value from commandline argument if present
362
eta = strtof(argv[1],
nullptr
);
363
}
364
365
test1
(eta);
366
367
std::cout <<
"Press ENTER to continue..."
<< std::endl;
368
std::cin.get();
369
370
test2
(eta);
371
372
std::cout <<
"Press ENTER to continue..."
<< std::endl;
373
std::cin.get();
374
375
test3
(eta);
376
377
return
0;
378
}
test3
void test3(double eta=0.01)
Definition
adaline_learning.cpp:313
adaline::adaline
adaline(int num_features, const double eta=0.01f, const double accuracy=1e-5)
Definition
adaline_learning.cpp:55
machine_learning::adaline
Definition
adaline_learning.cpp:46
machine_learning::adaline::activation
int activation(double x)
Definition
adaline_learning.cpp:186
machine_learning::adaline::adaline
adaline(int num_features, const double eta=0.01f, const double accuracy=1e-5)
Definition
adaline_learning.cpp:55
machine_learning::adaline::eta
const double eta
learning rate of the algorithm
Definition
adaline_learning.cpp:207
machine_learning::adaline::weights
std::vector< double > weights
weights of the neural network
Definition
adaline_learning.cpp:209
machine_learning::adaline::fit
double fit(const std::vector< double > &x, const int &y)
Definition
adaline_learning.cpp:119
machine_learning::adaline::fit
void fit(std::array< std::vector< double >, N > const &X, std::array< int, N > const &Y)
Definition
adaline_learning.cpp:145
machine_learning::adaline::accuracy
const double accuracy
model fit convergence accuracy
Definition
adaline_learning.cpp:208
machine_learning::adaline::predict
int predict(const std::vector< double > &x, double *out=nullptr)
Definition
adaline_learning.cpp:95
machine_learning::adaline::check_size_match
bool check_size_match(const std::vector< double > &x)
Definition
adaline_learning.cpp:196
machine_learning::adaline::operator<<
friend std::ostream & operator<<(std::ostream &out, const adaline &ada)
Definition
adaline_learning.cpp:76
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
MAX_ITER
constexpr int MAX_ITER
Definition
adaline_learning.cpp:40
test2
void test2(const std::string &text)
Self test 2 - using 8x8 randomly generated key.
Definition
hill_cipher.cpp:505
test1
void test1(const std::string &text)
Self test 1 - using 3x3 randomly generated key.
Definition
hill_cipher.cpp:470
machine_learning
A* search algorithm
machine_learning
adaline_learning.cpp
Generated by
1.18.0