Elixirでディープラーニング①：革新的ライブラリ「Nx」の導入

[ElixirImp／fukuoka.ex／kokura.ex](https://fukuokaex.connpass.com)と[LiveView JP](https://liveviewjp.connpass.com/)の [piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

今回は、Elixirの2021年を占うポジションであるニューラルネットワーク／ディープラーニング用ライブラリ「Nx」を導入してみます

Elixirによる機械学習／ディープラーニングの実現は、[福岡Elixirコミュニティ「fukuoka.ex」](https://fukuokaex.connpass.com/)を設立した半年後の2017年12月頃で、今回のNx以前から、自分達で独自実装を続けてきましたが、今回、「Nx」にその成果がフィードバックされ、Elixir本体実装にて約3年かかった野望を満たせたことになります

そんな革新的ライブラリ「Nx」が出たのが2021年2月18日 … つまり昨日なので、恐らく国内では一番乗りのコラムです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/c3dabadb-d73b-44fa-994a-c5ec789a592d.png)
https://github.com/elixir-nx/nx/tree/main/nx

内容が、面白かったり、役に立ったら、「LGTM」よろしくお願いします :wink:

<h3>:ocean::ocean::ocean: Advent Calendar、fukuoka.ex1位、Elixir2位達成ヽ(=´▽`=)ﾉ :ocean::ocean::ocean:</h3>

fukuoka.ex Advent Calendar、Webテクノロジーカテゴリで堂々1位 … 各コラムぜひお読みください
https://qiita.com/advent-calendar/2020/fukuokaex
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/8a22a81f-2917-6072-10bd-525e0fc24b75.png)](https://qiita.com/advent-calendar/2020/neosvr_reso)

そして、プログラミング言語カテゴリは、1位がRust、2位がElixir、3位がGoとモダン言語揃い踏みでのトップ3、熱いネー:laughing:
https://qiita.com/advent-calendar/2020/elixir
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/ea185203-c525-c778-dc10-6d2ecc391616.png)](https://qiita.com/advent-calendar/2020/elixir)

# 本コラムの検証環境

本コラムは、以下環境で検証しています（Windowsで実施していますが、Linuxやmacでも動作する想定です）

- Windows 10
- Elixir 1.11.3 　 　　　 ※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1#%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99elixir%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>
- git 2.30.1.windows.1　※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacerex/items/1a9cbcc740ca3707eaec#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%ABpc%E3%81%A7git%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B)</b>

# 「Nx」をWindowsでインストールすると…

まず結論から言うと、Erlangの計算ライブラリ関数 ``:math.acosh`` が呼べずにビルドでコケます:sob:

Windows以外の環境ならコケずに上手くいきそうですが、未検証なので、検証していただける方、本コラムのWindows対策以外を参考にしながら、よろしくお願いします（私メンションを付けてくれたら嬉しい）

さて、そこまでの手順ですが、Elixir PJを作成します

```
> mix new nx_review
> cd nx_review
```

Nxをdepsに追加します

```elixir:mix.exs
defmodule NxReview.MixProject do
  use Mix.Project
…
  defp deps do
    [
      {:nx, "~> 0.1.0-dev", github: "elixir-nx/nx", sparse: "nx"}
    ]
  end
…
```

ライブラリをインストールします

```
$ mix deps.get
```

ビルドすると、下記の通り、コケます

```
$ iex -S mix
==> file_system
Compiling 7 files (.ex)
Generated file_system app
…
==> nx
Compiling 17 files (.ex)

== Compilation error in file lib/nx.ex ==
** (UndefinedFunctionError) function :math.acosh/1 is undefined or private. Did you mean one of:

      * acosh/1

    (stdlib 3.8) :math.acosh(1)
    (stdlib 3.8) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir 1.11.2) lib/code.ex:706: Code.eval_quoted/3
    lib/nx.ex:3496: anonymous fn/2 in :elixir_compiler_11.__MODULE__/1
    (elixir 1.11.2) lib/enum.ex:2181: Enum."-reduce/3-lists^foldl/2-0-"/3
    lib/nx.ex:3488: (module)
could not compile dependency :nx, "mix compile" failed. You can recompile this dependency with "mix deps.compile nx", update it with "mix deps.update nx" or clean it with "mix deps.clean nx"
```

# WSL2からビルドする

下記のコラムにある手順でリビルドし直す、という裏ワザを駆使します:yum:

<b>WSL2でElixir本体のビルドとiexバージョン変更</b>
https://qiita.com/piacerex/items/7abdfbffcc10bb7106d3

WSL2上のElixirがインストールできたら、改めて「Nx」のビルドを行います

ここでは、上記のElixir PJ構築を、``c:\tmp``配下に行った想定で、フォルダ移動を行い、ビルドします

```
$ cd /mnt/c/tmp/nx_review
$ iex -S mix
==> file_system
Compiling 7 files (.ex)
…
==> nx
Compiling 17 files (.ex)
Generated nx app
===> Compiling ranch
…
```

やった、上手く通りました

# 「Nx」をお試しする

早速、iexからNxを試してみましょう

```elixir
iex> matrix = Nx.tensor( [ [ 0.123, 0.456 ], [ 0.789, 1.234 ] ] )
#Nx.Tensor<
  f64[2][2]
  [
    [0.123, 0.456],
    [0.789, 1.234]
  ]
>
iex> matrix
#Nx.Tensor<
  f64[2][2]
  [
    [0.123, 0.456],
    [0.789, 1.234]
  ]
>
```

Nxでは、このように、行列を定義できます

Nxには、微分の機能が入っているので、ディープラーニングの多クラス分類で頻出する「softmax」を作って、コレも試してみましょう

```elixir
iex> Nx.divide( Nx.exp( matrix ), Nx.sum( Nx.exp( matrix ) ) )
#Nx.Tensor<
  f64[2][2]
  [
    [0.135520130365152, 0.18907054376721744],
    [0.26378125835705013, 0.4116280675105804]
  ]
>
```

うむ、イイ感じですねっ:laughing:

# ちなみに

Nxのhexdocは、未だアップされていないため、しばらくはソースコード中のdoctestを見て、アレコレ試してください（下記リンクです）

<b>Nxソースコード</b>
https://github.com/elixir-nx/nx/tree/main/nx/lib

# 最後に

ニューラルネットワーク／ディープラーニング用ライブラリ「Nx」を導入してみました

[次回は、この「Nx」を使った<strike>GPU駆動と、簡単なニューラルネットワークでも開発</strike> GPU駆動の準備](https://qiita.com/piacerex/items/cb369ff43b1504f12d86)してみます

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/67568d54-6584-ad33-77c7-b3b3afe70287.png) や ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/f5b819ef-d655-ef72-294c-b1a9d2c5b563.png) にて、どうぞ応援よろしくお願いします:bow: