arnaucube
arnaucube/galdricPublic Self-hosted repository
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}