実践的な Golang の基本データ構造とアルゴリズム、k-means クラスタリング アルゴリズム

実践的な Golang の基本データ構造とアルゴリズム、k-means クラスタリング アルゴリズム

起源

最近読んだ本『はじめてのアルゴリズム』(石田康樹、宮崎修一)

この一連のノートは、Golangの実践を目的としたものです

k平均法クラスタリングアルゴリズム

クラスタリングとは、入力データが複数ある場合に、「類似した」データを 1 つのグループにまとめる操作です。 k-means アルゴリズムはクラスタリング アルゴリズムです。 まず、クラスターの中心点としてランダムに k 個の点を選択し、「データを対応するクラスターに分割する」と「中心点を重心に移動する」という 2 つの操作を、中心点が変化しなくなるまで繰り返します。 k-means アルゴリズムでは、演算を繰り返すと中心点の位置がどこかに収束することが数学的に証明されています。 石田康樹、宮崎修一著『はじめてのアルゴリズムより抜粋

シナリオ

  • ある場所で突如として新型コロナウイルス感染症が発生しました。感染者の分布状況から、感染源の特定を急ぐことが防疫上急務となっています。
  • まず、ケース分布の座標をシステムに入力します
  • 次に、k-meansアルゴリズムに従って、1から3までのkに応じてクラスタリングが実行されます。
  • クラスターの中心が病気の発生源である可能性がある

プロセス

  1. サンプル数とサンプル距離計算機が与えられた場合、k 個のサンプル中心点を見つける必要があります。
  2. まず、サンプルからk点をランダムに選択して中心点とする。
  3. 各サンプルをループする

    1. サンプル点からk個の中心点までの距離をそれぞれ計算する
    2. サンプルポイントからの距離が最小の中心点を決定する
    3. サンプルを最小の中心点を持つクラスターに分割する
  4. 各クラスターの中心点を新しい中心点として計算する

    1. クラスター内の各サンプルをループする
    2. このサンプルからこのクラスター内の他のサンプルまでの距離の合計を計算します
    3. 他のサンプルとの距離が最も短い点が新しい中心点となる
  5. 中心点が変化しなくなり計算が完了するまで、3~4を繰り返します。

デザイン

  • IPoint: サンプル ポイント インターフェイス (実際には空のインターフェイス)
  • IDistanceCalculator: 距離計算インターフェース
  • IClassifier: 分類器インターフェース。サンプルを k にクラスタ化し、k の中心点を返します。
  • tPerson: ケースサンプルポイント、IPoint インターフェースを実装、x、y 座標を含む
  • tPersonDistanceCalculator: ケース距離計算機。x 座標と y 座標の 2 点間の直線距離を計算します。
  • tKMeansClassifier: k-means クラスタラー。IClassifier インターフェイスを実装します。

ユニットテスト

k_means_test.go

  1. その他をパッケージ化する
  2. 輸入
  3. km 「学習/gooop/その他/k_means」
  4. 「文字列」
  5. 「テスト」
  6. 関数Test_KMeans(t *testing.T) {
  7. // サンプルポイントを作成する
  8. サンプル:= []km.IPoint {
  9. km.NewPerson( 2 , 11 )、
  10. km.NewPerson( 2 , 8 )、
  11. km.NewPerson( 2 , 6 )、
  12. km.NewPerson( 3 , 12 )、
  13. km.NewPerson( 3 , 10 )、
  14. km.NewPerson( 4 , 7 )、
  15. km.NewPerson( 4 , 3 )、
  16. km.NewPerson( 5 , 11 )、
  17. km.NewPerson( 5 , 9 )、
  18. km.NewPerson( 5 , 2 )、
  19. km.NewPerson( 7 , 9 )、
  20. km.NewPerson( 7 , 6 )、
  21. km.NewPerson( 7 , 3 )、
  22. km.NewPerson( 8 , 12 )、
  23. km.NewPerson( 9 , 3 )、
  24. km.NewPerson( 9 , 5 )、
  25. km.NewPerson( 9 , 10 )、
  26. km.NewPerson( 10 , 3 )、
  27. km.NewPerson( 10 , 6 )、
  28. km.NewPerson( 10 , 12 )、
  29. km.NewPerson( 11 , 9 )、
  30. }
  31. fnPoints2String := func(points []km.IPoint) 文字列 {
  32. アイテム:= make([]文字列、len(ポイント))
  33. i ,it := 範囲ポイント {
  34. アイテム[i] = it.String()
  35. }
  36. 文字列を返します。Join (items, " " )
  37. }
  38. k:= 1 ;k<= 3 ;k++の場合
  39. センター:= km.KMeansClassifier.Classify(サンプル、 km.PersonDistanceCalculator、 k)
  40. t.Log(fnPoints2String(中心))
  41. }
  42. }

