Clojureでの one hot vectorとcategory vector

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

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

(ns test01.core
  (:require [clojure.data.csv :as csv]
           [clojure.java.io :as io]
           [clojure.string :as str])
  (:import (java.io File FileInputStream InputStreamReader BufferedReader StringReader
                    BufferedWriter OutputStreamWriter FileOutputStream)
           (org.apache.lucene.analysis.ja JapaneseAnalyzer JapaneseTokenizer)
           (org.apache.lucene.analysis.ja.tokenattributes PartOfSpeechAttribute)
           (org.apache.lucene.analysis.tokenattributes CharTermAttribute OffsetAttribute)
           (org.apache.lucene.analysis.util CharArraySet)))

;;csvからデータ読み込み(Read data from csv)
(def data-reads
  (with-open [reader (io/reader "data/in/test-data.csv")]  ;;read test-data from folder
    (doall
     (csv/read-csv reader))))

;;形態素解析関数(morphological function)
(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))))

;;形態素解析の結果を(品詞,単語)の形に変形(Transform morphological analysis results into (part of speech, word) form)
(defn simple-morph [n]
  (map #(list (first (str/split (% 1) #"-")) (% 0))
       (morphological-analysis n)))

;;名詞抽出(pick up named entity)
(defn meisi-token [n]
  (keep
   #(cond
      (= "名詞" (first %)) (second %)
      :else nil)(simple-morph n)))
;;stop wordデータ(stop-word-num.txt等)を抜いて出現する単語辞書を作成(Create a dictionary of words that appear by extracting stop word data (stop-word-num.txt, etc.))
(def word-dic-raw3
  (->>
   (distinct (flatten (map #(meisi-token (nth (nth data-reads %) 1))(range (count data-reads)))))
   (remove (set (read-string (slurp "data/in/stop-word-num.txt"))))
   (remove (set (read-string (slurp "data/in/stop-word-kana.txt"))))
   (remove (set (read-string (slurp "data/in/stop-word1w.txt"))))))

;;word-dicの数
(def count-word-dic (count word-dic-raw3))
count-word-dic

;;word-dicでzipmapデータをつくる
(def word-dic3
  (zipmap
   (range (count word-dic-raw3))
   word-dic-raw3))

;;n番目の文章のm番目の単語がマッチするcategory No.を抽出する
(defn pickup-category-num [n m]
  (->> word-dic3
       (filter #(= (second %) (nth (meisi-token (nth data-reads n)) m)))
       first
       first))

;;それぞのn番目の文章の中全単語に適用(カテゴリベクトルの作成)
(defn category-vec [n]
  (map #(pickup-category-num n %)
       (range (count (meisi-token (nth data-reads n))))))


;;category-vectorの変形(カテゴリベクトルの頻度を抽出したmap)
(defn frequencies-category-vec [n]
  (frequencies (category-vec n)))


;;one-hot-vector作成のためのrawデータ全部でm個ある単語の中でn番目を1にする
(defn one-hot-vec [n m]
  (concat
   (vec (take (- n 1) (repeat 0)))
   [1]
   (vec (take (- m n) (repeat 0)))))

;;行列形態のone-hot-vector作成(n番目の文章でone-hot-vectorをつくる)
(defn doc-one-hot-vec [n]
  (vec (map #(vec (one-hot-vec % count-word-dic))(category-vec n))))


;;同じone-hot-vectorカウントして行列からベクトルにする(one-hot-vecを潰したもの)
;;ベクトルの足し算
(defn sum-doc-one-hot-vec [n]
  (loop [x (rest (doc-one-hot-vec n))
         y (first (doc-one-hot-vec n))]
    (if (empty? x)
      y
      (recur (rest x)(map + y (first x))))))

これらで作成されたデータを用いて各種の分類や深層学習の処理が可能になる

コメント

  1. […] このようにして抽出した単語から、不要な単語を抜き出したり(stop-word除去)、ベクトル化(one-hot-vector)を行うことで機械学習が行えるようになる。シンプルな機械学習例としては、検索等で用いられるtfidfを使った単語の頻度抽出等がある。 […]

  2. […] その橋渡しの一つの手段として「one-hotベクトル表現」がある。これはある次元のベクトルのうち一つの要素だけ1で残りの要素が0のベクトルで、事前に決めた語彙Vがあるとき、語彙数は|V|で表され、語彙V 中の各単語に1から|V|までの単語番号を割り振る。この時与えられた文のi番目に出現した単語の単語番号がnであったときに、i番目の単語を表すベクトルxiは、n番目の要素を1にし、それ以外の要素を0とするベクトルで表現するものになる。 […]

  3. […] Clojureでのone hot vectorとcategory vector […]

  4. […] Clojureでのone hot vectorとcategory vector […]

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