Elixirで機械学習に初挑戦①：基礎知識とLivebook＋Nx＋Axonによる機械学習入門

この記事は、[Elixir Advent Calendar 2022](https://qiita.com/advent-calendar/2022/elixir) 2の8日目です

昨日は、@the_haigo さんで[「Livebook + Evision基本編 Evision(OpenCV)でお手軽画像処理](https://qiita.com/the_haigo/items/baf47624567cb992d934)でした

---

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

この2年間で、Elixirの機械学習環境が凄まじく発展し、プロダクションに実戦投入しても問題無いフェーズに入ったので、「Eixirで機械学習に初挑戦」をテーマにシリーズコラムをお届けします

入門者向けに「機械学習とは何か？」や、機械学習の中で出てくる数々のキーワード解説もしていきますので、AI・MLの知識が無いWeb開発者／IoT開発者の方や、PythonでAI・MLを学んだけどイマイチ入らなかった方、Elixir経験者だけどNx／Axon／Livebook等の新テクノロジーに追いつけていない方にも、スッと入りやすい内容としてまとめていこうと思います

今回は、機械学習の最低限の基礎知識を入れつつ、カンタンな実装も行ってみます

なお、本コラムに対し、更に分かりやすい解説を @RyoWakabayashi さんが書いてくれていますので、本コラムを読んでいて難しいなぁ…と感じた方は、コチラをご参考に理解を深めてください

https://qiita.com/RyoWakabayashi/items/62e45b805f5de2d96017

また、下記のように、本コラムをベースに、ゼロから解説するハンズオンイベントも開催していますので、connpassメンバー登録をして、イベント開催通知をお待ちいただくのも手です

https://fukuokaex.connpass.com/event/276109/

<h3>:ocean::ocean::ocean: Elixir Advent Calendar: 言語カテゴリ1位+全カテゴリ2位! :ocean::ocean::ocean:</h3>

例年を遥かに超える盛り上がりを見せ、堂々のトップ獲得ッ！ :qiita: :tada: :confetti_ball:

https://qiita.com/advent-calendar/2022/elixir
https://qiita.com/advent-calendar/2022/ranking/feedbacks
https://qiita.com/advent-calendar/2022/ranking/feedbacks/categories/programming_languages
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/356a15c6-0dbb-097e-38f3-a1b4fed47555.png)](https://qiita.com/advent-calendar/2022/ranking/feedbacks/categories/programming_languages)

# 本シリーズの目次

[**①：基礎知識とLivebook＋Nx＋Axonによる機械学習入門**](https://qiita.com/piacerex/items/0871b54b41128d426da5)
|> [**②：機械学習コードの解説と「学習データの可視化」「学習過程のアニメ化」**](https://qiita.com/piacerex/items/96220f6954fc1c6fe718)
|> [**③：「予測」の可視化と「精度」の変化要因、「学習過程グラフ」の読み方**](https://qiita.com/piacerex/items/2c78dd26f879e6733f4d)
|> [**④：データ処理に強いElixirでKaggle挑戦（前編）…「データ前処理」基礎編**](https://qiita.com/piacerex/items/a40c5d24190d59f68610)
|> [**⑤：データ処理に強いElixirでKaggle挑戦（後編）…「統計」と「EDA」でKaggleに挑む**](https://qiita.com/piacerex/items/bf283a63945040c25a72)
|> [**⑥：いま、Elixir AI・MLで何が出来る？ → Elixirのメリット→2023年に攻略する領域**](https://qiita.com/piacerex/items/645939c537f24e68f514)

# 本コラムの検証環境

本コラムは、以下環境で検証しています（恐らくUbuntu実機やMacでも動きます）

- Windows 10 ＋ WSL2 ＋ Ubuntu 22.04　※[**最新版のインストール手順はコチラ**](https://qiita.com/piacerex/items/01e89435af0f7a454ad2)
- Elixir 1.14.2　　　　　　　　　　　　　※[**最新版のインストール手順はコチラ**](https://qiita.com/piacerex/items/01e89435af0f7a454ad2)
- Livebook 0.8.0

# 機械学習（ML：Machine Learning）とは？

ズバリ、

:::note
**「入力と出力から自動的に振る舞いを学習するアルゴリズム」**
:::

のことを指します

以下のような特徴を持っています

- 人間がプログラミングせずとも、入力データのパターンから、出力データを「学習」します
- 「学習」に基づいた「予測」を可能とします
- 「学習」は、入力データと出力データの「関係性」に対して行われます
- 「機械学習」≒「Machine Learning」の頭文字を取って、「ML」とも呼ばれます

# 機械学習ってなぜ流行しているの？

これもズバリ、

:::note
**「人間が頑張らなくても、予測精度の高いプログラムが自動生成できた」**
:::

という点がウケた理由です

そうなるまでに至る経緯は、以下の通りです

- 「機械学習」という言葉自体は、1960年から使われていました … が …
  - コンピュータ性能があまり高く無い時代だったため、機械学習がマトモに使えませんでした
  - その状況は、グラフィック向けの「GPU」がそれなりの性能となる2000年代まで続いていました
- 予測精度向上のための入力データ自動選定ができず、人間が苦労しなければプログラム化不可でした
- こうした状況から、システム利用が困難で、期待に応えられない失望期が2000年代まで続きました
- 2012年に生まれた「ディープラーニング」で、高い予測精度のプログラムの自動生成に成功しました
  - 入力データの自動選定が可能となりました
  - 人の感性にも合う予測精度を、人間の苦労無に実現できるようになりました
  - こうして、ディープラーニングがブレイクしました
- このディープラーニングが流行する余波で、機械学習にも注目が戻ってきました

このような流れから、現在の機械学習の流行へと繋がっています

# 機械学習はどういった場面で活躍するの？

これまたズバリ、

:::note
**条件や行動履歴などから、予測や識別を行う**
:::

という場面で活躍します

以下のような代表例があります

- 問題検知／不正検知：正規の行動で無いものを見つける
  - 例）クレジットカード作成の審査でNGの人を検出する
- レコメンド：人の行動傾向を他の多人数と比較し、次の行動を推奨する
  - 例）商品購入傾向から推奨商品をオススメしたり、広告を出す
- 価格予測：対象の価格を左右する条件／データを元に価格予測を行う
  - 例）物件の周辺情報や物件の写真から不動産購入価格を予測する
- 画像／音声／自然言語識別：特徴から対象を特定したり、その状態を特定する
  - 例）画像／音声／自然言語から対象が何者であるかを識別したり、感情特定をする
- 画像／音声／自然言語生成：特定の入力傾向から期待する出力を得る
  - 例）相手が人であるかの如く、投げかけた言葉から画像／音声／自然言語を生成する

# 参考：AIやニューラルネットワークとの関係性は？

ここが、やや分かりにくいところかも知れませんが、

:::note
- 機械学習 ≒ AIの1バリエーション
- ニューラルネットワーク ≒ 機械学習の1バリエーション
- ディープラーニング ≒ ニューラルネットワークの1バリエーション
:::

という関係性になります

図示すると以下のようになります（現時点で、下図の内容は把握しなくてもOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/ed8e3096-9b06-0a18-2744-02d0092ab3a0.png)

AIには、機械学習以外に「エキスパートシステム」などがあります（覚えなくてOK）

機械学習には、ニューラルネットワーク以外に以下のようなものがあります（覚えなくてOK）

- k近傍法
- 線形回帰
- リッジ回帰、ラッソ回帰
- ロジスティック回帰
- 決定木
- アンサンブル学習
  - バギング（ランダムフォレスト）
  - ブースティング（勾配ブースティング、AdaBoost、XGBoost、LightGBM）
  - スタッキング（メタモデル）
- 単純ベイズ
- サポートベクターマシン
- 隠れマルコフ
- ベイジアンネットワーク
- k-means
- 階層的クラスタリング
- DBSCAN
- EMアルゴリズム
- 主成分分析（PCA）
- NMF
- 混合ガウス
- LLE
- 動的計画法
- モンテカルロ法
- 時間的差分学習

ニューラルネットワークには、ディープラーニング以外に「単純パーセプトロン」などがあります（覚えなくてOK）

# 機械学習でどのようなことが可能になるのか？

機械学習（以降MLと省略）を使うと、どのようなことが可能になるのか、カンタンな例で解説します

## ①画像識別

たとえば、以下のような特徴の強弱で配置された「犬」と「猫」の画像群があったとき、線を1本引いて、「犬」と「猫」を分割するとしたら、どこに引きますか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/3d15dee7-ac70-103c-8576-687766cd3f5e.png)

こんな感じでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/743eab3e-e828-61c7-99bb-5ca58828f29c.png)

このように、2つの種類を識別するような線を自動特定できるのが、MLの出来ることの代表です

なお、いきなりズバリな線を、人間のように特定することはコンピュータには不可能なため、最初はランダムな線を引き、徐々にイイ感じに識別できる線を求めていきます（これは現時点では、あまりピンと来なくてもOK）

ここでは、「犬」を「0」、「猫」を「1」として、そこに近い画像ほど「0」や「1」という数字が振られ、「犬」とも「猫」とも付きにくい画像ほど「0.5」に近い数字が振られた状態で、イイ感じに識別できる線を「学習」していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/0091668e-3d08-0c9c-a0fb-b8a79da9fd8f.png)

このような仕組み上、たまにハズレも出します … 下図の緑枠は、「犬」なのに「0.5」以上で識別されてしまい、「猫」と間違えた例です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/58b94c04-acf8-3a91-87fb-03669d9d5f94.png)

全14匹中、1匹のハズレは、「正解率92.8%」という評価となり、これを「精度」と呼びます

## ②手書き文字識別

「犬」「猫」のような2種類の識別だけで無く、複数種類の識別もできます

たとえば、下図のような、人が書いた「0」～「9」の手書き文字を識別するといったものが代表例です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/5b71e4c8-d215-964a-30e4-3ecbe61c922c.png)

このような、複数種類の識別を「多クラス分類」と呼びます … 「クラス」とは「種類」のことを意味するので、「多クラス」とは「多くの種類」を意味します

一方、先ほど見た「犬」「猫」のような2種類の識別は、「二値分類」もしくは「2クラス分類」と呼びます

「多クラス分類」により、たった10種類の手書き文字だけで無く、1,000種類の動物や無機物を識別する … といった使い方もできます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/5dc13f5c-d55f-8108-8c43-06b41286cede.png)

こうして「人物認識」や「表情からの感情分析」、「自動運転」といった複雑なタスクも実現可能となる訳です

また、ここでの例では、主に画像識別を扱いましたが、画像だけに限らず、音声や自然言語など、様々な領域でMLが利用できます

そして、こうしたことを実現するプログラムを人間がイチから作らなくて良い … コレが機械学習の凄まじい可能性です

# 機械学習の3つのタイプ

ここまでは、MLによって、どんなことが叶うかを解説しました

次は、学習方法によってMLは以下3種類に大きく分かるという解説です

- ①教師あり学習
- ②教師なし学習
- ③強化学習

ここでは、まず「①教師あり学習」を解説し、その後、教師あり学習のプログラミング演習をしたいと思います

「②教師なし学習」「③強化学習」については、別途、解説します

## ①教師あり学習

入力データに対して、「ラベル」という正解となる出力データを紐付けることで学習するのが「教師あり学習」です

たとえば、「犬」や「猫」の学習は、下図のⅰ）にあるように、「犬」や「猫」の画像データと、その画像データに紐付く「0」や「1」の「ラベル」を投入することで学習をさせます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/a44cd6e9-9400-f2ba-e683-ef56171cb531.png)

学習が終わったら、ⅱ）の検証データである「犬」や「猫」の画像データによってMLに予測（識別）をさせ、それが「ラベル」と合っているかをもって精度の評価を行います

ⅱ）で問題無かったら、ⅲ）の未知データを投入し、「犬」か「猫」を識別させ、それが人の判断と同じであれば、期待通りに識別ができているということになります

# 事前準備

## LivebookをローカルPCで起動

開発には、Livebookを使用するので、下記コマンドでLivebook最新版をインストールし、起動します

```
echo y | mix escript.install hex livebook
echo 'export PATH=$HOME/.mix/escripts:$PATH' >> ~/.bashrc
source ~/.bashrc
livebook server
```

もし上手くいかない場合は、下記をお試しください

```
git clone https://github.com/livebook-dev/livebook.git
cd livebook
mix deps.get --only prod
MIX_ENV=prod mix phx.server
```

下記のように待ち受けログが出れば、起動成功です

```
[Livebook] Application running at http://localhost:8080/?token=a55u2laaty53acnvyokw27ucjx7yrjfu
```

上記ログに書かれたURLをブラウザでアクセスすると、下記のような画面が表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/0ad25bcc-8671-ce89-9fab-46bcb3486ceb.png)