テスト出力

  1. $ テストを実行 -v k_means_test.go
  2. === Test_KMeans を実行
  3. k_means_test.go: 53 : p( 7 , 6 )
  4. k_means_test.go: 53 : p( 5 , 9 ) p( 7 , 3 )
  5. k_means_test.go: 53 : p( 9 , 10 ) p( 3 , 10 ) p( 7 , 3 )
  6. --- 合格: Test_KMeans ( 0.00 秒)
  7. 合格
  8. ok コマンドライン引数0.002s

アイポイント

サンプルポイントインターフェースは実際には空のインターフェースです

  1. パッケージキロ
  2. 「fmt」をインポートする
  3. IPointインターフェース型{
  4. fmt.ストリンガー
  5. }

IDistanceCalculator.go

距離計算インターフェース

  1. パッケージキロ
  2. IDistanceCalculatorインターフェース型{
  3. Calc(a, b IPoint) int
  4. }

IClassifier.go

分類器インターフェース、サンプルをkにクラスタ化し、kの中心点を返す

  1. パッケージキロ
  2. IClassifierインターフェース型{
  3. //サンプルをk個のクラスターにクラスタ化し、k個の中心点を返す
  4. 分類(サンプル[]IPoint、calc IDistanceCalculator、k int )[]IPoint
  5. }

tPerson.go

ケースサンプルポイント、IPointインターフェースを実装、x、y座標を含む

  1. パッケージキロ
  2. 「fmt」をインポートする
  3. tPerson構造体型{
  4. x整数
  5. y整数
  6. }
  7. NewPerson関数(x, y int ) IPoint {
  8. &tPerson{x, y, }を返す
  9. }
  10. func (me *tPerson) String() 文字列 {
  11. fmt.Sprintf( "p(%v,%v)" , me.x, me.y)を返します
  12. }

tPersonDistanceCalculator.go

ケース距離計算機、x 座標と y 座標の 2 点間の直線距離を計算します

  1. パッケージキロ
  2. tPersonDistanceCalculator構造体型{
  3. }
  4. var gMaxInt = 0x7fffffff_ffffffff
  5. func newPersonDistanceCalculator() IDistanceCalculator {
  6. &tPersonDistanceCalculator{}を返します
  7. }
  8. func (me *tPersonDistanceCalculator) Calc(a, b IPoint) int {
  9. a == bの場合{
  10. 0を返す
  11. }
  12. p1、OK := a.(*tPerson)
  13. !okの場合{
  14. gMaxIntを返す
  15. }
  16. p2、OK := b.(*tPerson)
  17. !okの場合{
  18. gMaxIntを返す
  19. }
  20. dx := p1.x - p2.x
  21. dy := p1.y - p2.y
  22. d := dx*dx + dy*dy
  23. d < 0 の場合{
  24. パニック
  25. }
  26. 戻るd
  27. }
  28. var 人物距離計算機 = 新しい人物距離計算機()

tKMeansClassifier.go

