pikesaku’s blog

個人的なプログラム勉強メモです。記載内容について一切の責任は持ちません。

機械学習関係の勉強会メモ②

Deep Learning(以降DLと記載)の代表的な使われ方

 
①画像認識
自然言語処理
音声認識
 
全ての用途においてDLがベストではない。
 

Microsoft Cognitive Services

 
画像分析、音声認識、レコメンデーション等のAPIツールを提供
デモとしてCaptionBotがあり。
 
CaptionBot - For pictures worth the thousand words
 
画像をアップロードすると、それが何であるか認識した結果を教えてくれる。
 
例)はりねずみの写真をアップロードした場合
f:id:pikesaku:20170723125023p:plain
 

Tensor Flow

 
Tensor Flowを理解するには、playgroundが有用
playground.tensorflow.org
 
ニューラルネットワークの仕組みを理解するための教育コンテンツ
 

簡単なデータセットの分類動作

f:id:pikesaku:20170723134213p:plain
左上のデータセット
 
デフォルトの設定のままでも、実行すれば精度の高い学習モデルはすぐできる。
 
実行前
f:id:pikesaku:20170723134025p:plain
 
実行後
f:id:pikesaku:20170723134043p:plain
 

複雑なデータセットの分類動作

右下のデータセット
f:id:pikesaku:20170723134954p:plain
  
デフォルトの設定では、時間がたっても
入力・ニューロン・レイヤを追加する必要あり。
 
実行前
f:id:pikesaku:20170723134705p:plain
 
実行後
f:id:pikesaku:20170723135201p:plain
 
Activationでは活性関数を指定
レイヤやニューロンは多ければ良いわけではない。
できるだけシンプルな構成で精度を上げるのが良し。
 

おすすめのDLフレームワークは?


使いやすいのが一番では?
 

DLの処理について

多層パーセプトロン 入力・出力サイズが固定
RNN 入力が可変のもを扱う。音声・時系列データ等
CNN 画像処理で使われる

 

関連キーワード

 
言語処理=>encodecモデル→RNN→Seq2Seq
Sequence-to-Sequence(Seq2Seq)学習は、任意長の入力列から任意長の出力列を出力するような学習のこと
 
chainernlpman.hatenablog.com
 

Deep Learningの実装はコーディングするべきか?

 
そうでもない。GithubにDL実装プログラムがあり。
言語処理の場合、OpenNMTがオススメ。コードを書かずモデル作成が可能。
 
DL実装ではバグ取りが大変。そもそも結果が何故そうなるかわからないのに、バグかどうかの判定も困難。
Githubソースを使う時の注意点はバグが有る点。信頼性の高いものを使うべき。
最近Tensor FlowがOpenNMTみたいなサービスを公開したらしい。。。
 

OpenNMTについて

 
必要なものはデータだけ。
質問&回答を記述した2つのファイルが必要。(2ファイル間で質問と回答が1行毎に対応している必要あり。)
質問・回答セットは万単位は必要
 

Deep Learning取り組みの現状

 
経験則が大きい。何故それが正しいかは、説明できないケースが多い。
ビジネス活用する時は、簡易PoCをして結果が出たものを使うべき。結果が出ない場合は、ニューラルネットをいくら調整しても無理な場合が多い。 
汎用人工知能→専門家の間では使われない言葉。SF映画レベルの色々できる人工知能はまだまだ実現できないとの感想。現在の人工知能はタスク特化。それらを組み合わせた結果、汎用的に見えるものもあるが、あくまで複合技術であり、カバーできる範囲は少ない。
 

Deep Learningに取り組む時の数学知識の取得について

 
Playgroundが理解できる程度でOK。(これだけでも難しいそうなのだが。。。。。) 
統計学の習得は不要。
数学知識の習得は必要に応じてやるのが効率良し。
 

OpenNMT検証メモ

  
OpenNMT - Open-Source Neural Machine Translation
 

環境

Ubuntu 16.04.2 LTS
最小インストー
言語・ロケールは日本語選択
 

環境構築手順

 
Installation - OpenNMT
 
上記のDocker利用方式でやってみる。
 
Ubuntuにopenssh-serverインストール&起動(Ubuntuは普段使わない。最小だとインストールされなかった)
$ sudo atp-get install openssh-server
$ systemctl start sshd
 
$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb
$ sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb

$ sudo apt-add-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main'
$ sudo apt-get update
$ vim /etc/apt/sources.list
以下行を最後に追加
deb http://kr.archive.ubuntu.com/ubuntu trusty main
$ sudo apt-get install libltdl7 docker-engine
$ sudo apt-get install nvidia-modprobe
$ sudo dpkg -i /tmp/nvidia-docker*.deb
 