「New notebook」を開くと、下記画面が表示され、ここでElixirコードを実行することが出来ます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/848d2154-d32a-60ac-041c-801b1c3b1077.png)

## NxをLivebookで使えるようにする

まず、Pythonで言うところのNumPyと同様の行列計算ライブラリ「Nx」をLivebookで使ってみます

通常のElixir／Phoenixプロジェクトであれば、mix.exsのdepsにライブラリを追加することで対応しますが、Livebookの場合は、ライブラリ追加もノートブック上で行えます

下記コードをLivebook上の「Notebook dependencies and setup」をクリックすると現れるコードブロック（≒Elixirコードを入力する枠）に入力し、「Evaluate」ボタンをクリックするか、「Ctrl」＋「Enter」キーで実行してください

```elixir:※最上部「Notebook dependencies and setup」に入力
Mix.install([
  {:nx, "~> 0.4"}
])
```

実行した画面は、以下のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/325fd142-2965-a5a0-938f-358db50e5b25.png)

その後、Livebook上で「+Code」ボタンをクリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/6bcef92b-d009-136a-15fd-b71fac8324f8.png)

すると、下記のように、コードブロックが追加されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/d59a31db-d6cb-9520-9bd1-74f066866638.png)

ここに、下記コードを書いて、実行してみましょう