k-means クラスタラー。IClassifier インターフェイスを実装します。

  1. パッケージキロ
  2. 輸入
  3. 「数学/ランド」
  4. "時間"
  5. tKMeansClassifier構造体型{
  6. }
  7. tPointEntry構造体型{
  8. ポイント IPoint
  9. 距離int
  10. インデックスint
  11. }
  12. func newPointEntry(p IPoint, d int , i int ) *tPointEntry {
  13. &tPointEntry{を返す
  14. p、d、i、
  15. }
  16. }
  17. 関数 newKMeansClassifier() IClassifier {
  18. &tKMeansClassifier{}を返す
  19. }
  20. //サンプルをk個のクラスターにクラスタ化し、k個の中心点を返す
  21. func (me *tKMeansClassifier) ​​Classify(samples []IPoint, calc IDistanceCalculator, k int ) []IPoint {
  22. サンプル数:= len(サンプル数)
  23. サンプル数 <= kの場合
  24. サンプルを返却する
  25. }
  26. // 初期化、k 個の中心点をランダムに選択
  27. rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
  28. 中心 := make([]IPoint, k)
  29. 選択された場合、i:= make(map[ int ]bool, 0 ), 0 ;i < k; {
  30. n := rnd.Intn(サンプル数)
  31. _,ok := 選択[n]
  32. !okの場合{
  33. 選択された[n] = true
  34. センター[i] = サンプル[n]
  35. 私は++
  36. }
  37. }
  38. // 中心点までの距離に応じてサンプルを分割します
  39. のために{
  40. グループ := me.split(サンプル、センター、計算)
  41. 新しい中心点:= make([]IPoint, k)
  42. i ,g := 範囲グループ {
  43. 新しい中心[i] = me.centerOf(g, calc)
  44. }
  45. me.groupEquals(centers, newCenters)の場合{
  46. 返品センター
  47. }
  48. センター = newCenters
  49. }
  50. }
  51. // サンプルポイントと中心点の間の距離をクラスター化します
  52. func (me *tKMeansClassifier) ​​split(samples []IPoint, centers []IPoint, calc IDistanceCalculator) [][]IPoint {
  53. k := len(中心)
  54. 結果:= make([][]IPoint, k)
  55. i := 0 ;i<k;i++ {の場合
  56. 結果[i] = make([]IPoint, 0 )
  57. }
  58. エントリ := make([]*tPointEntry, k)
  59. i ,c := 範囲の中心 {
  60. エントリ[i] = newPointEntry(c, 0 , i)
  61. }
  62. _ ,p := 範囲サンプル {
  63. for _,e := 範囲エントリ {
  64. e.距離 = calc.Calc(p, e.ポイント)
  65. }
  66. 中心 := me.min(エントリ)
  67. 結果[センター.インデックス] = append(結果[センター.インデックス], p)
  68. }
  69. 結果を返す
  70. }
  71. // サンプルのクラスターの重心を計算します。重心は、すべてのポイントまでの距離の合計が最小のポイントです。
  72. func (me *tKMeansClassifier) ​​centerOf(samples []IPoint, calc IDistanceCalculator) IPoint {
  73. エントリ:= make([]*tPointEntry, len(サンプル))
  74. i ,src := 範囲サンプル {
  75. 距離:= 0
  76. _ ,it := 範囲サンプル {
  77. 距離 += calc.Calc(src, it)
  78. }
  79. エントリ[i] = newPointEntry(src, 距離, i)
  80. }
  81. me.min(entries).pointを返す
  82. }
  83. // 2つの点の集合が同じかどうかを判定する
  84. func (me *tKMeansClassifier) ​​groupEquals(g1, g2 []IPoint) bool {
  85. len(g1) != len(g2)の場合{
  86. を返す
  87. }
  88. i ,v := 範囲 g1 {
  89. g2[i] != v の場合
  90. を返す
  91. }
  92. }
  93. を返す
  94. }
  95. // 距離が最小の点を見つける
  96. func (me *tKMeansClassifier) ​​min(entries []*tPointEntry) *tPointEntry {
  97. 最小値:= 0
  98. minD := gMaxInt
  99. i ,it := 範囲エントリ {
  100. it.distance < minD {の場合
  101. 最小I = i
  102. minD = it.距離
  103. }
  104. }
  105. エントリを返す[minI]
  106. }
  107. var KMeansClassifier = newKMeansClassifier()

<<:  GGVファミリー|Kuoboo Smartが2億人民元のプレB-4ラウンドの資金調達完了を発表

>>:  2021 年に企業に影響を与える自然言語処理のトレンド

ブログ    
ブログ    
ブログ    

推薦する

...

テクノロジーは無罪? AIが女性の服を直接「脱がす」!

今朝、またひとつのAI奇抜なアプリケーションが公開されました!アルゴリズムを使って女性の服を直接「脱...

JavaScript チュートリアル: Web アプリケーションに顔検出機能を追加する

[51CTO.com クイック翻訳] 先週、annyang を使用してマップ インターフェースに音声...

大きな出来事がやってくる: Google Bard は Gemini に改名される予定、Ultra 1.0 は強力だが有料、Android アプリも登場

最後に、Google が昨年 12 月に約束した Gemini Ultra はリリースされるのでしょ...

プログラマーの 95% が決して使用しない「アルゴリズム」を勉強する必要はないのでしょうか?

私はほぼ 10 年間コードを書いてきましたが、挿入ソートや赤黒木を書いたことはなく、再帰を使用したこ...

...

人工知能技術の成功と失敗を支える5つの中核要素

海外メディア(VentureBeat)によると、1980年代後半には、多くのスタートアップ企業、政府...

...

...

超音波チップが脳コンピューターインターフェースに革命をもたらす:非侵襲的インプラントに一歩近づく

2023年、脳コンピューターインターフェース(BCI)技術は依然として急速な発展の年を迎えました。脳...

ディープラーニング: シンプルだが限界のあるソリューション

ディープラーニング:幾何学的視点ディープラーニングに関する最も驚くべき事実は、それがいかにシンプルで...

危険が迫っています!マスク氏、AIが5年以内に人間を超える可能性があると警告

[[335742]]メディアの報道によると、7月30日、マスク氏はニューヨークタイムズ紙との独占イン...

ヘルスケア分野で人工知能がどのように台頭しているか

人工知能は世界のほぼすべての分野に変革をもたらしたようです。ヘルスケア業界は長年にわたって大きく変化...

大規模モデルのモデル融合法についてお話しましょう

モデル融合は、特に判別モデルにおいて、これまで頻繁に使用されてきました。これは、常に着実に改善できる...

...