k-meansとClojure

機械学習技術 人工知能技術 デジタルトランスフォーメーション技術  サポートベクトルマシン 自然言語処理技術 Clojure

前回に引き続き、clojureを用いた機械学習を述べたい。今回は教師なし学習であるk-meansについて。

ライブラリはclusteringを用いる。

:dependenciesは以下となる。

[rm-hull/clustering "0.2.0"]

オフィシャルサンプルコードは以下となる。

(require '[clustering.core.k-means :as k-means])
(require '[clj-time.core :refer [after? date-time interval in-days])
(require '[clj-time.format :refer [unparse formatters])
(require '[clj-time.coerce :refer [to-long from-long])

(def test-dataset
  (hash-set
    (date-time 2013 7 21)
    (date-time 2013 7 25)
    (date-time 2013 7 14)
    (date-time 2013 7 31)
    (date-time 2013 7 1)
    (date-time 2013 8 3)

    (date-time 2012 12 26)
    (date-time 2012 12 28)
    (date-time 2013 1 16)

    (date-time 2012 6 2)
    (date-time 2012 6 7)
    (date-time 2012 6 6)
    (date-time 2012 6 9)
    (date-time 2012 5 28)))

(defn distance [dt-a dt-b]
  (if (after? dt-a dt-b)
    (distance dt-b dt-a)
    (in-days (interval dt-a dt-b))))

(defn average [dates]
  (from-long
    (/ (reduce + (map to-long dates)) (count dates))))

(def means (k-means/init-means 3 test-dataset)

(def groups (k-means/cluster distance average test-dataset means 0))

(count groups)
; => 3

(map fmt (sort (groups 0)))
; => ("2012-12-26" "2012-12-28" "2013-01-16")

(map fmt (sort (groups 1)))
; => ("2013-07-01" "2013-07-14" "2013-07-21" "2013-07-25" "2013-07-31" "2013-08-03")

(map fmt (sort (groups 2)))
; => ("2012-05-28" "2012-06-02" "2012-06-06" "2012-06-07" "2012-06-09")

サンプルでは日時情報のクラスタリングだが、これを自然言語処理の結果と組み合わせてみる。

形態素解析は、前回と同様にkuromojiを利用する。

;;形態素解析関数
(defn morphological-analysis
  [src]
  (let [analyzer (JapaneseAnalyzer. nil
                                    JapaneseTokenizer/DEFAULT_MODE
                                    CharArraySet/EMPTY_SET
                                    #{})
        rdr (StringReader. src)]
    (with-open [ts (.tokenStream analyzer "field" rdr)]
      (let [^OffsetAttribute       offsetAtt (.addAttribute ts OffsetAttribute)
            ^PartOfSpeechAttribute posAtt    (.addAttribute ts PartOfSpeechAttribute)
            _       (.reset ts)
            surface #(subs src (.startOffset offsetAtt) (.endOffset offsetAtt))
            pos     #(.getPartOfSpeech posAtt)
            tokens  (->> #(if (.incrementToken ts)
                            [(surface) (pos)]
                            nil)
                         repeatedly
                         (take-while identity)
                         doall)
            _       (.end ts)]
        tokens))))

これで入力文を分解してトークンデータとする。後はこれも前述と同様にclojureのhash-set関数を用いて全てのトークンデータをつなぎ合わせてhash-set化すれば学習の準備は整う。

なおpythonでのk-meansに関しては”k-meansの概要と応用および実装例について“を参照のこと。

コメント

  1. […] 最近傍法は以前k-meansとして紹介したものでもあり、ある分布をしている訓練データを用いていくつかのクラスターに分類し、入力データが与えられるとそのクラスタとの距離を計算して一番近いものを探すと言うものになる。ここで距離の概念は単純に空間的なものだけでなく以下のような画像の場合にも適用される。 […]

  2. […] k-meansとClojure 教師なし学習 […]

  3. […] その他の解釈可能なモデルとしては、ナィーブベイズ、k-means等がある。 […]

  4. […] 自然言語処理の機械学習で利用される。one-hot-vectorとcategory vectorのClojureでの実装。(形態素解析やCSVの入出力以外は極力外部のライブラリを使わない形で実装。 […]

タイトルとURLをコピーしました