Skip to content

Commit 81967ed

Browse files
feat: menambahkan algoritma KNN
# Deskripsi (Description) menambahkan algoritma klassifikasi knn # Checklist: ##### Umum: - [x] Saya menambah algoritma terbaru. - [ ] Saya memperbaiki algoritma yang sudah ada. - [ ] Saya memperbaiki dokumentasi. - [ ] Saya menambah dokumentasi. ##### Contributor Requirements (Syarat Kontributor) dan Lain-Lain: - [x] Saya sudah membaca (I have read) [CONTRIBUTING](https://github.com/bellshade/CPP/blob/main/CONTRIBUTING.md) dan sudah menyetujui semua syarat. - [x] Saya telah menambahkan komentar kode yang memberikan penjelasan maksud dari kode yang saya buat. - [x] Saya menggunakan bahasa Indonesia untuk memberikan penjelasan dari kode yang saya buat. # Environment Saya menggunakan (I'm using): - ``OS`` = `Linux` - ``g++`` = 14.2.1 20240910 This Commit License https://github.com/bellshade/CPP/blob/main/license Co-authored-by: bellshadebot <bellshade07@gmail.com>
1 parent e1b298f commit 81967ed

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
2+
/**
3+
* @namespace artificial_intelligence
4+
* @brief algoritma knn
5+
*/
6+
#include <algorithm>
7+
#include <cassert>
8+
#include <cmath>
9+
#include <cstddef>
10+
#include <iostream>
11+
#include <iterator>
12+
#include <numeric>
13+
#include <unordered_map>
14+
#include <utility>
15+
#include <vector>
16+
namespace artificial_intelligence {
17+
/**
18+
* @brief fungsi k nearest neighbour
19+
*/
20+
namespace k_nearest_neighbour {
21+
/**
22+
* @brief menghitung jarak euclidean antara dua vektor
23+
* @param T tipe data vektor
24+
* @param a vektor pertama
25+
* @param b vektor kedua
26+
* @return double nilai jarak euclidean antara kedua vektor
27+
*/
28+
template <typename T>
29+
double jarak_euclidean(const std::vector<T> &a, const std::vector<T> &b) {
30+
std::vector<double> hasil_antara;
31+
std::transform(
32+
a.begin(), a.end(), b.begin(), std::back_inserter(hasil_antara),
33+
[](T elemen1, T elemen2) { return std::pow((elemen1 - elemen2), 2); });
34+
// kecilin ukuran dari vektor
35+
hasil_antara.shrink_to_fit();
36+
return std::sqrt(
37+
std::accumulate(hasil_antara.begin(), hasil_antara.end(), 0.0));
38+
}
39+
40+
/**
41+
* @brief class dari knn menggunakan jarak euclidean sebagai metriks dari jarak
42+
*/
43+
class knn {
44+
private:
45+
// vektor attribut
46+
std::vector<std::vector<double>> X_;
47+
std::vector<int> Y_;
48+
49+
public:
50+
/**
51+
* @brief buat jarak knn terdekat
52+
* @param X vektor attribut
53+
* @param Y vektor label
54+
*/
55+
explicit knn(std::vector<std::vector<double>> &X, std::vector<int> &Y)
56+
: X_(X), Y_(Y){};
57+
// copy konstruktor
58+
knn(const knn &model) = default;
59+
// copy assignment
60+
knn &operator=(const knn &model) = default;
61+
// pindah konstruktor
62+
knn(knn &&) = default;
63+
// pindah juga assigmentnya
64+
knn &operator=(knn &&) = default;
65+
// lalu buat destruktor
66+
~knn() = default;
67+
68+
/**
69+
* @brief klasifikasikan sampel
70+
* @param sampel sample yang ingin diklasifikasikan
71+
* @param k jumlah neighbour yang mau dilihat
72+
* @return int label dari neighbour yang paling sering muncul
73+
*/
74+
int prediksi(std::vector<double> &sampel, int k) {
75+
std::vector<int> neighbour;
76+
std::vector<std::pair<double, int>> jarak;
77+
78+
// hitung jarak euclidean antara sampel dan setiap data dalam
79+
// sebuah dataset
80+
for (std::size_t i = 0; i < this->X_.size(); ++i) {
81+
auto data_sekarang = this->X_.at(i);
82+
auto label = this->Y_.at(i);
83+
auto jarak_data = jarak_euclidean(data_sekarang, sampel);
84+
jarak.emplace_back(jarak_data, label);
85+
}
86+
87+
// urutkan jarak berdasarkan kedekatan
88+
std::sort(jarak.begin(), jarak.end());
89+
90+
// ambil label dari knn
91+
for (int i = 0; i < k; i++) {
92+
auto label = jarak.at(i).second;
93+
neighbour.push_back(label);
94+
}
95+
96+
// hitung frekuensi dari setiap label
97+
std::unordered_map<int, int> frekuensi;
98+
for (auto label : neighbour) {
99+
++frekuensi[label];
100+
}
101+
102+
// temukan label dengan frekuensi tertinggi
103+
std::pair<int, int> prediksi;
104+
// label hasil prediksi
105+
prediksi.first = -1;
106+
// frekuensi tertinggi
107+
prediksi.second = -1;
108+
109+
for (auto &pasangan : frekuensi) {
110+
if (pasangan.second > prediksi.second) {
111+
prediksi.second = pasangan.second;
112+
prediksi.first = pasangan.first;
113+
}
114+
}
115+
// return hasil prediksi
116+
return prediksi.first;
117+
}
118+
};
119+
} // namespace k_nearest_neighbour
120+
} // namespace artificial_intelligence
121+
122+
/**
123+
* @brief fungsi untuk testing knn
124+
*/
125+
static void uji() {
126+
std::cout << "testing knn" << std::endl;
127+
std::vector<std::vector<double>> X1 = {{0.0, 0.0}, {0.25, 0.25}, {0.0, 0.5},
128+
{0.5, 0.5}, {1.0, 0.5}, {1.0, 1.0}};
129+
std::vector<int> Y1 = {1, 1, 1, 1, 2, 2};
130+
auto model1 = artificial_intelligence::k_nearest_neighbour::knn(X1, Y1);
131+
std::vector<double> sampel_pertama = {1.2, 1.2};
132+
assert(model1.prediksi(sampel_pertama, 2) == 2);
133+
std::cout << "testing pass" << std::endl;
134+
}
135+
136+
int main() {
137+
uji();
138+
return 0;
139+
}

0 commit comments

Comments
 (0)