Skip to content

Commit 3309ba5

Browse files
authored
feat: menambahkan adaline learning (#115)
Signed-off-by: slowy07 <[email protected]>
1 parent 36a5c2c commit 3309ba5

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
file(GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
2+
foreach(testsourcefile ${APP_SOURCES})
3+
string(REPLACE ".cpp" "" testname ${testsourcefile})
4+
add_executable(${testname} ${testsourcefile})
5+
set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX)
6+
if(OpenMP_CXX_FOUND)
7+
target_link_libraries(${testname} OpenMP::OpenMP_CXX)
8+
endif()
9+
install(TARGETS ${testname} DESTINATION "bin/artificial_intelligence")
10+
endforeach(testsourcefile ${APP_SOURCES})
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#include <array>
2+
#include <cassert>
3+
#include <cstdlib>
4+
#include <ctime>
5+
#include <iostream>
6+
#include <numeric>
7+
#include <vector>
8+
constexpr int MAKS_ITERASI = 500;
9+
10+
/**
11+
* @namespace artificial_intelligence
12+
* @brief algoritma machine learning
13+
*/
14+
namespace artificial_intelligence {
15+
class adaline {
16+
public:
17+
/**
18+
* @brief konstruktor default
19+
* @param jumlah_fitur jumlah fitur yang ada
20+
* @param laju_pembelajaran nilai laju training
21+
* @param akurasi nilai akurasi konvergensi
22+
*/
23+
explicit adaline(int jumlah_fitur, const double laju_pembelajaran = 0.01f,
24+
const double akurasi = 1e-5)
25+
: laju_pembelajaran(laju_pembelajaran), akurasi(akurasi) {
26+
if (laju_pembelajaran <= 0) {
27+
std::cerr << "laju pembelajaran harus positif dan tidak nol" << std::endl;
28+
std::exit(EXIT_FAILURE);
29+
}
30+
31+
// inisialisasi bobot dengan nilai acak di range [-50, 49]
32+
bobot = std::vector<double>(jumlah_fitur + 1);
33+
// inisialisasi bobot awal dengan nilai 1
34+
for (double &bobot_satuan : bobot)
35+
bobot_satuan = 1.f;
36+
}
37+
38+
// buat operator untuk mencetak bobot model
39+
friend std::ostream &operator<<(std::ostream &keluar, const adaline &ada) {
40+
keluar << "<";
41+
for (int i = 0; i < ada.bobot.size(); i++) {
42+
keluar << ada.bobot[i];
43+
if (i < ada.bobot.size() - 1) {
44+
keluar << ", ";
45+
}
46+
}
47+
keluar << ">";
48+
return keluar;
49+
}
50+
51+
/**
52+
* @brief prediksi keluaran model untuk set fitur tertentu
53+
* @param x vektor input
54+
* @param out keluaran opsional, mengembalikan output neuron sebelum aktivasi
55+
* @return keluaran prediksi model
56+
*/
57+
int prediksi(const std::vector<double> &x, double *keluaran = nullptr) {
58+
if (!cek_kecocokan_ukuran(x)) {
59+
return 0;
60+
}
61+
// nilai bias
62+
double y = bobot.back();
63+
// hitung nilai y dari input dan bobot
64+
y = std::inner_product(x.begin(), x.end(), bobot.begin(), y);
65+
66+
if (keluaran != nullptr) {
67+
*keluaran = y;
68+
}
69+
return aktivasi(y);
70+
}
71+
72+
/**
73+
* @brief memperbarui bobot model denga menggunakan training untuk satu vektor
74+
* @param x vektor fitur
75+
* @param y nilai keluaran yang diketahui
76+
* @return faktor koreksi
77+
*/
78+
double pelatihan(const std::vector<double> &x, const int &y) {
79+
if (cek_kecocokan_ukuran(x)) {
80+
return 0;
81+
}
82+
83+
// output model dengan bobot saat ini
84+
int p = prediksi(x);
85+
int kesalahan_prediksi = y - p;
86+
double faktor_koreksi = laju_pembelajaran * kesalahan_prediksi;
87+
88+
for (int i = 0; i < x.size(); i++) {
89+
bobot[i] += faktor_koreksi * x[i];
90+
}
91+
bobot[x.size()] += faktor_koreksi;
92+
return faktor_koreksi;
93+
}
94+
95+
/**
96+
* @brief memperbarui bobot mdel menggunakan training untuk array vektor
97+
* @param x array vektor fitur
98+
* @param y nilai keluaran yang diketahui untuk setiap vektor fitur
99+
*/
100+
template <size_t N>
101+
void pelatihan(std::array<std::vector<double>, N> const &X,
102+
std::array<int, N> const &Y) {
103+
double rata_kesalahan_prediksi = 1.f;
104+
int iterasi = 0;
105+
106+
for (iterasi = 0;
107+
(iterasi < MAKS_ITERASI) && (rata_kesalahan_prediksi > akurasi);
108+
iterasi++) {
109+
rata_kesalahan_prediksi = 0.f;
110+
for (int i = 0; i < N; i++) {
111+
double err = pelatihan(X[i], Y[i]);
112+
rata_kesalahan_prediksi += std::abs(err);
113+
}
114+
rata_kesalahan_prediksi /= N;
115+
std::cout << "\tIterasi " << iterasi << ": Bobot training: " << *this
116+
<< "\tRata-rata error: " << rata_kesalahan_prediksi
117+
<< std::endl;
118+
}
119+
120+
if (iterasi < MAKS_ITERASI) {
121+
std::cout << "konvergen setelah " << iterasi << " iterasi" << std::endl;
122+
} else {
123+
std::cout << "tidak konvergen setelah " << iterasi << " iterasi"
124+
<< std::endl;
125+
}
126+
}
127+
128+
/**
129+
* @brief fungsi aktivasi sebagai fungsi heaviside
130+
* @param x nilai untuk diaktivasi
131+
* @return hasil aktivasi
132+
*/
133+
int aktivasi(double x) { return x > 0 ? 1 : -1; }
134+
135+
private:
136+
bool cek_kecocokan_ukuran(const std::vector<double> &x) {
137+
if (x.size() != (bobot.size() - 1)) {
138+
std::cerr
139+
<< __func__ << ": "
140+
<< "jumlah fitur dalam x tidak cocok dengan dimensi fitur model!";
141+
return false;
142+
}
143+
return true;
144+
}
145+
const double laju_pembelajaran;
146+
const double akurasi;
147+
std::vector<double> bobot;
148+
};
149+
} // namespace artificial_intelligence
150+
151+
using artificial_intelligence::adaline;
152+
153+
/**
154+
* @brief fungsi pengujian untuk memprediksi titik dalam sistem koordinat 2D
155+
* memisahkan di atas garis x=y sebagai +1 dan lainnya sebagai -1
156+
* @param laju_pembelajaran laju pembelajaran (default = 0.01)
157+
*/
158+
void pengujian1(double laju_pembelajaran = 0.01) {
159+
adaline ada(2, laju_pembelajaran);
160+
161+
// jumlah sample
162+
const int N = 10;
163+
164+
// data fitur dan label keluaran
165+
std::array<std::vector<double>, N> X = {
166+
std::vector<double>({0, 1}), std::vector<double>({1, -2}),
167+
std::vector<double>({2, 3}), std::vector<double>({3, -1}),
168+
std::vector<double>({4, 1}), std::vector<double>({6, -5}),
169+
std::vector<double>({-7, -3}), std::vector<double>({-8, 5}),
170+
std::vector<double>({-9, 2}), std::vector<double>({-10, -15})};
171+
172+
// label keluaran
173+
std::array<int, N> y = {1, -1, 1, -1, -1, -1, 1, 1, 1, -1};
174+
175+
std::cout << "pengujian pertama" << std::endl;
176+
std::cout << "model sebelum pelatihan: " << ada << std::endl;
177+
178+
ada.pelatihan<N>(X, y);
179+
std::cout << "model setelah pelatihan: " << ada << std::endl;
180+
181+
int prediksi = ada.prediksi({5, -3});
182+
std::cout << "prediksi untuk x=(5, 3): " << prediksi;
183+
assert(prediksi == -1);
184+
std::cout << "... berhasil !" << std::endl;
185+
186+
prediksi = ada.prediksi({5, 8});
187+
std::cout << "prediksi untuk x=(5, 8): " << prediksi;
188+
assert(prediksi == 1);
189+
std::cout << "... berhasil !" << std::endl;
190+
}
191+
192+
int main() {
193+
std::srand(std::time(nullptr));
194+
pengujian1();
195+
return 0;
196+
return 0;
197+
}

0 commit comments

Comments
 (0)