※URLの手順だとlibltdl7が依存関係でインストールされない問題があった為、上記手順で実施。nvidia-dcockerも最新がリリースされていた為、wgetのパス変更。
 
$ sudo nvidia-docker run -it harvardnlp/opennmt:8.0



 

機械学習関係の勉強会メモ①

人工知能キーワード

 
f:id:pikesaku:20170723123119p:plain
 
機械学習=Deep Learningではない。
人工知能の明確な定義はなし。言ったもん勝ち
 

機械学習イメージ

f:id:pikesaku:20170723112242p:plain
 

機械学習で必要な数学を学ぶためのオススメ参考書

 
http://www.mathema.jp/books/zemi_math.html
微分積分キャンパス・ゼミ
線形代数キャンパス・ゼミ
統計学キャンパス・ゼミ
 

機械学習で利用される数学アルゴリズムには2つの流派があり

 

流派 難易度 抽象度
線形代数ベース 比較的具体的 SVM, DeepLearning, 重回帰分析
確率統計ベース MCMC, HMM, ベイズ統計(超難)

 
どちらでも、基本的に同じことが実現できる。
違いは確率統計ベースの方が、不確実性まで予測できる点
例) 家賃予測の場合
線形代数ベース→〜万
線形代数ベース→〜%の確率で〜万
 
機械学習は学習で挫折しない為に、まず線形代数ベースから取り組むべき。
機械学習で必要な数学知識を身につけるには、以下セミナーが有用
www.kikagaku.co.jp
 

機械学習における予測の考え方

 
f:id:pikesaku:20170723114643p:plain
 
上記のデータが学習済みの場合、、、
3が入力された場合の予測を内挿
5が入力された場合の予測を外挿
 
と言う。機械学習の予測は、基本的に内挿で行うべき。
外挿は予測結果が精度は低くなる。
 
基本的には与えたデータの範囲で予測すべき
 

学習データに異常データがあった場合の対処

除外する
他データの平均値で補完
 

機械学習の現状

 
経験則&勘で行われている。
何故、この方法がいいかは?は解明されないケースが多い。
実際にデータを学習し結果を見る必要があり。
 

Deep Learning(以降DLと記載)と、それ以外の機械学習の違い

 
f:id:pikesaku:20170723120313p:plain
 
DLは特徴量も自動抽出するのが特徴。
必ずしも、DLを採用すべきではない。扱うデータにより採用すべきアルゴリズムは変わる。
 
例)画像認識の場合
従来は、グレースケール処理(モノクロ変換)等、特徴量抽出の為の操作が必要であったが、DLの場合は、これらが不要
 

機械学習カテゴリ

 

教師あり 入力と答えのセットで学習
教師なし クラスタリング(顧客データの属性分け)、次元削減(大量データから密度の高い部分のみ抽出・主成分分析とも言う)
強化学習 思考錯誤を通じ、「価値を最大化するような行動」を学習。例)ルンバ

 
強化学習=DLではない。
強化学習については以下書籍に良い解説あり。
https://www.amazon.co.jp/実装-ディープラーニング-藤田一弥/dp/4274219992
 

データサイエンスとデータエンジニアリングの違い

 
データサイエンス→研究・数学
データエンジニアリング→プログラミング 
 

今オススメのDeep Learningフレームワークは?

  
Chainner or Tensor Flow
 
Chainnerは少し難しいことやろうとすると数学知識や深い知識が必要になる&技術情報は英語を読む必要あり。
Tensor Flowはネットに技術情報が多くある。今最も主流。
 
Tensor Flowをやるのが無難そう。
Chainnerを理解してれば、Tensor Flowへの転向は容易。
 

グラフデータベースNeo4j動作検証

やってみる

 
路線図とかをインプットしてみて最短距離検索とかやる場合、どうやるのかな?
と思っていたら、参考URLがあったので、やってみる!
※正直しっかり理解できてません。。。
 

データ登録スクリプト

 
山手線の路線図を作るだけ。

# -*- coding: utf-8 -*-

import urllib.request as urllib
from xml.dom import minidom, Node
from neo4j.v1 import GraphDatabase, basic_auth


def get_station_info(line_cd):
    join_list = []
    url = 'http://www.ekidata.jp/api/n/' + str(line_cd) + '.xml'
    dom = minidom.parse(urllib.urlopen(url))
    all_station = set()
    all_kukan = dict()
    for join_node in dom.getElementsByTagName('station_join'):
        for join_node_child in join_node.childNodes:
            if join_node_child.nodeType == Node.TEXT_NODE:
                continue
            name = join_node_child.nodeName
            value = join_node_child.childNodes.item(0).nodeValue
            if name == 'station_name1':
                station_name1 = value
                all_station.add(value)
            elif name == 'station_name2':
                station_name2 = value
                all_station.add(value)
        all_kukan[station_name1] = station_name2
    return all_station, all_kukan