```elixir:Livebook上
Nx.tensor([[1, 2], [3, 4]])
|> Nx.divide(3)
```

このコードは、下記のような行列を``Nx.tensor()``で作り、各値を3で除算するというNxのコードです

```math
\begin{bmatrix}
1 & 2 \\
3 & 4
\end{bmatrix}
```

下図のように実行できれば成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/00cf3da5-9a39-a5e5-e8eb-0483a56a2d08.png)

# 教師あり学習のElixirでの実践

それでは、実際に教師あり学習をElixirで体験してみましょう

ここではカンタンな題材として、ビット演算などで使う「OR」を「教師あり」学習させて、予測させてみます

ORは、下記のビット演算を行います

入力1 | 入力2 | 出力
-|-|-
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 1

ラベルは、入力1と入力2のOR演算を行えば計算できるため、教師あり学習のためのラベルの準備を手作業で行わなくて済むため、ラクができます

## OR学習／予測で行うことの構成と流れ

「教師あり」学習は、以下4つのステップで構成されています

うちOR学習／予測では、「ⅲ）検証データによる評価」を割愛します（ココはORの次の課題で扱います）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/ab9103d2-d861-68ca-829c-3e0fdf406e77.png)

以降のコード解説では、各ステップ毎にコードを分けます

## 最終的なコード

