実践的な 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 年に企業に影響を与える自然言語処理のトレンド

ブログ    
ブログ    
ブログ    

推薦する

...

今年の主要リリース: 人工知能開発レポート 2020

過去10年間で、人工知能は研究室から工業生産へと移行し、従来の産業モデルを再構築し未来をリードする価...

協働ロボットはインダストリー4.0戦略の成功の核心です

インダストリー4.0戦略における自動化とロボットのシームレスな統合に対する関心が高まっています。しか...

...

...

...

知識共有: 管理距離と最大ホップ数の違いに関するルーティングアルゴリズムの分析

管理距離は、ルーティング プロトコルの優先度を表す人工的に指定された数値です。数値が小さいほど、ルー...

グラフ ネットワークをより堅牢にします。 Googleは、データのラベル付けバイアスやドメイン転送を恐れないSR-GNNを提案

グラフ ニューラル ネットワーク (GNN) は、機械学習でグラフ構造データを活用するための強力なツ...

GitHub のホット プロジェクト: 実稼働レベルのディープラーニング プロジェクトを構築するには?

ディープラーニング モデルを本番環境に導入することは、優れたパフォーマンスのモデルをトレーニングする...

...

...

ボストン住宅データセットに基づくシンプルなMLP回帰モデルのトレーニング

[[422501]]多層パーセプトロン(MLP)は非常に長い歴史を持っています。多層パーセプトロン(...

ドローンのバッテリー寿命の悩みをどう解決するか?答えは3つの主要な方向から得られる

近年、我が国のドローン産業は、継続的な技術革新、継続的な政策奨励、加速した資本注入、段階的な市場改善...

機械学習のプライバシー研究における新たな進歩: データ強化のリスクは過小評価されており、新しいアルゴリズムは次元依存性を「克服」します

編集者注: 今日、データは人工知能のイノベーションを推進する中核的な要素です。ただし、データのセキュ...