def connect_srv():
    driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth('neo4j', 'neo4j'))
    return driver


if __name__ == '__main__':
    all_station, all_kukan = get_station_info(11302)
    driver = connect_srv()

    # Delete Data
    session = driver.session()
    q = 'match (a) optional match (a)-[r]-() delete a,r'
    session.run(q)


    # Add Data
    for station in all_station:
        q = 'create (a:' + station + '{name:' + "'" + station + "'" + '})'
        session.run(q)

    # Add Connectivity
    for src,dst in all_kukan.items():
        q = 'match (a:' + src + '{name:' + "'" + src + "'" + '}), '
        q += '(b:' + dst + '{name:' + "'" + dst + "'" + '}) '
        q += 'merge (a)-[c:rosen]->(b)'
        session.run(q)

    session.close()

 
上記を実行すると、こんなグラフが生成される。
f:id:pikesaku:20170717193330p:plain
 
駅の色に意味なし。neo4jが登録順にラベルの色をつけているためと想定される。
駅間の距離も意味なし。
内・外回りのリレーションを作ろうと思ったが、双方向リレーションを設定するのは、非推奨との情報あり。
Neo4jで学ぶGraph DB入門 - omotenashi-mind
Modelling Data in Neo4j: Bidirectional Relationships
参照時は、方向性を無視した探し方で対応するのが良いとのこと。
 

最短距離を検索

 
GUIから以下クエリを実行

池袋→東京

MATCH (from: 池袋 {name:'池袋'}), (to: 東京 {name:'東京'}), path=allShortestPaths((from)-[*]-(to)) return from,to,path

 
f:id:pikesaku:20170717195954p:plain
 

池袋→新宿

MATCH (from: 池袋 {name:'池袋'}), (to: 新宿 {name:'新宿'}), path=allShortestPaths((from)-[*]-(to)) return from,to,path

 
f:id:pikesaku:20170717200128p:plain
 

グラフデータベースNeo4jのクエリ言語Cypherの動作検証

はじめに

 
データ操作はCypherと呼ばれるクエリ言語を利用
Cypherは以下4つのIFより実行可能
①Neo4jウェブインターフェー
②Neo4jシェル
REST API
④Neo4jドライバー
 
Cypher動作検証にNeo4jシェルを利用した。
事前に以下セットアップを実施した。
pikesaku.hatenablog.com

 

データ構成要素

ノード(データの最小単位)

①ラベル
②属性
 

関係性

①タイプ
②方向性
③属性
  

データ構造

 
上記参考URLより引用

f:id:pikesaku:20170717140119p:plain

 
参考URL筆者の考察の箇条書き
・ノードとノード間の関係性を明確に分離して管理
・ノードはノードストア・関係者は関係性ストアで管理
・同じラベルを持ったノード群がRDMSのテーブル、ノードの属性はレコードのような役割をする。
・関係性はタイプという情報を持つ。タイプは属性情報を保持し、多様性のある連結を表現。
 

データ操作

 
neo4j-shellで記述

全ノード参照

 

neo4j-sh (?)$ match (a) return a;
+---+
| a |
+---+
+---+
0 row
9 ms
neo4j-sh (?)$ 

  
上記で全ノードの情報確認が可能
上記のaは識別子。クエリ実行時のみ利用される識別子。aでなくてもOK
 

neo4j-sh (?)$ match (hoge) return hoge;
+------+
| hoge |
+------+
+------+
0 row
18 ms
neo4j-sh (?)$ 

 
returnや他操作(後述するcreate or merge or delete等)を指定しないとエラーになる。
 

neo4j-sh (?)$ match (a);
1 ms

WARNING: Query cannot conclude with MATCH (must be RETURN or an update clause) (line 1, column 1 (offset: 0))
"match (a)"
 ^
neo4j-sh (?)$ 

 

ノード登録

 

ラベルも属性もないノードを登録

neo4j-sh (?)$ create (hoge);
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
5 ms
neo4j-sh (?)$ match (a) return a;
+-----------+
| a         |
+-----------+
| Node[4]{} |
+-----------+
1 row
6 ms
neo4j-sh (?)$ 

 
Node[4]の4は内部でノードを特定するためのID番号が使われていると想定。
上記が[4]になった理由は、上記実行前に登録したデータがあったため。
 

登録後に状態を表示させるには、returnを付与

neo4j-sh (?)$ create (hoge2) return hoge2;;
+-----------+
| hoge2     |
+-----------+
| Node[0]{} |
+-----------+
1 row
Nodes created: 1
42 ms
neo4j-sh (?)$ 

 

ラベル有・属性なしで登録