下記のコードでORの予測が実現できるので、Livebookに打ち込んで、動かしてみてください（次回、OR予測で行うことの構成と流れ、およびコードの各パートの解説をします）

```elixir:※最上部「Notebook dependencies and setup」に入力
Mix.install([
  {:nx, "~> 0.4"}, 
  {:axon, "~> 0.3"},
  {:exla, "~> 0.4"},
  {:table_rex, "~> 3.1"}
])
```

```elixir:ⅰ）学習データの準備
train_datas = Stream.repeatedly(fn -> 
    input1 = Nx.tensor(for _ <- 1..32, do: [Enum.random(0..1)])
    input2 = Nx.tensor(for _ <- 1..32, do: [Enum.random(0..1)])
    label = Nx.logical_or(input1, input2)
    {%{"input1" => input1, "input2" => input2}, label}
  end)
  |> Enum.take(1000)
```

```elixir:ⅱ）モデルの学習
require Axon

input1 = Axon.input("input1", shape: {nil, 1})
input2 = Axon.input("input2", shape: {nil, 1})
model = Axon.concatenate(input1, input2)
  |> Axon.dense(8, activation: :relu)
  |> Axon.dense(1, activation: :sigmoid)

trained_state = model
  |> Axon.Loop.trainer(:binary_cross_entropy, :sgd)
  |> Axon.Loop.metric(:accuracy, "Accuracy")
  |> Axon.Loop.run(train_datas, %{}, epochs: 5, iterations: 1000, compiler: EXLA)
```

```elixir:ⅲ）検証データによる評価
（検証不要で今回は割愛）
```

```elixir:ⅳ）未知データによる予測
Axon.predict(model, trained_state, %{"input1" => Nx.tensor([[0]]), "input2" => Nx.tensor([[0]])})
Axon.predict(model, trained_state, %{"input1" => Nx.tensor([[0]]), "input2" => Nx.tensor([[1]])})
Axon.predict(model, trained_state, %{"input1" => Nx.tensor([[1]]), "input2" => Nx.tensor([[0]])})
Axon.predict(model, trained_state, %{"input1" => Nx.tensor([[1]]), "input2" => Nx.tensor([[1]])})
```

