galdric/knn.go
knn.goRaw
1package main
2
3import (
4 "fmt"
5 "sort"
6)
7
8type Neighbour struct {
9 Dist float64
10 Label string
11}
12
13func euclideanDist(img1, img2 [][]float64) float64 {
14 var dist float64
15 for i := 0; i < len(img1); i++ {
16 for j := 0; j < len(img1[i]); j++ {
17 dist += (img1[i][j] - img2[i][j]) * (img1[i][j] - img2[i][j])
18 }
19 }
20
21 return dist
22}
23
24func isNeighbour(neighbours []Neighbour, dist float64, label string) []Neighbour {
25 var temp []Neighbour
26
27 for i := 0; i < len(neighbours); i++ {
28 temp = append(temp, neighbours[i])
29 }
30 ntemp := Neighbour{dist, label}
31 temp = append(temp, ntemp)
32
33 //now, sort the temp array
34 sort.Slice(temp, func(i, j int) bool {
35 return temp[i].Dist < temp[j].Dist
36 })
37
38 for i := 0; i < len(neighbours); i++ {
39 neighbours[i] = temp[i]
40 }
41
42 return neighbours
43}
44
45func getMapKey(dataset map[string]ImgDataset) string {
46 for k, _ := range dataset {
47 return k
48 }
49 return ""
50}
51
52type LabelCount struct {
53 Label string
54 Count int
55}
56
57func averageLabel(neighbours []Neighbour) string {
58 labels := make(map[string]int)
59 for _, n := range neighbours {
60 labels[n.Label]++
61 }
62 //create array from map
63 var a []LabelCount
64 for k, v := range labels {
65 a = append(a, LabelCount{k, v})
66 }
67 sort.Slice(a, func(i, j int) bool {
68 return a[i].Count > a[j].Count
69 })
70 fmt.Println(a)
71 //send the most appeared neighbour in k
72 return a[0].Label
73}
74
75func distNeighboursFromDataset(dataset Dataset, neighbours []Neighbour, input [][]float64) []Neighbour {
76 //check the complete dataset, checking if each entry is a k nearest neighbour
77 for l, v := range dataset {
78 for i := 0; i < len(v); i++ {
79 dNew := euclideanDist(v[i], input)
80 neighbours = isNeighbour(neighbours, dNew, l)
81 }
82 }
83 return neighbours
84}
85func knn(dataset Dataset, input [][]float64) string {
86 k := 6
87 var neighbours []Neighbour
88 var neighboursED []Neighbour
89
90 //get a key from map dataset, the key is a label
91 label := getMapKey(dataset)
92 //fill the first k neighbours
93 for i := 0; i < k; i++ {
94 neighbours = append(neighbours, Neighbour{euclideanDist(dataset[label][0], input), label})
95 neighboursED = append(neighbours, Neighbour{euclideanDist(dataset[label][0], input), label})
96 }
97
98 neighbours = distNeighboursFromDataset(dataset, neighbours, input)
99 neighboursED = distNeighboursFromDataset(datasetED, neighbours, input)
100 neighbours = append(neighbours, neighboursED...)
101
102 for i := 0; i < len(neighbours); i++ {
103 fmt.Print(neighbours[i].Label + " - ")
104 fmt.Println(neighbours[i].Dist)
105 }
106 //from the k nearest neighbours, get the more frequent neighbour
107 r := averageLabel(neighbours)
108 return r
109}