識別子:ラベルで記述。
※くどいが識別子はクエリ実行時のみ利用される情報。なんでもOK。自分はこの情報を知らず、結構はまった。。。。。
以下の場合、

neo4j-sh (?)$ create (test:hoge) return test;
+-----------+
| test      |
+-----------+
| Node[2]{} |
+-----------+
1 row
Nodes created: 1
Labels added: 1
20 ms
neo4j-sh (?)$ 

 

ラベル有・属性ありノードを登録

neo4j-sh (?)$ create (test:hoge{zoku1:"test", zoku2:1000, zoku3:True}) return test;
+---------------------------------------------+
| test                                        |
+---------------------------------------------+
| Node[3]{zoku1:"test",zoku2:1000,zoku3:true} |
+---------------------------------------------+
1 row
Nodes created: 1
Properties set: 3
Labels added: 1
37 ms
neo4j-sh (?)$ 

 

全ノード削除

neo4j-sh (?)$ match (a) delete a;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 5
21 ms
neo4j-sh (?)$ 

 

関係性のあるノードの登録

neo4j-sh (?)$ create (a:hoge1{zoku:"test"}), (b:hoge2{zoku:"test"}), (a)-[kankeiseitype:huga]->(b) return a,b,kankeiseitype;
+-------------------------------------------------------------+
| a                    | b                    | kankeiseitype |
+-------------------------------------------------------------+
| Node[8]{zoku:"test"} | Node[9]{zoku:"test"} | :huga[1]{}    |
+-------------------------------------------------------------+
[f:id:pikesaku:20170717155751p:plain]1 row
Nodes created: 2
Relationships created: 1
Properties set: 2
Labels added: 2
18 ms
neo4j-sh (?)$ 

 
上記では、ラベルhoge1を持つノードとラベルhoge2を持つノードを関係性タイプhugaで関係性をもたせている。
GUIでは以下の様に表示される。

f:id:pikesaku:20170717155832p:plain
 

関係性のあるノードの削除

ノード削除ではエラーになる。事前に関係性を削除する必要あり。

neo4j-sh (?)$ match (a) delete a;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 2
4 ms
ConstraintViolationException: Cannot delete node<8>, because it still has relationships. To delete this node, you must first delete its relationships.
neo4j-sh (?)$ match (a) optional match (a)-[r]-() delete a,r;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 2
Relationships deleted: 1
17 ms
neo4j-sh (?)$ 

 
optional matchで関係性も削除すればOK
 

まとめ

 
他mergeなどいろいろな操作が可能だが、参考URLをみればなんとかできそう。
個人的な動作把握のためのメモとしては、これまでとする。

グラフデータベースNeo4jのセットアップ

環境構築

 
環境: Mac Sierra
 
Javaインストー

brew cask install java

 
brewでNeo4jをインストー

brew install neo4j

 

やってみる

 
①shellからCypher実行するために設定ファイル変更
stackoverflow.com
 

$ diff /usr/local/Cellar/neo4j/3.2.2/libexec/conf/neo4j.conf /usr/local/Cellar/neo4j/3.2.2/libexec/conf/neo4j.conf_org 
233c233
< dbms.shell.enabled=true
---
> #dbms.shell.enabled=true
235c235
< dbms.shell.host=127.0.0.1
---
> #dbms.shell.host=127.0.0.1
237c237
< dbms.shell.port=1337
---
> #dbms.shell.port=1337

 
上記変更しないと、neo4j-shell実行時に
Connection refused
エラーになる。
 
②neo4j起動

neo4j start

 
※停止はneo4j stop
 
③Webアクセスしneo4jユーザーでログインしパスワード変更
http://localhost:7474/browser/
 
④neo4j-shellログイン確認

$ neo4j-shell

データ構造としてのグラフとは?

グラフとは?

 
ノードとエッジで表現するデータ型
ノードは頂点
エッジはノード間の連結関係を示す
グラフ理論を適用できる
mathtrain.jp

 

グラフの数学的表現方法

以下の2つがあり。
 

①隣接行列

 
以下URLより引用
隣接行列 — WTOPIA v1.0 documentation
 

行列という名の通り, グラフを 2 次元配列で表現する. 配列のインデックスがノードの番号に対応する. 例えば, この 2 次元配列を M とすると, M[i][j] がノード i と ノード j の関係を表す

f:id:pikesaku:20170716223645p:plain

 
連結の向き・重みを考慮した場合の表現もある。
 

②隣接リスト

 
以下URLより引用
mathwords.net
 

f:id:pikesaku:20170716224306p:plain

 

グラフ表現の例

 
tech-blog.abeja.asia
グラフ表現
 
画像や文章の表現も可能。
画像表現に適しているが、グラフ構造を処理するには、計算量が莫大になる問題があり。
 
※Convolution=畳み込み(難しい。。。)
qiita.com