## 未知データによる予測を試す

本コラムでは、ⅰ）～ⅲ）の解説を次回に預け、OR予測の結果のみを見ていくため、「ⅳ）未知データによる予測」を1つずつ実行した結果を解説します、

まず、「0」と「0」の組み合わせですが、ラベルとしては「0」ですが、予測は「0.0612…」という値を出しており、小数点第一位で四捨五入すると「0」と予測されていることが分かります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/e3f7a92c-87f6-7f92-3355-bffdcf1e9130.png)

「0」と「1」の組み合わせは、ラベルは「1」ですが、予測は「0.9939…」で、小数点第一位で四捨五入すると「1」と予測されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/3f112be7-5b4e-9932-13d3-88aea20dcc0b.png)

「1」と「0」の組み合わせは、ラベルは「1」ですが、予測は「0.9954…」で、小数点第一位で四捨五入すると「1」と予測されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/5b9e7012-5296-5537-ef63-fb2d7b926e1e.png)

「1」と「1」の組み合わせは、ラベルは「1」ですが、予測は「0.9999…」で、小数点第一位で四捨五入すると「1」と予測されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/92153853-8713-cbf9-3d3c-e489c6bda76b.png)

ということで、ORは下記の期待通りの結果が予測されました

入力1 | 入力2 | 出力
-|-|-
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 1

# 今回コラムをマスターすると…

下記コラムシリーズの幾つかを読みこなす基礎知識は身につけていますので、上から拾い読みしてみてください

https://qiita.com/piacerex/items/ccfc7198f08d06433fbc

また、下記イベントをそれなりに楽しめるようにもなったと思います

https://liveviewjp.connpass.com/

https://fukuokaex.connpass.com/

# 終わり

今回は、機械学習の基礎知識を学んだ後、実際にカンタンな「教師あり学習」を実装してみました

Livebook＋Axonを使うことで、Web上で機械学習の開発ができるということが、何となく体験できたでしょうか？

[次回は、OR予測で行うことの構成と流れ、および今回実装したコードの各パート解説になります](https://qiita.com/piacerex/items/96220f6954fc1c6fe718)

# 主催／運営しているElixirコミュニティ紹介

[**1. ElixirImp** : A place to LOVE the buds in Elixir (Elixir実装の芽を愛でる場)
**2. fukuoka.ex** : Fukuoka local Elixir Community (福岡Elixirコミュニティ)
**3. kokura.ex** : Kokura local Elixir Community (小倉Elixirコミュニティ)](https://fukuokaex.connpass.com)

https://fukuokaex.connpass.com

[**4. LiveView JP** : A place to mob-program in LiveView, LiveBook+Nx+Axon, and elixir-desktop](https://liveviewjp.connpass.com)

https://liveviewjp.connpass.com

[**5. Neos.ex** : A place to connecting Elixir and NeosVR to create a new world](https://elixirjp.slack.com/archives/C02J9C12VMF)

---

<h3>:ocean::ocean::ocean: Elixir生誕10周年を一緒にお祝いしませんか？ :ocean::ocean::ocean:</h3>

12/21（水）19:30～21:00、「過去LTいただいた方々への感謝祭」をテーマに、リモート忘年会を開催

「Elixir生誕10周年」に対するコメントや、今／昔のElixirの進化を聞けるチャンスですので、お見逃し無くッ

https://fukuokaex.connpass.com/event/263809/

<font color="#f020a0"><b>※カンパイスタートの会ですので、お酒 or ソフトドリンク、お菓子 or ご飯をお忘れなく</b></font>

<font color="#a020f0"><b>※Zoom接続できれば、本人でも、2Dアバター／3D（VR）アバターでも、お好きな姿でご参加OK</b></font>

日々アップデートされる、Elixir生誕10周年をお祝いするコラム群についての解説もあります（本コラムも、「第3弾「Elixir／Livebook＋NxでPythonっぽくAI・ML」に追加しています）

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf/#%E7%AC%AC3%E5%BC%BEelixirlivebooknx%E3%81%A7python%E3%81%A3%E3%81%BD%E3%81%8Faiml

---

明日は、@the_haigo さんで[「EvisionのDNN.ClassificationModelを使ってクラス分類をする」](https://qiita.com/the_haigo/items/8fdbb80bdff8ff6fd2fc)です