LoginSignup
7
4

More than 3 years have passed since last update.

はじめに

  • Elixir楽しんでいますか :bangbang::bangbang::bangbang:
  • 話題のNxを触ってみました
    • 本当に文字通りさわってみただけです
    • 公式のExamplesを写した + 九九(大筋は @kikuyuta 先生のコード例を拝借 :pray::pray_tone1::pray_tone2::pray_tone3::pray_tone4::pray_tone5:)
  • Introducing Nx - José Valim | Lambda Days 2021
  • 2021/02/20(土)に開催されたkokura.ex#18ので成果です
    • @im_miolab さんありがとうございます!
  • 私の使った環境です
    • macOS 10.15.7
    • docker desktop 3.1.0
    • Docker version 20.10.2, build 2291f61

参考

環境構築

.devcontainer

  • 適当なディレクトリに.devcontainerディレクトリをつくってその中に次の2つのファイルを入れてください
.devcontainer/devcontainer.json
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.106.0/containers/elm
{
    "name": "Elixir 1.11",
    "build": {
        "dockerfile": "Dockerfile"
    },

    // Set *default* container specific settings.json values on container create.
    "settings": {
      "terminal.integrated.shell.linux": "/bin/bash"
    },

    // Add the IDs of extensions you want installed when the container is created.
    "extensions": [
      "elixir-lsp.elixir-ls",
    ]

    // Uncomment the next line if you want start specific services in your Docker Compose config.
    // "runServices": [],

    // Uncomment the line below if you want to keep your containers running after VS Code shuts down.
    // "shutdownAction": "none",

    // Use 'postCreateCommand' to run commands after the container is created.
    // "postCreateCommand": "yarn install",

    // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
    // "remoteUser": "node"
  }
.devcontainer/Dockerfile
FROM elixir:1.11

Remote-Containers: Open Folder in Container...

  • 開発環境の展開と同じ要領でさきほどつくった.devcontainerがあるフォルダを選んでください
  • 左下がこんなのになっていれば成功です

スクリーンショット 2021-02-20 12.32.25.png

  • Terminal > New Terminal として、ターミナルを開きます

プロジェクト作成

# mix new hello

Nxの導入

mix.exs
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
      {:nx, "~> 0.1.0-dev", github: "elixir-nx/nx", branch: "main", sparse: "nx"}
    ]
  end
end

  • 2021/2/20時点はこんな感じです
    • おそらく今後は、hexのほうにも登録されてもっと簡単な指定方法ですむようになるとおもいます
  • mix.exsを書き換えたらターミナルで以下のコマンドをうって、Nxを導入します
# cd hello
# mix deps.get

Run

  • 私は現段階ではAI?、ML?、TensorFlow?の区別すらよくわかっていないのでとりあえず写しただけです

Examplesを写してみます

# iex -S mix
  • リンク先と同じですので割愛です
lib/my_module.ex
defmodule MyModule do
  import Nx.Defn

  defn softmax(t) do
    Nx.exp(t) / Nx.sum(Nx.exp(t))
  end
end
  • そのまま写して、
iex> recompile
:ok

iex> MyModule.softmax 1
#Nx.Tensor<
  f64
  1.0
>
  • これでいいのかな

九九

  • 大筋は @kikuyuta 先生のコード例を拝借です :pray::pray_tone1::pray_tone2::pray_tone3::pray_tone4::pray_tone5:
iex> IEx.configure(inspect: [limit: :infinity])
:ok

iex> s = Enum.map(1..9, &List.duplicate(&1, 9)) |> Nx.tensor()
#Nx.Tensor<
  s64[9][9]
  [
    [1, 1, 1, 1, 1, 1, 1, 1, 1],
    [2, 2, 2, 2, 2, 2, 2, 2, 2],
    [3, 3, 3, 3, 3, 3, 3, 3, 3],
    [4, 4, 4, 4, 4, 4, 4, 4, 4],
    [5, 5, 5, 5, 5, 5, 5, 5, 5],
    [6, 6, 6, 6, 6, 6, 6, 6, 6],
    [7, 7, 7, 7, 7, 7, 7, 7, 7], 
    [8, 8, 8, 8, 8, 8, 8, 8, 8],
    [9, 9, 9, 9, 9, 9, 9, 9, 9]
  ]
>

iex> t = Nx.transpose(s)
#Nx.Tensor<
  s64[9][9]
  [
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9], 
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
  ]
>

iex> Nx.multiply(s,t)
#Nx.Tensor<
  s64[9][9]
  [
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [2, 4, 6, 8, 10, 12, 14, 16, 18],
    [3, 6, 9, 12, 15, 18, 21, 24, 27],
    [4, 8, 12, 16, 20, 24, 28, 32, 36],
    [5, 10, 15, 20, 25, 30, 35, 40, 45],
    [6, 12, 18, 24, 30, 36, 42, 48, 54],
    [7, 14, 21, 28, 35, 42, 49, 56, 63],
    [8, 16, 24, 32, 40, 48, 56, 64, 72],
    [9, 18, 27, 36, 45, 54, 63, 72, 81]
  ]
>

Nxを使わない例

for/1をつかって

iex> for(x <- 1..9, y <- 1..9, do: x * y) |> Enum.chunk_every(9)
[
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [2, 4, 6, 8, 10, 12, 14, 16, 18],
  [3, 6, 9, 12, 15, 18, 21, 24, 27],
  [4, 8, 12, 16, 20, 24, 28, 32, 36],
  [5, 10, 15, 20, 25, 30, 35, 40, 45],
  [6, 12, 18, 24, 30, 36, 42, 48, 54],
  [7, 14, 21, 28, 35, 42, 49, 56, 63],
  [8, 16, 24, 32, 40, 48, 56, 64, 72],
  [9, 18, 27, 36, 45, 54, 63, 72, 81]
]

Enum.reduce/3をつかって

iex> (
...> Enum.reduce(1..9, [], fn i, acc ->
...>   [ Enum.map(1..9, & &1 * i) ] |> Kernel.++(acc)
...> end)
...> |> Enum.reverse()
...> )
[
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [2, 4, 6, 8, 10, 12, 14, 16, 18],
  [3, 6, 9, 12, 15, 18, 21, 24, 27],
  [4, 8, 12, 16, 20, 24, 28, 32, 36],
  [5, 10, 15, 20, 25, 30, 35, 40, 45],
  [6, 12, 18, 24, 30, 36, 42, 48, 54],
  [7, 14, 21, 28, 35, 42, 49, 56, 63],
  [8, 16, 24, 32, 40, 48, 56, 64, 72],
  [9, 18, 27, 36, 45, 54, 63, 72, 81]
]

Nxをつかわずに

iex> s = Enum.map(1..9, &List.duplicate(&1, 9))                                                           
[                                        
  [1, 1, 1, 1, 1, 1, 1, 1, 1],
  [2, 2, 2, 2, 2, 2, 2, 2, 2],
  [3, 3, 3, 3, 3, 3, 3, 3, 3],
  [4, 4, 4, 4, 4, 4, 4, 4, 4],
  [5, 5, 5, 5, 5, 5, 5, 5, 5],
  [6, 6, 6, 6, 6, 6, 6, 6, 6],
  '\a\a\a\a\a\a\a\a\a',
  '\b\b\b\b\b\b\b\b\b',
  '\t\t\t\t\t\t\t\t\t'
]

# Nx.transpose/1 相当
iex> t = List.zip(s) |> Enum.map(&Tuple.to_list/1)                                                        
[                                        
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [1, 2, 3, 4, 5, 6, 7, 8, 9]
]

# Nx.multiply/2相当
iex> (
...> Enum.zip(s, t)
...> |> Enum.map(fn {list1, list2} -> Enum.zip(list1, list2) end)
...> |> Enum.map(&Enum.map(&1, fn {a, b} -> a * b end))
...> )
[
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [2, 4, 6, 8, 10, 12, 14, 16, 18],
  [3, 6, 9, 12, 15, 18, 21, 24, 27],
  [4, 8, 12, 16, 20, 24, 28, 32, 36],
  [5, 10, 15, 20, 25, 30, 35, 40, 45],
  [6, 12, 18, 24, 30, 36, 42, 48, 54],
  [7, 14, 21, 28, 35, 42, 49, 56, 63],
  [8, 16, 24, 32, 40, 48, 56, 64, 72],
  [9, 18, 27, 36, 45, 54, 63, 72, 81]
]

Wrapping Up :lgtm::lgtm::lgtm::lgtm::lgtm:

  • とりあえず触ってみました
    • 触ってみただけです
    • 雰囲気すごそうな感じはしています
    • まだみなさんと語り合うレベルにはないので周辺知識とかをつけていきたいと強く感じました
    • 九九という簡単な例ですが、素のElixirだとなんだかこねくり回した感じでしか書けそうにないものをNx.transposeとかNx.multiplyとかで
    • $\huge{必殺技}$
    • っぽく書けそうで理解を深めていきたいです
  • Enjoy Elixir :rocket::rocket::rocket::rocket::rocket:
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4