概要
paiza.ioでelixirやってみた。
練習問題やってみた。
練習問題
qiita apiを叩け。
サンプルコード
:inets.start
:ssl.start
{:ok, {_status, _headers, body}} = :httpc.request('https://qiita.com/api/v2/items?query=elixir')
body = IO.iodata_to_binary(body)
body = String.replace(body, "\\u003c", "<")
body = String.replace(body, "\\u003e", ">")
IO.puts(body)
実行結果
[{"rendered_body":"<h1 data-sourcepos=\"1:1-1:8\">\n<span id=\"概要\" class=\"fragment\"></span><a href=\"#%E6%A6%82%E8%A6%81\"><i class=\"fa fa-link\"></i></a>概要</h1>\n<p data-sourcepos=\"2:1-3:24\">paiza.ioでelixirやってみた。<br>\nString使ってみた。</p>\n<h1 data-sourcepos=\"5:1-5:23\">\n<span id=\"サンプルコード\" class=\"fragment\"></span><a href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89\"><i class=\"fa fa-link\"></i></a>サンプルコード</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"7:1-119:3\"><div class=\"highlight\"><pre><code>String.at(\"elixir\", 1)\n|\u0026gt; IO.puts\nString.bag_distance(\"abcd\", \"abc\")\n|\u0026gt; IO.puts\nString.capitalize(\"fin\")\n|\u0026gt; IO.puts\nString.chunk(\u0026lt;\u0026lt;?a, ?b, ?c, 0\u0026gt;\u0026gt;, :valid)\n|\u0026gt; IO.puts\nString.codepoints(\"\<\")\n|\u0026gt; IO.puts\nString.contains?(\"elixir of life\", \"of\")\n|\u0026gt; IO.puts\nString.downcase(\"ABCD\")\n|\u0026gt; IO.puts\nString.duplicate(\"abc\", 2)\n|\u0026gt; IO.puts\nString.ends_with?(\"language\", \"age\")\n|\u0026gt; IO.puts\nString.equivalent?(\"abc\", \"abc\")\n|\u0026gt; IO.puts\nString.first(\"elixir\")\n|\u0026gt; IO.puts\nString.graphemes(\"\>\")\n|\u0026gt; IO.puts\nString.jaro_distance(\"Dwayne\", \"Duane\")\n|\u0026gt; IO.puts\nString.last(\"elixir\")\n|\u0026gt; IO.puts\nString.length(\"elixir\")\n|\u0026gt; IO.puts\nString.match?(\"foo\", ~r/foo/)\n|\u0026gt; IO.puts\nstring1 = \"fox hops over the dog\"\nstring2 = \"fox jumps over the lazy cat\"\nString.myers_difference(string1, string2)\n|\u0026gt; IO.inspect\nString.next_codepoint(\"olá\")\n|\u0026gt; IO.inspect\nString.next_grapheme(\"olá\")\n|\u0026gt; IO.inspect\nString.next_grapheme_size(\"olá\")\n|\u0026gt; IO.inspect\nString.normalize(\"fi\", :nfkc)\n|\u0026gt; IO.puts\nString.pad_leading(\"abc\", 5)\n|\u0026gt; IO.puts\nString.pad_trailing(\"abc\", 5)\n|\u0026gt; IO.puts\nString.printable?(\"abc\")\n|\u0026gt; IO.puts\nString.replace(\"a,b,c\", \",\", \"-\")\n|\u0026gt; IO.puts\nString.replace_leading(\"hello world\", \"hello \", \"hi \")\n|\u0026gt; IO.puts\nString.replace_prefix(\"world\", \"hello \", \"\")\n|\u0026gt; IO.puts\nString.replace_suffix(\"hello\", \" world\", \"\")\n|\u0026gt; IO.puts\nString.replace_trailing(\"hello world\", \" world\", \"\")\n|\u0026gt; IO.puts\nString.reverse(\"abcd\")\n|\u0026gt; IO.puts\nString.slice(\"elixir\", 1..3)\n|\u0026gt; IO.puts\nString.slice(\"elixir\", 1, 3)\n|\u0026gt; IO.puts\nString.split(\"foo bar\")\n|\u0026gt; IO.inspect\nString.split(\"a,b,c\", \",\")\n|\u0026gt; IO.inspect\nString.split_at(\"sweetelixir\", 5)\n|\u0026gt; IO.inspect\nString.splitter(\"1,2 3,4 5,6 7,8,...,99999\", [\" \", \",\"]) \n|\u0026gt; Enum.take(4)\n|\u0026gt; IO.inspect\nString.starts_with?(\"elixir\", \"eli\")\n|\u0026gt; IO.puts\nString.to_atom(\"my_atom\")\n|\u0026gt; IO.puts\nString.to_charlist(\"æß\")\n|\u0026gt; IO.puts\n_ = :my_atom\nString.to_existing_atom(\"my_atom\")\n|\u0026gt; IO.puts\nString.to_float(\"2.2017764e+0\")\n|\u0026gt; IO.puts\nString.to_integer(\"123\")\n|\u0026gt; IO.puts\nString.to_integer(\"3FF\", 16)\n|\u0026gt; IO.puts\nString.trim(\"\\n abc\\n \")\n|\u0026gt; IO.puts\nString.trim(\"a abc a\", \"a\")\n|\u0026gt; IO.puts\nString.trim_leading(\"\\n abc \")\n|\u0026gt; IO.puts\nString.trim_leading(\"__ abc _\", \"_\")\n|\u0026gt; IO.puts\nString.trim_trailing(\" abc\\n \")\n|\u0026gt; IO.puts\nString.trim_trailing(\"_ abc __\", \"_\")\n|\u0026gt; IO.puts\nString.upcase(\"abcd\")\n|\u0026gt; IO.puts\nString.valid?(\"a\")\n|\u0026gt; IO.puts\n\n\n\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"121:1-121:14\">\n<span id=\"実行結果\" class=\"fragment\"></span><a href=\"#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C\"><i class=\"fa fa-link\"></i></a>実行結果</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"123:1-184:3\"><div class=\"highlight\"><pre><code>l\n0.75\nFin\nabc\n\u0026lt;\ntrue\nabcd\nabcabc\ntrue\ntrue\ne\n\u0026gt;\n0.8222222222222223\nr\n6\ntrue\n[\n eq: \"fox \",\n del: \"ho\",\n ins: \"jum\",\n eq: \"ps over the \",\n del: \"dog\",\n ins: \"lazy cat\"\n]\n{\"o\", \"lá\"}\n{\"o\", \"lá\"}\n{1, \"lá\"}\nfi\n abc\nabc \ntrue\na-b-c\nhi world\nworld\nhello\nhello\ndcba\nlix\nlix\n[\"foo\", \"bar\"]\n[\"a\", \"b\", \"c\"]\n{\"sweet\", \"elixir\"}\n[\"1\", \"2\", \"3\", \"4\"]\ntrue\nmy_atom\næß\nmy_atom\n2.2017764\n123\n1023\nabc\n abc \nabc \n abc _\n abc\n_ abc \nABCD\ntrue\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"186:1-186:11\">\n<span id=\"成果物\" class=\"fragment\"></span><a href=\"#%E6%88%90%E6%9E%9C%E7%89%A9\"><i class=\"fa fa-link\"></i></a>成果物</h1>\n<p data-sourcepos=\"189:1-189:48\"><qiita-embed-ogp src=\"https://paiza.io/projects/9T4V-7yjixjrX1gFTG2ovg\"></qiita-embed-ogp></p>\n<p data-sourcepos=\"192:1-192:9\">以上。</p>\n","body":"# 概要\npaiza.ioでelixirやってみた。\nString使ってみた。\n\n# サンプルコード\n\n```\nString.at(\"elixir\", 1)\n|> IO.puts\nString.bag_distance(\"abcd\", \"abc\")\n|> IO.puts\nString.capitalize(\"fin\")\n|> IO.puts\nString.chunk(<<?a, ?b, ?c, 0>>, :valid)\n|> IO.puts\nString.codepoints(\"\<\")\n|> IO.puts\nString.contains?(\"elixir of life\", \"of\")\n|> IO.puts\nString.downcase(\"ABCD\")\n|> IO.puts\nString.duplicate(\"abc\", 2)\n|> IO.puts\nString.ends_with?(\"language\", \"age\")\n|> IO.puts\nString.equivalent?(\"abc\", \"abc\")\n|> IO.puts\nString.first(\"elixir\")\n|> IO.puts\nString.graphemes(\"\>\")\n|> IO.puts\nString.jaro_distance(\"Dwayne\", \"Duane\")\n|> IO.puts\nString.last(\"elixir\")\n|> IO.puts\nString.length(\"elixir\")\n|> IO.puts\nString.match?(\"foo\", ~r/foo/)\n|> IO.puts\nstring1 = \"fox hops over the dog\"\nstring2 = \"fox jumps over the lazy cat\"\nString.myers_difference(string1, string2)\n|> IO.inspect\nString.next_codepoint(\"olá\")\n|> IO.inspect\nString.next_grapheme(\"olá\")\n|> IO.inspect\nString.next_grapheme_size(\"olá\")\n|> IO.inspect\nString.normalize(\"fi\", :nfkc)\n|> IO.puts\nString.pad_leading(\"abc\", 5)\n|> IO.puts\nString.pad_trailing(\"abc\", 5)\n|> IO.puts\nString.printable?(\"abc\")\n|> IO.puts\nString.replace(\"a,b,c\", \",\", \"-\")\n|> IO.puts\nString.replace_leading(\"hello world\", \"hello \", \"hi \")\n|> IO.puts\nString.replace_prefix(\"world\", \"hello \", \"\")\n|> IO.puts\nString.replace_suffix(\"hello\", \" world\", \"\")\n|> IO.puts\nString.replace_trailing(\"hello world\", \" world\", \"\")\n|> IO.puts\nString.reverse(\"abcd\")\n|> IO.puts\nString.slice(\"elixir\", 1..3)\n|> IO.puts\nString.slice(\"elixir\", 1, 3)\n|> IO.puts\nString.split(\"foo bar\")\n|> IO.inspect\nString.split(\"a,b,c\", \",\")\n|> IO.inspect\nString.split_at(\"sweetelixir\", 5)\n|> IO.inspect\nString.splitter(\"1,2 3,4 5,6 7,8,...,99999\", [\" \", \",\"]) \n|> Enum.take(4)\n|> IO.inspect\nString.starts_with?(\"elixir\", \"eli\")\n|> IO.puts\nString.to_atom(\"my_atom\")\n|> IO.puts\nString.to_charlist(\"æß\")\n|> IO.puts\n_ = :my_atom\nString.to_existing_atom(\"my_atom\")\n|> IO.puts\nString.to_float(\"2.2017764e+0\")\n|> IO.puts\nString.to_integer(\"123\")\n|> IO.puts\nString.to_integer(\"3FF\", 16)\n|> IO.puts\nString.trim(\"\\n abc\\n \")\n|> IO.puts\nString.trim(\"a abc a\", \"a\")\n|> IO.puts\nString.trim_leading(\"\\n abc \")\n|> IO.puts\nString.trim_leading(\"__ abc _\", \"_\")\n|> IO.puts\nString.trim_trailing(\" abc\\n \")\n|> IO.puts\nString.trim_trailing(\"_ abc __\", \"_\")\n|> IO.puts\nString.upcase(\"abcd\")\n|> IO.puts\nString.valid?(\"a\")\n|> IO.puts\n\n\n\n\n\n```\n\n# 実行結果\n\n```\nl\n0.75\nFin\nabc\n<\ntrue\nabcd\nabcabc\ntrue\ntrue\ne\n>\n0.8222222222222223\nr\n6\ntrue\n[\n eq: \"fox \",\n del: \"ho\",\n ins: \"jum\",\n eq: \"ps over the \",\n del: \"dog\",\n ins: \"lazy cat\"\n]\n{\"o\", \"lá\"}\n{\"o\", \"lá\"}\n{1, \"lá\"}\nfi\n abc\nabc \ntrue\na-b-c\nhi world\nworld\nhello\nhello\ndcba\nlix\nlix\n[\"foo\", \"bar\"]\n[\"a\", \"b\", \"c\"]\n{\"sweet\", \"elixir\"}\n[\"1\", \"2\", \"3\", \"4\"]\ntrue\nmy_atom\næß\nmy_atom\n2.2017764\n123\n1023\nabc\n abc \nabc \n abc _\n abc\n_ abc \nABCD\ntrue\n\n\n```\n\n# 成果物\n\n\nhttps://paiza.io/projects/9T4V-7yjixjrX1gFTG2ovg\n\n\n以上。\n","coediting":false,"comments_count":0,"created_at":"2022-11-09T18:39:03+09:00","group":null,"id":"6220926a1478a09e94e2","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Elixir","versions":[]},{"name":"paiza.IO","versions":[]}],"title":"paiza.ioでelixir その54","updated_at":"2022-11-09T18:39:03+09:00","url":"https://qiita.com/ohisama@github/items/6220926a1478a09e94e2","user":{"description":null,"facebook_id":null,"followees_count":0,"followers_count":59,"github_login_name":"ohisama","id":"ohisama@github","items_count":3006,"linkedin_id":null,"location":null,"name":"","organization":null,"permanent_id":18104,"profile_image_url":"https://secure.gravatar.com/avatar/2e0bb506fbe90e6572bf92fa05db88d3?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","team_only":false,"twitter_screen_name":null,"website_url":null},"page_views_count":null,"team_membership":null},{"rendered_body":"<p data-sourcepos=\"2:1-3:68\">Axon で、以下のドキュメントに沿って、機械学習を試してみました。<br>\n<a href=\"https://hexdocs.pm/axon/mnist.html\" rel=\"nofollow noopener\" target=\"_blank\">Classifying handwritten digits</a></p>\n<p data-sourcepos=\"6:1-7:145\">ちなみに機械学習はGPUパワーなしには無理なので、以下の方法で Livebook の起動を行いました。大変助かりました。<br>\n<a href=\"https://qiita.com/RyoWakabayashi/items/113b94866780c7646af1\" id=\"reference-e761ed0f1ec2a3869491\">Google Colaboratory 上で Elixir Livebook を動かす(GPUを無料で使う)</a></p>\n<p data-sourcepos=\"10:1-13:126\"><strong>関連記事</strong><br>\n<a href=\"https://qiita.com/sand/items/9a47cfe0c95386417224\" id=\"reference-896ebc7b4cca57353945\">Elixir Nx の基礎 (Livebook) - Qitta</a><br>\n<a href=\"https://qiita.com/sand/items/6753c1782774b45daf6b\" id=\"reference-95ee1c7dd2e9033706d0\">Livebook 事始め (Elixir) - Qiita</a><br>\n<a href=\"https://qiita.com/sand/items/2d783a12c575fb949c6e\" id=\"reference-c2a8a6a3417d3eaec881\">【機械学習】誤差逆伝播法のコンパクトな説明 - Qiita</a></p>\n<h1 data-sourcepos=\"16:1-16:40\">\n<span id=\"1訓練データの取得と正規化\" class=\"fragment\"></span><a href=\"#1%E8%A8%93%E7%B7%B4%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%8F%96%E5%BE%97%E3%81%A8%E6%AD%A3%E8%A6%8F%E5%8C%96\"><i class=\"fa fa-link\"></i></a>1.訓練データの取得と正規化</h1>\n<h2 data-sourcepos=\"18:1-18:35\">\n<span id=\"1-1-必要なインストール\" class=\"fragment\"></span><a href=\"#1-1-%E5%BF%85%E8%A6%81%E3%81%AA%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB\"><i class=\"fa fa-link\"></i></a>1-1. 必要なインストール</h2>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"21:1-28:3\"><div class=\"highlight\"><pre><code><span class=\"no\">Mix</span><span class=\"o\">.</span><span class=\"n\">install</span><span class=\"p\">([</span>\n <span class=\"p\">{</span><span class=\"ss\">:axon</span><span class=\"p\">,</span> <span class=\"ss\">github:</span> <span class=\"s2\">\"elixir-nx/axon\"</span><span class=\"p\">},</span>\n <span class=\"p\">{</span><span class=\"ss\">:nx</span><span class=\"p\">,</span> <span class=\"s2\">\"~\u0026gt; 0.4\"</span><span class=\"p\">},</span>\n <span class=\"p\">{</span><span class=\"ss\">:exla</span><span class=\"p\">,</span> <span class=\"s2\">\"~\u0026gt; 0.4\"</span><span class=\"p\">},</span>\n <span class=\"p\">{</span><span class=\"ss\">:req</span><span class=\"p\">,</span> <span class=\"s2\">\"~\u0026gt; 0.3.0\"</span><span class=\"p\">}</span>\n<span class=\"p\">])</span>\n</code></pre></div></div>\n<h2 data-sourcepos=\"32:1-32:32\">\n<span id=\"1-2-訓練データの取得\" class=\"fragment\"></span><a href=\"#1-2-%E8%A8%93%E7%B7%B4%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%8F%96%E5%BE%97\"><i class=\"fa fa-link\"></i></a>1-2. 訓練データの取得</h2>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"34:1-41:3\"><div class=\"highlight\"><pre><code><span class=\"n\">base_url</span> <span class=\"o\">=</span> <span class=\"s2\">\"https://storage.googleapis.com/cvdf-datasets/mnist/\"</span>\n<span class=\"p\">%{</span><span class=\"ss\">body:</span> <span class=\"n\">train_images</span><span class=\"p\">}</span> <span class=\"o\">=</span> <span class=\"no\">Req</span><span class=\"o\">.</span><span class=\"n\">get!</span><span class=\"p\">(</span><span class=\"n\">base_url</span> <span class=\"o\">\u0026lt;\u0026gt;</span> <span class=\"s2\">\"train-images-idx3-ubyte.gz\"</span><span class=\"p\">)</span>\n<span class=\"p\">%{</span><span class=\"ss\">body:</span> <span class=\"n\">train_labels</span><span class=\"p\">}</span> <span class=\"o\">=</span> <span class=\"no\">Req</span><span class=\"o\">.</span><span class=\"n\">get!</span><span class=\"p\">(</span><span class=\"n\">base_url</span> <span class=\"o\">\u0026lt;\u0026gt;</span> <span class=\"s2\">\"train-labels-idx1-ubyte.gz\"</span><span class=\"p\">)</span>\n\n<span class=\"o\">\u0026lt;\u0026lt;</span><span class=\"n\">_</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_images</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_rows</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_cols</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">images</span><span class=\"p\">::</span><span class=\"n\">binary</span><span class=\"o\">\u0026gt;\u0026gt;</span> <span class=\"o\">=</span> <span class=\"n\">train_images</span>\n<span class=\"o\">\u0026lt;\u0026lt;</span><span class=\"n\">_</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_labels</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">labels</span><span class=\"p\">::</span><span class=\"n\">binary</span><span class=\"o\">\u0026gt;\u0026gt;</span> <span class=\"o\">=</span> <span class=\"n\">train_labels</span>\n</code></pre></div></div>\n<p data-sourcepos=\"44:1-45:92\">train_images、 を4個のヘッダー(32ビット)部分と本体(images)に分解してます。<br>\ntrain_labels も2個のヘッダー(32ビット)部分と本体(labels)に分解します。</p>\n<div data-sourcepos=\"47:1-56:3\" class=\"note warn\">\n<span class=\"fa fa-fw fa-exclamation-circle\"></span><div>\n<p data-sourcepos=\"48:1-48:77\">Elixir では <strong>\u0026lt;\u0026lt;\u0026gt;\u0026gt;</strong> を使って <strong>バイナリ</strong> を定義できます。</p>\n<p data-sourcepos=\"50:1-53:1\">iex\u0026gt; \u0026lt;\u0026lt;0, 1, 2, 3\u0026gt;\u0026gt;<br>\n\u0026lt;\u0026lt;0, 1, 2, 3\u0026gt;\u0026gt;<br>\niex\u0026gt; byte_size(\u0026lt;\u0026lt;0, 1, 2, 3\u0026gt;\u0026gt;)<br>\n4</p>\n<p data-sourcepos=\"55:1-55:58\"><strong>バイナリとはバイトのシーケンスです。</strong></p>\n</div>\n</div>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"59:1-62:3\"><div class=\"highlight\"><pre><code><span class=\"o\">\u0026lt;\u0026lt;</span><span class=\"n\">_</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_images</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_rows</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_cols</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">images</span><span class=\"p\">::</span><span class=\"n\">binary</span><span class=\"o\">\u0026gt;\u0026gt;</span> <span class=\"o\">=</span> <span class=\"n\">train_images</span>\n<span class=\"o\">\u0026lt;\u0026lt;</span><span class=\"n\">_</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">n_labels</span><span class=\"p\">::</span><span class=\"mi\">32</span><span class=\"p\">,</span> <span class=\"n\">labels</span><span class=\"p\">::</span><span class=\"n\">binary</span><span class=\"o\">\u0026gt;\u0026gt;</span> <span class=\"o\">=</span> <span class=\"n\">train_labels</span>\n</code></pre></div></div>\n<p data-sourcepos=\"64:1-64:120\"><a href=\"https://camo.qiitausercontent.com/63e54aacc4167aa3434fde2c517d86c28f5a88a3/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f36313931352f36313837636662342d313961332d333432352d646536322d6538616537623030396366652e706e67\" target=\"_blank\" rel=\"nofollow noopener\"><img src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F61915%2F6187cfb4-19a3-3425-de62-e8ae7b009cfe.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=82be30734becba5a200acdfa4ed766d5\" alt=\"image.png\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/6187cfb4-19a3-3425-de62-e8ae7b009cfe.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F61915%2F6187cfb4-19a3-3425-de62-e8ae7b009cfe.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=35ded1ffa5765c53778ed614b17394ea 1x\" loading=\"lazy\"></a></p>\n<p data-sourcepos=\"66:1-66:373\">イメージ数もラベル数(解答数)も60000個です。つまり1個の数字で 28<em>28 Byte使用しているので、全体のイメージの byte 数は 28</em>28*60000 = 47040000 となります。画像の1ドットは <strong>0 ~ 255</strong> の整数値で表され、1 byte 使用することに注意してください。画素の色の濃淡を表現しています。</p>\n<h2 data-sourcepos=\"69:1-69:35\">\n<span id=\"1-3-訓練データの正規化\" class=\"fragment\"></span><a href=\"#1-3-%E8%A8%93%E7%B7%B4%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E6%AD%A3%E8%A6%8F%E5%8C%96\"><i class=\"fa fa-link\"></i></a>1-3. 訓練データの正規化</h2>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"71:1-77:3\"><div class=\"highlight\"><pre><code><span class=\"n\">images</span> <span class=\"o\">=</span>\n <span class=\"n\">images</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">from_binary</span><span class=\"p\">({</span><span class=\"ss\">:u</span><span class=\"p\">,</span> <span class=\"mi\">8</span><span class=\"p\">})</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">reshape</span><span class=\"p\">({</span><span class=\"n\">n_images</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"n\">n_rows</span><span class=\"p\">,</span> <span class=\"n\">n_cols</span><span class=\"p\">},</span> <span class=\"ss\">names:</span> <span class=\"p\">[</span><span class=\"ss\">:images</span><span class=\"p\">,</span> <span class=\"ss\">:channels</span><span class=\"p\">,</span> <span class=\"ss\">:height</span><span class=\"p\">,</span> <span class=\"ss\">:width</span><span class=\"p\">])</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">divide</span><span class=\"p\">(</span><span class=\"mi\">255</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<div data-sourcepos=\"79:1-90:3\" class=\"note info\">\n<span class=\"fa fa-fw fa-check-circle\"></span><div>\n<p data-sourcepos=\"80:1-80:23\"><strong>Tensor の正規化</strong></p>\n<ul data-sourcepos=\"81:1-89:157\">\n<li data-sourcepos=\"81:1-84:0\">\n<p data-sourcepos=\"81:3-83:231\">Nx.from_binary(images, {:u, 8})<br>\nbinary(=images) から、与えられた型の 1次元 tensor を作ります。<br>\n<strong>Nx tensors</strong> は <strong>unsigned integers</strong> (<strong>u8, u16, u32, u64</strong>) や <strong>signed integers</strong> (<strong>s8, s16, s32, s64</strong>)、 <strong>floats</strong> (<strong>f32, f64</strong>)、 <strong>brain floats</strong> (<strong>bf16</strong>)、 <strong>complex</strong> (<strong>c64, c128</strong>) の値を保持します。</p>\n</li>\n<li data-sourcepos=\"85:1-87:0\">\n<p data-sourcepos=\"85:3-86:74\">Nx.reshape(x, {n_images, 1, n_rows, n_cols}, names: [:images, :channels, :height, :width])<br>\n1次元 tensor を、意味のある次元の tensor に変形します。</p>\n</li>\n<li data-sourcepos=\"88:1-89:157\">\n<p data-sourcepos=\"88:3-89:157\">Nx.divide(255)<br>\ntensor の値は <strong>0~255</strong> の値だから、255 で割ることにより、<strong>0~1</strong> の値に変換します。これを <strong>正規化</strong> と呼びます。</p>\n</li>\n</ul>\n</div>\n</div>\n<p data-sourcepos=\"93:1-93:77\">この結果得られる、images tensor を可視化してみましょう。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"95:1-97:3\"><div class=\"highlight\"><pre><code><span class=\"n\">images</span><span class=\"p\">[[</span><span class=\"ss\">images:</span> <span class=\"mi\">0</span><span class=\"o\">..</span><span class=\"mi\">4</span><span class=\"p\">]]</span> <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">to_heatmap</span><span class=\"p\">()</span>\n</code></pre></div></div>\n<p data-sourcepos=\"99:1-99:139\">画面をうまくキャプチャーできないので残念ですが、いい感じに5個の数字のドット絵が表示されます。</p>\n<p data-sourcepos=\"101:1-101:120\"><a href=\"https://camo.qiitausercontent.com/469b90aa98d4fc7ef1d2219b671de5d935649064/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f36313931352f61383933303730622d616236332d393863342d653062662d6630313161653964646239332e706e67\" target=\"_blank\" rel=\"nofollow noopener\"><img src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F61915%2Fa893070b-ab63-98c4-e0bf-f011ae9ddb93.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=4f04bbe531bbf861d1d94bc654dec2c5\" alt=\"image.png\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/a893070b-ab63-98c4-e0bf-f011ae9ddb93.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F61915%2Fa893070b-ab63-98c4-e0bf-f011ae9ddb93.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=abb0e7b5968bfed3204bac19eb7114b0 1x\" loading=\"lazy\"></a></p>\n<h2 data-sourcepos=\"104:1-104:44\">\n<span id=\"1-4-訓練データのミニバッチ化\" class=\"fragment\"></span><a href=\"#1-4-%E8%A8%93%E7%B7%B4%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E3%83%9F%E3%83%8B%E3%83%90%E3%83%83%E3%83%81%E5%8C%96\"><i class=\"fa fa-link\"></i></a>1-4. 訓練データのミニバッチ化</h2>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"107:1-109:3\"><div class=\"highlight\"><pre><code><span class=\"n\">images</span> <span class=\"o\">=</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">to_batched</span><span class=\"p\">(</span><span class=\"n\">images</span><span class=\"p\">,</span> <span class=\"mi\">32</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"111:1-111:207\">勾配降下法で学習する場合、何件かの訓練データをグループ化し、一気に勾配計算をやると効率的です。これは <strong>ミニバッチ学習法</strong> と呼ばれています。</p>\n<p data-sourcepos=\"113:1-113:82\"><strong>Nx.to_batched(images, 32)</strong> は images を tensor batches に変換します。</p>\n<h2 data-sourcepos=\"115:1-115:72\">\n<span id=\"1-5-labels-の-one-hot-エンコーディングとミニバッチ化\" class=\"fragment\"></span><a href=\"#1-5-labels-%E3%81%AE-one-hot-%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8%E3%83%9F%E3%83%8B%E3%83%90%E3%83%83%E3%83%81%E5%8C%96\"><i class=\"fa fa-link\"></i></a>1-5. labels の one-hot エンコーディングとミニバッチ化</h2>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"117:1-124:3\"><div class=\"highlight\"><pre><code><span class=\"n\">targets</span> <span class=\"o\">=</span>\n <span class=\"n\">labels</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">from_binary</span><span class=\"p\">({</span><span class=\"ss\">:u</span><span class=\"p\">,</span> <span class=\"mi\">8</span><span class=\"p\">})</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">new_axis</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">equal</span><span class=\"p\">(</span><span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">tensor</span><span class=\"p\">(</span><span class=\"no\">Enum</span><span class=\"o\">.</span><span class=\"n\">to_list</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"o\">..</span><span class=\"mi\">9</span><span class=\"p\">)))</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">to_batched</span><span class=\"p\">(</span><span class=\"mi\">32</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"126:1-127:251\">images と同様に、labels も扱いやすいように変換します。<br>\n<strong>one-hot エンコーディング</strong> とは、例えば <strong>3</strong> というスカラー値を、<strong>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]</strong> という 3番目だけ 1 で他は全て 0 のベクトルに変換することです。0 番始まりの 3 番目です。</p>\n<p data-sourcepos=\"131:1-131:78\">大分細かくなりますが、段階的に変換を追っていきます。</p>\n<ul data-sourcepos=\"132:1-133:0\">\n<li data-sourcepos=\"132:1-133:0\">最初の変換です。</li>\n</ul>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"134:1-137:3\"><div class=\"highlight\"><pre><code> <span class=\"n\">labels</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">from_binary</span><span class=\"p\">({</span><span class=\"ss\">:u</span><span class=\"p\">,</span> <span class=\"mi\">8</span><span class=\"p\">})</span>\n</code></pre></div></div>\n<p data-sourcepos=\"139:1-139:67\">Nx.from_binaryで labels を1次元の tensor に変換します。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"141:1-145:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n u8[60000]\n [5, 0, 4, 1,...,] \n</code></pre></div></div>\n<ul data-sourcepos=\"147:1-148:0\">\n<li data-sourcepos=\"147:1-148:0\">次の変換です</li>\n</ul>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"149:1-153:3\"><div class=\"highlight\"><pre><code> <span class=\"n\">labels</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">from_binary</span><span class=\"p\">({</span><span class=\"ss\">:u</span><span class=\"p\">,</span> <span class=\"mi\">8</span><span class=\"p\">})</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">new_axis</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"155:1-155:102\">Nx.new_axis で size 1 の axis を加えます。 -1 引数なので後ろに axis を加えます。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"157:1-167:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n u8[60000][1]\n [\n [5],\n [0],\n [4],\n [1],\n ---\n ]\n</code></pre></div></div>\n<ul data-sourcepos=\"169:1-170:0\">\n<li data-sourcepos=\"169:1-170:0\">次の変換です</li>\n</ul>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"171:1-176:3\"><div class=\"highlight\"><pre><code> <span class=\"n\">labels</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">from_binary</span><span class=\"p\">({</span><span class=\"ss\">:u</span><span class=\"p\">,</span> <span class=\"mi\">8</span><span class=\"p\">})</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">new_axis</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">equal</span><span class=\"p\">(</span><span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">tensor</span><span class=\"p\">(</span><span class=\"no\">Enum</span><span class=\"o\">.</span><span class=\"n\">to_list</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"o\">..</span><span class=\"mi\">9</span><span class=\"p\">)))</span>\n</code></pre></div></div>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"178:1-188:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n u8[60000][10]\n [\n [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],\n [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],\n [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n ...\n ]\n</code></pre></div></div>\n<p data-sourcepos=\"190:1-190:33\">もう少し詳細に見ます。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"192:1-194:3\"><div class=\"highlight\"><pre><code><span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">tensor</span><span class=\"p\">(</span><span class=\"no\">Enum</span><span class=\"o\">.</span><span class=\"n\">to_list</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"o\">..</span><span class=\"mi\">9</span><span class=\"p\">))</span>\n</code></pre></div></div>\n<p data-sourcepos=\"196:1-196:44\">以下のような tensor になります。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"198:1-202:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n s64[10]\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n</code></pre></div></div>\n<p data-sourcepos=\"204:1-204:111\">Nx.equal は2つの tensor を比べて、等しい箇所を1に、そうでない個所を0にします。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"206:1-210:3\"><div class=\"highlight\"><pre><code><span class=\"n\">left</span> <span class=\"o\">=</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">tensor</span><span class=\"p\">([[</span><span class=\"mi\">3</span><span class=\"p\">],[</span><span class=\"mi\">9</span><span class=\"p\">],[</span><span class=\"mi\">4</span><span class=\"p\">]])</span>\n<span class=\"n\">right</span> <span class=\"o\">=</span> <span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">tensor</span><span class=\"p\">([</span><span class=\"mi\">0</span><span class=\"p\">,</span><span class=\"mi\">1</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">,</span><span class=\"mi\">3</span><span class=\"p\">,</span><span class=\"mi\">4</span><span class=\"p\">,</span><span class=\"mi\">5</span><span class=\"p\">,</span><span class=\"mi\">6</span><span class=\"p\">,</span><span class=\"mi\">7</span><span class=\"p\">,</span><span class=\"mi\">8</span><span class=\"p\">,</span><span class=\"mi\">9</span><span class=\"p\">])</span>\n<span class=\"no\">Nx</span><span class=\"o\">.</span><span class=\"n\">equal</span><span class=\"p\">(</span><span class=\"n\">left</span><span class=\"p\">,</span> <span class=\"n\">right</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"212:1-212:39\">以下のように変換されます。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"214:1-222:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n u8[3][10]\n [\n [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n ]\n</code></pre></div></div>\n<h1 data-sourcepos=\"227:1-227:20\">\n<span id=\"2-model-の定義\" class=\"fragment\"></span><a href=\"#2-model-%E3%81%AE%E5%AE%9A%E7%BE%A9\"><i class=\"fa fa-link\"></i></a>2. Model の定義</h1>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"229:1-235:3\"><div class=\"highlight\"><pre><code><span class=\"n\">model</span> <span class=\"o\">=</span>\n <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"n\">input</span><span class=\"p\">(</span><span class=\"s2\">\"input\"</span><span class=\"p\">,</span> <span class=\"ss\">shape:</span> <span class=\"p\">{</span><span class=\"no\">nil</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">28</span><span class=\"p\">,</span> <span class=\"mi\">28</span><span class=\"p\">})</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"n\">flatten</span><span class=\"p\">()</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"n\">dense</span><span class=\"p\">(</span><span class=\"mi\">128</span><span class=\"p\">,</span> <span class=\"ss\">activation:</span> <span class=\"ss\">:relu</span><span class=\"p\">)</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"n\">dense</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">,</span> <span class=\"ss\">activation:</span> <span class=\"ss\">:softmax</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"239:1-239:105\">Axon.input はネットワークの採取に使われ、ネットワーク層(Layer)を出力します。</p>\n<div data-sourcepos=\"241:1-245:3\" class=\"note info\">\n<span class=\"fa fa-fw fa-check-circle\"></span><div>\n<p data-sourcepos=\"242:1-244:99\">Axon.input(\"input\", shape: {nil, 1, 28, 28})<br>\n<strong>input(name, opts \\ [])</strong><br>\nネットワークに input 層 を加える。ここでは具体的には、(1,28,28) のtensor。</p>\n</div>\n</div>\n<p data-sourcepos=\"248:1-248:162\">以下は、前のネットワークの出力層(Layer)を入力として、次の層(Layer)を出力するものです。引数 <strong>x</strong> が前の出力層です。</p>\n<div data-sourcepos=\"251:1-262:3\" class=\"note info\">\n<span class=\"fa fa-fw fa-check-circle\"></span><div>\n<p data-sourcepos=\"252:1-254:240\">Axon.dense(x, 128, activation: :relu)<br>\n<strong>dense(x, units, opts \\ [])</strong><br>\nネットワークに <strong>dense</strong> 層を加える。<strong>dense</strong> とは全結合ニューラルネットワークで、1つのニューラルネットワークを定義する。ニューラルネットワークの単位のようなものか。</p>\n<p data-sourcepos=\"256:1-257:50\"><strong>activation</strong> は活性化関数の指定。kernel と bias はレイヤーのパラメータ。units は出力ベクトルの行数。denseの実装は以下の通り。<br>\n<strong>output = activation(dot(input, kernel) + bias)</strong></p>\n<p data-sourcepos=\"259:1-259:359\">x は (1,28,28) の tensor を flatten したものだから、784行のベクトルとなる。つまり、ここでは784行のベクトル入力に対して、(784,128)の行列を掛け合わせ、、128行ベクトルの出力を得る。それに bias を足しこみ、最後に activation 関数を適用したものを最終的な出力とする。</p>\n<p data-sourcepos=\"261:1-261:192\"><strong>活性化関数</strong> は非線形関数で、ディープラーニングでは線形関数の間に入れて使われます。ここではReLU関数(ランプ関数)を用いています。</p>\n</div>\n</div>\n<div data-sourcepos=\"265:1-269:3\" class=\"note info\">\n<span class=\"fa fa-fw fa-check-circle\"></span><div>\n<p data-sourcepos=\"266:1-268:345\">Axon.dense(x, 10, activation: :softmax)<br>\n直前の dense 層の出力が 128行ベクトルで、それを入力とするこの dense 層では、出力が10行ベクトルなので、(128,10) の行列を掛け合わせる線形変換となります。<br>\n<strong>活性化関数</strong> に <strong>softmax</strong> を指定していますが、前の活性化関数の使われ方とは少し違います。ここでは最終出力値を、<strong>確率値</strong> を表す0~1の実数値に変換します。推論結果が確率値として得られるわけです。<strong>softmax</strong> の他に、<strong>sigmoid</strong> などもあります。</p>\n</div>\n</div>\n<h1 data-sourcepos=\"274:1-274:11\">\n<span id=\"3-訓練\" class=\"fragment\"></span><a href=\"#3-%E8%A8%93%E7%B7%B4\"><i class=\"fa fa-link\"></i></a>3. 訓練</h1>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"276:1-282:3\"><div class=\"highlight\"><pre><code><span class=\"n\">params</span> <span class=\"o\">=</span>\n <span class=\"n\">model</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"no\">Loop</span><span class=\"o\">.</span><span class=\"n\">trainer</span><span class=\"p\">(</span><span class=\"ss\">:categorical_cross_entropy</span><span class=\"p\">,</span> <span class=\"ss\">:adam</span><span class=\"p\">)</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"no\">Loop</span><span class=\"o\">.</span><span class=\"n\">metric</span><span class=\"p\">(</span><span class=\"ss\">:accuracy</span><span class=\"p\">,</span> <span class=\"s2\">\"Accuracy\"</span><span class=\"p\">)</span>\n <span class=\"o\">|\u0026gt;</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"no\">Loop</span><span class=\"o\">.</span><span class=\"n\">run</span><span class=\"p\">(</span><span class=\"no\">Stream</span><span class=\"o\">.</span><span class=\"n\">zip</span><span class=\"p\">(</span><span class=\"n\">images</span><span class=\"p\">,</span> <span class=\"n\">targets</span><span class=\"p\">),</span> <span class=\"p\">%{},</span> <span class=\"ss\">epochs:</span> <span class=\"mi\">10</span><span class=\"p\">,</span> <span class=\"ss\">compiler:</span> <span class=\"no\">EXLA</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"283:1-283:242\">機械学習では、繰り返し計算(training loop)を行うことで、Modelのdense層で使われた行列のパラメータを損失がゼロに近づくように、調整していきます。この過程を訓練と呼びます。</p>\n<p data-sourcepos=\"285:1-285:152\">これまで獲得した 訓練データ(images)+解答リスト(targets) と Model (ネットワーク)を用いて、学習を行いまます。</p>\n<p data-sourcepos=\"288:1-290:90\"><strong>trainer(model, loss, optimizer, loss_scale \\ :identity, opts \\ [])</strong><br>\nModel と 損失関数 とオプティマイザから <strong>training loop</strong> を作り出します。<br>\nここでは損失関数として categorical_cross_entropy が指定されています。</p>\n<p data-sourcepos=\"293:1-295:61\"><strong>run(loop, data, init_state \\ %{}, opts \\ [])</strong><br>\n訓練データと解答(labels)を与えてloopを走らせます。<br>\n<strong>compiler: EXLA</strong> が無ければ、とても遅いです。</p>\n<h1 data-sourcepos=\"298:1-298:11\">\n<span id=\"4-予測\" class=\"fragment\"></span><a href=\"#4-%E4%BA%88%E6%B8%AC\"><i class=\"fa fa-link\"></i></a>4. 予測</h1>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"299:1-303:3\"><div class=\"highlight\"><pre><code><span class=\"n\">first_batch</span> <span class=\"o\">=</span> <span class=\"no\">Enum</span><span class=\"o\">.</span><span class=\"n\">at</span><span class=\"p\">(</span><span class=\"n\">images</span><span class=\"p\">,</span> <span class=\"mi\">0</span><span class=\"p\">)</span>\n\n<span class=\"n\">output</span> <span class=\"o\">=</span> <span class=\"no\">Axon</span><span class=\"o\">.</span><span class=\"n\">predict</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"n\">first_batch</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"305:1-306:153\">訓練されたパラメータをもとに、結果を予測します。<br>\nここでは訓練データ自信をテストデータとして使っているので、アレですが、まあ動作確認の意味だけですから。</p>\n<p data-sourcepos=\"309:1-309:206\">実行した結果が以下です。とりあえず5個の結果が表示されています。予測値は確率で表現されていますから、それぞれ最も1に近い値が解答となります。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"310:1-323:3\"><div class=\"highlight\"><pre><code>#Nx.Tensor\u0026lt;\n f32[32][10]\n EXLA.Backend\u0026lt;cuda:0, 0.4287185959.1584005128.178388\u0026gt;\n [\n [1.831141302537213e-17, 2.1314743702152114e-17, 2.788575577047925e-13, 0.016425110399723053, 2.6716437079667318e-24, 0.9835748672485352, 4.4600362268452274e-23, 4.170524941561095e-14, 1.6398175635225806e-15, 4.088237723614413e-14],\n [1.0, 1.6728642627921315e-16, 5.3293486956818015e-8, 6.417299061801029e-15, 1.880324350235668e-20, 9.067465677500657e-15, 1.4072107194784689e-12, 4.926563714272025e-13, 1.8360491078894814e-12, 8.877283131682179e-13],\n [1.0514713232046002e-11, 4.384134626889136e-6, 7.727980744220986e-8, 1.8622221542585748e-9, 0.9998115301132202, 1.154940986597408e-11, 2.9517911010433495e-13, 1.8387872842140496e-4, 5.427200733265636e-8, 1.1141140277004524e-7],\n [6.884900288772755e-11, 0.9999977350234985, 9.951911295047466e-9, 1.23654253503247e-9, 3.8443337402327415e-9, 1.4718837260119244e-11, 7.166710801198573e-13, 2.2690628611599095e-6, 3.970355155757943e-9, 6.868552582198087e-16],\n [1.28227966253062e-15, 3.5129577025116987e-10, 3.530791788499202e-14, 3.4387208870612085e-5, 1.5201632095340756e-6, 1.4119769353726497e-8, 4.554542479500676e-17, 4.376623508051125e-8, 8.845394745549129e-7, 0.9999631643295288],\n ...\n ]\n\u0026gt;\n</code></pre></div></div>\n<p data-sourcepos=\"325:1-325:107\">もともとの解答リストである labels を表示させてみると以下のようになります。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"326:1-329:3\"><div class=\"highlight\"><pre><code>\u0026lt;\u0026lt;5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5, 3, 6, 1, 7, 2, 8, 6, 9, 4, 0, 9, 1, 1, 2, 4, 3, 2, 7, 3, 8, 6,\n 9, 0, 5, 6, 0, 7, 6, 1, 8, 7, 9, 3, 9, 8, 5, 9, 3, ...\u0026gt;\u0026gt;\n</code></pre></div></div>\n<p data-sourcepos=\"331:1-335:63\">最初の解答が 5 です。確かに0.9835748672485352が1に近いです。<br>\n2番目の解答は 0 です。1.0 となっておりOKです。<br>\n3番目の解答は 4 です。0.9998115301132202でOKですね。<br>\n4番目の解答は 1 です。0.9999977350234985でOKですね。<br>\n5番目の解答は 9 です。0.9999631643295288でOKです。</p>\n<p data-sourcepos=\"337:1-337:104\">他の値は 1.xxx e-9 などとほぼゼロの値を指していることに注意してください。</p>\n<p data-sourcepos=\"341:1-341:24\">今回は以上です。</p>\n","body":"\nAxon で、以下のドキュメントに沿って、機械学習を試してみました。\n[Classifying handwritten digits](https://hexdocs.pm/axon/mnist.html)\n\n\nちなみに機械学習はGPUパワーなしには無理なので、以下の方法で Livebook の起動を行いました。大変助かりました。\n[Google Colaboratory 上で Elixir Livebook を動かす(GPUを無料で使う)](https://qiita.com/RyoWakabayashi/items/113b94866780c7646af1)\n\n\n**関連記事**\n[Elixir Nx の基礎 (Livebook) - Qitta](https://qiita.com/sand/items/9a47cfe0c95386417224)\n[Livebook 事始め (Elixir) - Qiita](https://qiita.com/sand/items/6753c1782774b45daf6b)\n[【機械学習】誤差逆伝播法のコンパクトな説明 - Qiita](https://qiita.com/sand/items/2d783a12c575fb949c6e)\n\n\n# 1.訓練データの取得と正規化\n\n## 1-1. 必要なインストール\n\n\n```elixir:\nMix.install([\n {:axon, github: \"elixir-nx/axon\"},\n {:nx, \"~> 0.4\"},\n {:exla, \"~> 0.4\"},\n {:req, \"~> 0.3.0\"}\n])\n```\n\n\n\n## 1-2. 訓練データの取得\n\n```elixir:\nbase_url = \"https://storage.googleapis.com/cvdf-datasets/mnist/\"\n%{body: train_images} = Req.get!(base_url <> \"train-images-idx3-ubyte.gz\")\n%{body: train_labels} = Req.get!(base_url <> \"train-labels-idx1-ubyte.gz\")\n\n<<_::32, n_images::32, n_rows::32, n_cols::32, images::binary>> = train_images\n<<_::32, n_labels::32, labels::binary>> = train_labels\n```\n\n\ntrain_images、 を4個のヘッダー(32ビット)部分と本体(images)に分解してます。\ntrain_labels も2個のヘッダー(32ビット)部分と本体(labels)に分解します。\n\n::: note warn\nElixir では **<<>>** を使って **バイナリ** を定義できます。\n\niex> <<0, 1, 2, 3>>\n<<0, 1, 2, 3>>\niex> byte_size(<<0, 1, 2, 3>>)\n4\n\n**バイナリとはバイトのシーケンスです。**\n:::\n\n\n```elixir:\n<<_::32, n_images::32, n_rows::32, n_cols::32, images::binary>> = train_images\n<<_::32, n_labels::32, labels::binary>> = train_labels\n```\n\n![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/6187cfb4-19a3-3425-de62-e8ae7b009cfe.png)\n\nイメージ数もラベル数(解答数)も60000個です。つまり1個の数字で 28*28 Byte使用しているので、全体のイメージの byte 数は 28*28*60000 = 47040000 となります。画像の1ドットは **0 ~ 255** の整数値で表され、1 byte 使用することに注意してください。画素の色の濃淡を表現しています。\n\n\n## 1-3. 訓練データの正規化\n\n```elixir:\nimages =\n images\n |> Nx.from_binary({:u, 8})\n |> Nx.reshape({n_images, 1, n_rows, n_cols}, names: [:images, :channels, :height, :width])\n |> Nx.divide(255)\n```\n\n::: note info\n**Tensor の正規化**\n* Nx.from_binary(images, {:u, 8})\nbinary(=images) から、与えられた型の 1次元 tensor を作ります。 \n**Nx tensors** は **unsigned integers** (**u8, u16, u32, u64**) や **signed integers** (**s8, s16, s32, s64**)、 **floats** (**f32, f64**)、 **brain floats** (**bf16**)、 **complex** (**c64, c128**) の値を保持します。\n\n* Nx.reshape(x, {n_images, 1, n_rows, n_cols}, names: [:images, :channels, :height, :width])\n1次元 tensor を、意味のある次元の tensor に変形します。\n\n* Nx.divide(255)\ntensor の値は **0~255** の値だから、255 で割ることにより、**0~1** の値に変換します。これを **正規化** と呼びます。\n:::\n\n\nこの結果得られる、images tensor を可視化してみましょう。\n\n```elixir:\nimages[[images: 0..4]] |> Nx.to_heatmap()\n```\n\n画面をうまくキャプチャーできないので残念ですが、いい感じに5個の数字のドット絵が表示されます。\n\n![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/a893070b-ab63-98c4-e0bf-f011ae9ddb93.png)\n\n\n## 1-4. 訓練データのミニバッチ化\n\n\n```elixir:\nimages = Nx.to_batched(images, 32)\n```\n\n勾配降下法で学習する場合、何件かの訓練データをグループ化し、一気に勾配計算をやると効率的です。これは **ミニバッチ学習法** と呼ばれています。\n\n**Nx.to_batched(images, 32)** は images を tensor batches に変換します。 \n\n## 1-5. labels の one-hot エンコーディングとミニバッチ化\n\n```elixir:\ntargets =\n labels\n |> Nx.from_binary({:u, 8})\n |> Nx.new_axis(-1)\n |> Nx.equal(Nx.tensor(Enum.to_list(0..9)))\n |> Nx.to_batched(32)\n```\n\nimages と同様に、labels も扱いやすいように変換します。\n**one-hot エンコーディング** とは、例えば **3** というスカラー値を、**[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]** という 3番目だけ 1 で他は全て 0 のベクトルに変換することです。0 番始まりの 3 番目です。\n\n\n\n大分細かくなりますが、段階的に変換を追っていきます。\n* 最初の変換です。\n\n```elixir:\n labels\n |> Nx.from_binary({:u, 8})\n```\n\nNx.from_binaryで labels を1次元の tensor に変換します。\n\n```\n#Nx.Tensor<\n u8[60000]\n [5, 0, 4, 1,...,] \n```\n\n* 次の変換です\n\n```elixir:\n labels\n |> Nx.from_binary({:u, 8})\n |> Nx.new_axis(-1)\n```\n\nNx.new_axis で size 1 の axis を加えます。 -1 引数なので後ろに axis を加えます。\n\n```\n#Nx.Tensor<\n u8[60000][1]\n [\n [5],\n [0],\n [4],\n [1],\n ---\n ]\n```\n\n* 次の変換です\n\n```elixir:\n labels\n |> Nx.from_binary({:u, 8})\n |> Nx.new_axis(-1)\n |> Nx.equal(Nx.tensor(Enum.to_list(0..9)))\n```\n\n```\n#Nx.Tensor<\n u8[60000][10]\n [\n [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],\n [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],\n [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n ...\n ]\n```\n\nもう少し詳細に見ます。\n\n```elixir:\nNx.tensor(Enum.to_list(0..9))\n```\n\n以下のような tensor になります。\n\n```\n#Nx.Tensor<\n s64[10]\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n```\n\nNx.equal は2つの tensor を比べて、等しい箇所を1に、そうでない個所を0にします。\n\n```elixir:\nleft = Nx.tensor([[3],[9],[4]])\nright = Nx.tensor([0,1,2,3,4,5,6,7,8,9])\nNx.equal(left, right)\n```\n\n以下のように変換されます。\n\n```\n#Nx.Tensor<\n u8[3][10]\n [\n [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n ]\n```\n\n\n\n\n# 2. Model の定義\n\n```elixir:\nmodel =\n Axon.input(\"input\", shape: {nil, 1, 28, 28})\n |> Axon.flatten()\n |> Axon.dense(128, activation: :relu)\n |> Axon.dense(10, activation: :softmax)\n```\n\n\n\nAxon.input はネットワークの採取に使われ、ネットワーク層(Layer)を出力します。\n\n::: note info\nAxon.input(\"input\", shape: {nil, 1, 28, 28})\n**input(name, opts \\\\ [])**\nネットワークに input 層 を加える。ここでは具体的には、(1,28,28) のtensor。\n:::\n\n\n以下は、前のネットワークの出力層(Layer)を入力として、次の層(Layer)を出力するものです。引数 **x** が前の出力層です。\n\n\n::: note info\nAxon.dense(x, 128, activation: :relu)\n**dense(x, units, opts \\\\ [])**\nネットワークに **dense** 層を加える。**dense** とは全結合ニューラルネットワークで、1つのニューラルネットワークを定義する。ニューラルネットワークの単位のようなものか。\n\n**activation** は活性化関数の指定。kernel と bias はレイヤーのパラメータ。units は出力ベクトルの行数。denseの実装は以下の通り。\n**output = activation(dot(input, kernel) + bias)**\n\nx は (1,28,28) の tensor を flatten したものだから、784行のベクトルとなる。つまり、ここでは784行のベクトル入力に対して、(784,128)の行列を掛け合わせ、、128行ベクトルの出力を得る。それに bias を足しこみ、最後に activation 関数を適用したものを最終的な出力とする。\n\n**活性化関数** は非線形関数で、ディープラーニングでは線形関数の間に入れて使われます。ここではReLU関数(ランプ関数)を用いています。\n:::\n\n\n::: note info\nAxon.dense(x, 10, activation: :softmax)\n直前の dense 層の出力が 128行ベクトルで、それを入力とするこの dense 層では、出力が10行ベクトルなので、(128,10) の行列を掛け合わせる線形変換となります。\n**活性化関数** に **softmax** を指定していますが、前の活性化関数の使われ方とは少し違います。ここでは最終出力値を、**確率値** を表す0~1の実数値に変換します。推論結果が確率値として得られるわけです。**softmax** の他に、**sigmoid** などもあります。\n:::\n\n\n\n\n# 3. 訓練\n\n```elixir:\nparams =\n model\n |> Axon.Loop.trainer(:categorical_cross_entropy, :adam)\n |> Axon.Loop.metric(:accuracy, \"Accuracy\")\n |> Axon.Loop.run(Stream.zip(images, targets), %{}, epochs: 10, compiler: EXLA)\n```\n機械学習では、繰り返し計算(training loop)を行うことで、Modelのdense層で使われた行列のパラメータを損失がゼロに近づくように、調整していきます。この過程を訓練と呼びます。\n\nこれまで獲得した 訓練データ(images)+解答リスト(targets) と Model (ネットワーク)を用いて、学習を行いまます。\n\n\n**trainer(model, loss, optimizer, loss_scale \\\\ :identity, opts \\\\ [])**\nModel と 損失関数 とオプティマイザから **training loop** を作り出します。\nここでは損失関数として categorical_cross_entropy が指定されています。\n\n\n**run(loop, data, init_state \\\\ %{}, opts \\\\ [])**\n訓練データと解答(labels)を与えてloopを走らせます。\n**compiler: EXLA** が無ければ、とても遅いです。\n\n\n# 4. 予測\n```elixir:\nfirst_batch = Enum.at(images, 0)\n\noutput = Axon.predict(model, params, first_batch)\n```\n\n訓練されたパラメータをもとに、結果を予測します。\nここでは訓練データ自信をテストデータとして使っているので、アレですが、まあ動作確認の意味だけですから。\n\n\n実行した結果が以下です。とりあえず5個の結果が表示されています。予測値は確率で表現されていますから、それぞれ最も1に近い値が解答となります。\n```\n#Nx.Tensor<\n f32[32][10]\n EXLA.Backend<cuda:0, 0.4287185959.1584005128.178388>\n [\n [1.831141302537213e-17, 2.1314743702152114e-17, 2.788575577047925e-13, 0.016425110399723053, 2.6716437079667318e-24, 0.9835748672485352, 4.4600362268452274e-23, 4.170524941561095e-14, 1.6398175635225806e-15, 4.088237723614413e-14],\n [1.0, 1.6728642627921315e-16, 5.3293486956818015e-8, 6.417299061801029e-15, 1.880324350235668e-20, 9.067465677500657e-15, 1.4072107194784689e-12, 4.926563714272025e-13, 1.8360491078894814e-12, 8.877283131682179e-13],\n [1.0514713232046002e-11, 4.384134626889136e-6, 7.727980744220986e-8, 1.8622221542585748e-9, 0.9998115301132202, 1.154940986597408e-11, 2.9517911010433495e-13, 1.8387872842140496e-4, 5.427200733265636e-8, 1.1141140277004524e-7],\n [6.884900288772755e-11, 0.9999977350234985, 9.951911295047466e-9, 1.23654253503247e-9, 3.8443337402327415e-9, 1.4718837260119244e-11, 7.166710801198573e-13, 2.2690628611599095e-6, 3.970355155757943e-9, 6.868552582198087e-16],\n [1.28227966253062e-15, 3.5129577025116987e-10, 3.530791788499202e-14, 3.4387208870612085e-5, 1.5201632095340756e-6, 1.4119769353726497e-8, 4.554542479500676e-17, 4.376623508051125e-8, 8.845394745549129e-7, 0.9999631643295288],\n ...\n ]\n>\n```\n\nもともとの解答リストである labels を表示させてみると以下のようになります。\n```\n<<5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5, 3, 6, 1, 7, 2, 8, 6, 9, 4, 0, 9, 1, 1, 2, 4, 3, 2, 7, 3, 8, 6,\n 9, 0, 5, 6, 0, 7, 6, 1, 8, 7, 9, 3, 9, 8, 5, 9, 3, ...>>\n```\n\n最初の解答が 5 です。確かに0.9835748672485352が1に近いです。\n2番目の解答は 0 です。1.0 となっておりOKです。\n3番目の解答は 4 です。0.9998115301132202でOKですね。\n4番目の解答は 1 です。0.9999977350234985でOKですね。\n5番目の解答は 9 です。0.9999631643295288でOKです。\n\n他の値は 1.xxx e-9 などとほぼゼロの値を指していることに注意してください。\n\n\n\n今回は以上です。\n","coediting":false,"comments_count":0,"created_at":"2022-11-09T14:56:23+09:00","group":null,"id":"390b14a8665be2c0baf9","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Elixir","versions":[]},{"name":"機械学習","versions":[]},{"name":"Axon","versions":[]}],"title":"Elixir Axon で学ぶ機械学習 (Livebook)","updated_at":"2022-11-09T15:12:42+09:00","url":"https://qiita.com/sand/items/390b14a8665be2c0baf9","user":{"description":"フリーのプログラマです。\r\n仕事ではPython、Node、React、Vueなどを使うことが多いです。\r\n個人的にはHaskell、Elm、Elixir、Phoenixなど関数型言語が好きです。\r\n関数型はシンプルで直感的だから好きですが、オブジェクト指向は複雑で見通しが悪いので苦手です。\r\n確率統計を勉強中。","facebook_id":"","followees_count":9,"followers_count":93,"github_login_name":null,"id":"sand","items_count":230,"linkedin_id":"","location":"埼玉","name":"sand mypress","organization":"フリー","permanent_id":61915,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/61915/profile-images/1511829854","team_only":false,"twitter_screen_name":null,"website_url":""},"page_views_count":null,"team_membership":null},{"rendered_body":"<p data-sourcepos=\"1:1-1:132\"><a href=\"https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88\" rel=\"nofollow noopener\" target=\"_blank\">シェルスクリプト</a>が苦手なので、いつも<a href=\"https://elixirschool.com/ja/why\" rel=\"nofollow noopener\" target=\"_blank\">Elixir</a>で気軽にスクリプトを書いています。</p>\n<p data-sourcepos=\"3:1-3:117\"><a href=\"https://elixirschool.com/ja/lessons/intermediate/escripts\" rel=\"nofollow noopener\" target=\"_blank\">escriptで実行ファイルを作る</a>方法がありますが、もっと簡単に気軽にやりたいのです。</p>\n<h2 data-sourcepos=\"9:1-9:15\">\n<span id=\"論よりrun\" class=\"fragment\"></span><a href=\"#%E8%AB%96%E3%82%88%E3%82%8Arun\"><i class=\"fa fa-link\"></i></a>論よりRUN</h2>\n<h3 data-sourcepos=\"11:1-11:37\">\n<span id=\"toukonexsファイルを作る\" class=\"fragment\"></span><a href=\"#toukonexs%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E3%82%8B\"><i class=\"fa fa-link\"></i></a><code>toukon.exs</code>ファイルを作る</h3>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"13:1-15:3\"><div class=\"highlight\"><pre><code><span class=\"err\">❯</span> <span class=\"n\">echo</span> <span class=\"s1\">'IO.puts(\"闘魂🔥\")'</span> <span class=\"o\">\u0026gt;</span> <span class=\"n\">toukon</span><span class=\"o\">.</span><span class=\"n\">exs</span>\n</code></pre></div></div>\n<p data-sourcepos=\"17:1-17:158\"><code>闘魂🔥</code>を表示するElixirコードが書かれたファイルが出来ました。早速<code>elixir</code>コマンドで実行してみたいと思います。</p>\n<p data-sourcepos=\"19:1-19:211\">注意:サンプルコードにある<code>❯ </code>はコマンド入力待ち状態であることを示す表示(<a href=\"https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88\" rel=\"nofollow noopener\" target=\"_blank\">コマンドプロンプト</a>)です。コピーするときはそれを取り除いてください。</p>\n<h3 data-sourcepos=\"23:1-23:33\">\n<span id=\"elixirコマンドで実行\" class=\"fragment\"></span><a href=\"#elixir%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E5%AE%9F%E8%A1%8C\"><i class=\"fa fa-link\"></i></a><code>elixir</code>コマンドで実行</h3>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"25:1-29:3\"><div class=\"highlight\"><pre><code>❯ elixir <span class=\"nt\">--help</span>\nUsage: elixir <span class=\"o\">[</span>options] <span class=\"o\">[</span>.exs file] <span class=\"o\">[</span>data]\n...\n</code></pre></div></div>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"31:1-34:3\"><div class=\"highlight\"><pre><code>❯ elixir toukon.exs\n闘魂🔥\n</code></pre></div></div>\n<p data-sourcepos=\"36:1-36:27\">闘魂が燃えました。</p>\n<h3 data-sourcepos=\"38:1-38:28\">\n<span id=\"ファイル名で実行\" class=\"fragment\"></span><a href=\"#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%A7%E5%AE%9F%E8%A1%8C\"><i class=\"fa fa-link\"></i></a>ファイル名で実行</h3>\n<p data-sourcepos=\"40:1-40:116\">試しに<a href=\"https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88\" rel=\"nofollow noopener\" target=\"_blank\">シェルスクリプト</a>みたいにファイル名をコマンドとして使えるようにします。</p>\n<p data-sourcepos=\"42:1-42:90\">何も準備せずにやるとエラーが出ます。順番に対処していきます。</p>\n<h4 data-sourcepos=\"44:1-44:34\">\n<span id=\"エラー1-permission-denied\" class=\"fragment\"></span><a href=\"#%E3%82%A8%E3%83%A9%E3%83%BC1-permission-denied\"><i class=\"fa fa-link\"></i></a>エラー1: permission denied</h4>\n<p data-sourcepos=\"46:1-46:51\">ファイルを実行する権限が必要です。</p>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"48:1-51:3\"><div class=\"highlight\"><pre><code>❯ ./toukon.exs\nzsh: permission denied: ./toukon.exs\n</code></pre></div></div>\n<p data-sourcepos=\"53:1-53:64\"><a href=\"https://ja.wikipedia.org/wiki/Chmod\" rel=\"nofollow noopener\" target=\"_blank\">chmod</a>でファイルへのアクセス権を変更します。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"55:1-57:3\"><div class=\"highlight\"><pre><code>❯ chmod a+x ./toukon.exs\n</code></pre></div></div>\n<h4 data-sourcepos=\"61:1-61:29\">\n<span id=\"エラー2-syntax-error\" class=\"fragment\"></span><a href=\"#%E3%82%A8%E3%83%A9%E3%83%BC2-syntax-error\"><i class=\"fa fa-link\"></i></a>エラー2: syntax error</h4>\n<p data-sourcepos=\"63:1-63:81\">ElixirコードがElixirコードとして認識されていないようです。</p>\n<p data-sourcepos=\"65:1-65:111\">ファイルを実行する環境にElixirコードを実行したいとお願いする必要があります。</p>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"67:1-71:3\"><div class=\"highlight\"><pre><code>❯ ./toukon.exs\n./toukon.exs: line 1: syntax error near unexpected token <span class=\"sb\">`</span><span class=\"s2\">\"闘魂🔥\"</span><span class=\"s1\">'\n./toukon.exs: line 1: `IO.puts(\"闘魂🔥\")'</span>\n</code></pre></div></div>\n<p data-sourcepos=\"73:1-73:135\">スクリプトファイルに<a href=\"https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix)\" rel=\"nofollow noopener\" target=\"_blank\">shebang</a>を追加して起動時にスクリプトを読み込むインタプリタを指定します。</p>\n<p data-sourcepos=\"75:1-75:99\">Elixirのインタプリタを使いたいので以下のようにおまじないを書きます。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"77:1-80:3\"><div class=\"highlight\"><pre><code><span class=\"c1\">#!/usr/bin/env elixir</span>\n<span class=\"no\">IO</span><span class=\"o\">.</span><span class=\"n\">puts</span><span class=\"p\">(</span><span class=\"s2\">\"闘魂🔥\"</span><span class=\"p\">)</span>\n</code></pre></div></div>\n<p data-sourcepos=\"82:1-82:204\">お気に入りのテキストエディターで直接編集した方が早いかもしれませんが、以下のようなコマンドでもファイルの中身を入れ替えることができます。</p>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"84:1-89:3\"><div class=\"highlight\"><pre><code>❯ <span class=\"nb\">cat</span> <span class=\"o\">\u0026lt;\u0026lt;-</span><span class=\"no\">EOF</span><span class=\"sh\"> \u0026gt; ./toukon.exs\n#!/usr/bin/env elixir\nIO.puts(\"闘魂🔥\")\n</span><span class=\"no\">EOF\n</span></code></pre></div></div>\n<p data-sourcepos=\"91:1-91:60\">再度あらためてファイルを実行してみます。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"93:1-96:3\"><div class=\"highlight\"><pre><code><span class=\"err\">❯</span> <span class=\"o\">./</span><span class=\"n\">toukon</span><span class=\"o\">.</span><span class=\"n\">exs</span>\n<span class=\"err\">闘魂🔥</span>\n</code></pre></div></div>\n<p data-sourcepos=\"98:1-98:27\">闘魂が燃えました。</p>\n<h3 data-sourcepos=\"102:1-102:15\">\n<span id=\"mixinstall\" class=\"fragment\"></span><a href=\"#mixinstall\"><i class=\"fa fa-link\"></i></a>Mix.install</h3>\n<p data-sourcepos=\"104:1-104:138\"><a href=\"https://hexdocs.pm/mix/Mix.html#install/2\" rel=\"nofollow noopener\" target=\"_blank\">Mix.install/2</a>を用いて、Elixirスクリプトの中で直接Elixirパッケージをインストールすることも可能です。</p>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"106:1-119:3\"><div class=\"highlight\"><pre><code>❯ <span class=\"nb\">cat</span> <span class=\"o\">\u0026lt;\u0026lt;-</span><span class=\"no\">EOF</span><span class=\"sh\"> \u0026gt; ./weather.exs\n#! /usr/bin/env elixir\nMix.install [{:req, \"~\u0026gt; 0.3.0\"}]\n\nweather =\n case Req.get!(\"https://wttr.in?format=3\") do\n %{status: 200, body: body} -\u0026gt; body\n _ -\u0026gt; \"error😭\"\n end\n\nIO.puts(weather)\n</span><span class=\"no\">EOF\n</span></code></pre></div></div>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"121:1-123:3\"><div class=\"highlight\"><pre><code>❯ <span class=\"nb\">chmod </span>a+x ./weather.exs\n</code></pre></div></div>\n<div class=\"code-frame\" data-lang=\"bash\" data-sourcepos=\"125:1-128:3\"><div class=\"highlight\"><pre><code>❯ ./weather.exs\nWashington, District of Columbia, United States: ⛅️ +56°F\n</code></pre></div></div>\n<p data-sourcepos=\"132:1-132:120\">闘魂に関してはこの記事がおすすめです。職種を問わずひらめきが得られると思います。</p>\n<p data-sourcepos=\"134:1-134:41\"><qiita-embed-ogp src=\"https://note.com/awesomey/n/n4d8c355bc8f7\"></qiita-embed-ogp></p>\n","body":"[シェルスクリプト]が苦手なので、いつも[Elixir][なぜElixir?]で気軽にスクリプトを書いています。\n\n[escriptで実行ファイルを作る]方法がありますが、もっと簡単に気軽にやりたいのです。\n\n[なぜElixir?]: https://elixirschool.com/ja/why\n[シェルスクリプト]: https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88\n[escriptで実行ファイルを作る]: https://elixirschool.com/ja/lessons/intermediate/escripts\n\n## 論よりRUN\n\n### `toukon.exs`ファイルを作る\n\n```elixir\n❯ echo 'IO.puts(\"闘魂🔥\")' > toukon.exs\n```\n\n`闘魂🔥`を表示するElixirコードが書かれたファイルが出来ました。早速`elixir`コマンドで実行してみたいと思います。\n\n注意:サンプルコードにある`❯ `はコマンド入力待ち状態であることを示す表示([コマンドプロンプト])です。コピーするときはそれを取り除いてください。\n\n[コマンドプロンプト]: https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88\n\n### `elixir`コマンドで実行\n\n```bash\n❯ elixir --help\nUsage: elixir [options] [.exs file] [data]\n...\n```\n\n```bash\n❯ elixir toukon.exs\n闘魂🔥\n```\n\n闘魂が燃えました。\n\n### ファイル名で実行\n\n試しに[シェルスクリプト]みたいにファイル名をコマンドとして使えるようにします。\n\n何も準備せずにやるとエラーが出ます。順番に対処していきます。\n\n#### エラー1: permission denied\n\nファイルを実行する権限が必要です。\n\n```bash\n❯ ./toukon.exs\nzsh: permission denied: ./toukon.exs\n```\n\n[chmod]でファイルへのアクセス権を変更します。\n\n```\n❯ chmod a+x ./toukon.exs\n```\n\n[chmod]: https://ja.wikipedia.org/wiki/Chmod\n\n#### エラー2: syntax error\n\nElixirコードがElixirコードとして認識されていないようです。\n\nファイルを実行する環境にElixirコードを実行したいとお願いする必要があります。\n\n```bash\n❯ ./toukon.exs\n./toukon.exs: line 1: syntax error near unexpected token `\"闘魂🔥\"'\n./toukon.exs: line 1: `IO.puts(\"闘魂🔥\")'\n```\n\nスクリプトファイルに[shebang]を追加して起動時にスクリプトを読み込むインタプリタを指定します。\n\nElixirのインタプリタを使いたいので以下のようにおまじないを書きます。\n\n```elixir\n#!/usr/bin/env elixir\nIO.puts(\"闘魂🔥\")\n```\n\nお気に入りのテキストエディターで直接編集した方が早いかもしれませんが、以下のようなコマンドでもファイルの中身を入れ替えることができます。\n\n```bash\n❯ cat <<-EOF > ./toukon.exs\n#!/usr/bin/env elixir\nIO.puts(\"闘魂🔥\")\nEOF\n```\n\n再度あらためてファイルを実行してみます。\n\n```elixir\n❯ ./toukon.exs\n闘魂🔥\n```\n\n闘魂が燃えました。\n\n[shebang]: https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix)\n\n### Mix.install\n\n[Mix.install/2]を用いて、Elixirスクリプトの中で直接Elixirパッケージをインストールすることも可能です。\n\n```bash\n❯ cat <<-EOF > ./weather.exs\n#! /usr/bin/env elixir\nMix.install [{:req, \"~> 0.3.0\"}]\n\nweather =\n case Req.get!(\"https://wttr.in?format=3\") do\n %{status: 200, body: body} -> body\n _ -> \"error😭\"\n end\n\nIO.puts(weather)\nEOF\n```\n\n```bash\n❯ chmod a+x ./weather.exs\n```\n\n```bash\n❯ ./weather.exs\nWashington, District of Columbia, United States: ⛅️ +56°F\n```\n\n[Mix.install/2]: https://hexdocs.pm/mix/Mix.html#install/2\n\n闘魂に関してはこの記事がおすすめです。職種を問わずひらめきが得られると思います。\n\nhttps://note.com/awesomey/n/n4d8c355bc8f7\n\n\n","coediting":false,"comments_count":0,"created_at":"2022-11-08T20:49:01+09:00","group":null,"id":"4a4e6d5dd1432e6168c1","likes_count":2,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Erlang","versions":[]},{"name":"script","versions":[]},{"name":"Elixir","versions":[]},{"name":"40代駆け出しエンジニア","versions":[]},{"name":"AdventCalendar2022","versions":[]}],"title":"Elixirで気軽にスクリプト","updated_at":"2022-11-09T05:55:06+09:00","url":"https://qiita.com/mnishiguchi/items/4a4e6d5dd1432e6168c1","user":{"description":"Software Engineer","facebook_id":"","followees_count":112,"followers_count":63,"github_login_name":"mnishiguchi","id":"mnishiguchi","items_count":96,"linkedin_id":"mnishiguchi","location":"","name":"Masatoshi Nishiguchi","organization":"","permanent_id":82804,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/82804/profile-images/1473702574","team_only":false,"twitter_screen_name":null,"website_url":"http://mnishiguchi.com"},"page_views_count":null,"team_membership":null},{"rendered_body":"<h1 data-sourcepos=\"1:1-1:8\">\n<span id=\"概要\" class=\"fragment\"></span><a href=\"#%E6%A6%82%E8%A6%81\"><i class=\"fa fa-link\"></i></a>概要</h1>\n<p data-sourcepos=\"2:1-3:20\">paiza.ioでelixirやってみた。<br>\nIO使ってみた。</p>\n<h1 data-sourcepos=\"5:1-5:23\">\n<span id=\"サンプルコード\" class=\"fragment\"></span><a href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89\"><i class=\"fa fa-link\"></i></a>サンプルコード</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"7:1-52:3\"><div class=\"highlight\"><pre><code>\nIO.chardata_to_string([0x00E6, 0x00DF])\n|\u0026gt; IO.puts\nIO.chardata_to_string([0x0061, \"bc\"])\n|\u0026gt; IO.puts\nIO.chardata_to_string(\"string\")\n|\u0026gt; IO.puts\n\nIO.gets(\"What is your name?\\n\")\n|\u0026gt; IO.puts\n\nIO.inspect(\u0026lt;\u0026lt;0, 1, 2\u0026gt;\u0026gt;, width: 40)\n\n[1, 2, 3]\n|\u0026gt; IO.inspect(label: \"before\")\n|\u0026gt; Enum.map(\u0026amp;(\u0026amp;1 * 2))\n|\u0026gt; IO.inspect(label: \"after\")\n|\u0026gt; Enum.sum()\n|\u0026gt; IO.puts\n\nIO.iodata_length([1, 2 | \u0026lt;\u0026lt;3, 4\u0026gt;\u0026gt;])\n|\u0026gt; IO.puts\n\nbin1 = \u0026lt;\u0026lt;1, 2, 3\u0026gt;\u0026gt;\nbin2 = \u0026lt;\u0026lt;4, 5\u0026gt;\u0026gt;\nbin3 = \u0026lt;\u0026lt;6\u0026gt;\u0026gt;\nIO.iodata_to_binary([bin1, 1, [2, 3, bin2], 4 | bin3])\n|\u0026gt; IO.inspect\n\nbin = \u0026lt;\u0026lt;1, 2, 3\u0026gt;\u0026gt;\nIO.iodata_to_binary(bin)\n|\u0026gt; IO.inspect\n\nIO.puts(\"Hello World!\")\nIO.write(\"sample\")\nIO.puts(:stderr, \"error\")\n\nEnum.each(IO.stream(:stdio, :line), \u0026amp;IO.write(\u0026amp;1))\n\nIO.warn(\"variable bar is unused\")\n\n\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"54:1-54:14\">\n<span id=\"実行結果\" class=\"fragment\"></span><a href=\"#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C\"><i class=\"fa fa-link\"></i></a>実行結果</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"56:1-74:3\"><div class=\"highlight\"><pre><code>æß\nabc\nstring\nWhat is your name?\na\n\n\u0026lt;\u0026lt;0, 1, 2\u0026gt;\u0026gt;\nbefore: [1, 2, 3]\nafter: [2, 4, 6]\n12\n4\n\u0026lt;\u0026lt;1, 2, 3, 1, 2, 3, 4, 5, 4, 6\u0026gt;\u0026gt;\n\u0026lt;\u0026lt;1, 2, 3\u0026gt;\u0026gt;\nHello World!\nsamplehello\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"76:1-76:11\">\n<span id=\"成果物\" class=\"fragment\"></span><a href=\"#%E6%88%90%E6%9E%9C%E7%89%A9\"><i class=\"fa fa-link\"></i></a>成果物</h1>\n<p data-sourcepos=\"78:1-78:64\"><qiita-embed-ogp src=\"https://paiza.io/projects/NqMuOgj4YB0PprBTHr2kAQ?language=elixir\"></qiita-embed-ogp></p>\n<p data-sourcepos=\"81:1-81:9\">以上。</p>\n","body":"# 概要\npaiza.ioでelixirやってみた。\nIO使ってみた。\n\n# サンプルコード\n\n```\n\nIO.chardata_to_string([0x00E6, 0x00DF])\n|> IO.puts\nIO.chardata_to_string([0x0061, \"bc\"])\n|> IO.puts\nIO.chardata_to_string(\"string\")\n|> IO.puts\n\nIO.gets(\"What is your name?\\n\")\n|> IO.puts\n\nIO.inspect(<<0, 1, 2>>, width: 40)\n\n[1, 2, 3]\n|> IO.inspect(label: \"before\")\n|> Enum.map(\u0026(\u00261 * 2))\n|> IO.inspect(label: \"after\")\n|> Enum.sum()\n|> IO.puts\n\nIO.iodata_length([1, 2 | <<3, 4>>])\n|> IO.puts\n\nbin1 = <<1, 2, 3>>\nbin2 = <<4, 5>>\nbin3 = <<6>>\nIO.iodata_to_binary([bin1, 1, [2, 3, bin2], 4 | bin3])\n|> IO.inspect\n\nbin = <<1, 2, 3>>\nIO.iodata_to_binary(bin)\n|> IO.inspect\n\nIO.puts(\"Hello World!\")\nIO.write(\"sample\")\nIO.puts(:stderr, \"error\")\n\nEnum.each(IO.stream(:stdio, :line), \u0026IO.write(\u00261))\n\nIO.warn(\"variable bar is unused\")\n\n\n\n\n```\n\n# 実行結果\n\n```\næß\nabc\nstring\nWhat is your name?\na\n\n<<0, 1, 2>>\nbefore: [1, 2, 3]\nafter: [2, 4, 6]\n12\n4\n<<1, 2, 3, 1, 2, 3, 4, 5, 4, 6>>\n<<1, 2, 3>>\nHello World!\nsamplehello\n\n\n```\n\n# 成果物\n\nhttps://paiza.io/projects/NqMuOgj4YB0PprBTHr2kAQ?language=elixir\n\n\n以上。\n","coediting":false,"comments_count":0,"created_at":"2022-11-08T20:25:48+09:00","group":null,"id":"1565c659d6cd66f30776","likes_count":1,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Elixir","versions":[]},{"name":"paiza.IO","versions":[]}],"title":"paiza.ioでelixir その53","updated_at":"2022-11-08T20:25:48+09:00","url":"https://qiita.com/ohisama@github/items/1565c659d6cd66f30776","user":{"description":null,"facebook_id":null,"followees_count":0,"followers_count":59,"github_login_name":"ohisama","id":"ohisama@github","items_count":3006,"linkedin_id":null,"location":null,"name":"","organization":null,"permanent_id":18104,"profile_image_url":"https://secure.gravatar.com/avatar/2e0bb506fbe90e6572bf92fa05db88d3?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","team_only":false,"twitter_screen_name":null,"website_url":null},"page_views_count":null,"team_membership":null},{"rendered_body":"<h1 data-sourcepos=\"1:1-1:8\">\n<span id=\"概要\" class=\"fragment\"></span><a href=\"#%E6%A6%82%E8%A6%81\"><i class=\"fa fa-link\"></i></a>概要</h1>\n<p data-sourcepos=\"2:1-3:23\">paiza.ioでelixirやってみた。<br>\nRegex使ってみた。</p>\n<h1 data-sourcepos=\"5:1-5:23\">\n<span id=\"サンプルコード\" class=\"fragment\"></span><a href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89\"><i class=\"fa fa-link\"></i></a>サンプルコード</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"7:1-46:3\"><div class=\"highlight\"><pre><code>\nRegex.compile(\"foo\")\n|\u0026gt; IO.inspect\n\nRegex.escape(\".\")\n|\u0026gt; IO.inspect\n\nRegex.match?(~r/foo/, \"foo\")\n|\u0026gt; IO.inspect\n\nRegex.named_captures(~r/c(?\u0026lt;foo\u0026gt;d)/, \"abcd\")\n|\u0026gt; IO.inspect\n\nRegex.names(~r/(?\u0026lt;foo\u0026gt;bar)/)\n|\u0026gt; IO.inspect\n\nRegex.opts(~r/foo/m)\n|\u0026gt; IO.inspect\n\nRegex.replace(~r/b/, \"abc\", \"d\")\n|\u0026gt; IO.inspect\n\nRegex.run(~r/c(d)/, \"abcd\")\n|\u0026gt; IO.inspect\n\nRegex.scan(~r/c(d|e)/, \"abcd abce\")\n|\u0026gt; IO.inspect\n\nRegex.source(~r/foo/)\n|\u0026gt; IO.inspect\n\nRegex.split(~r{-}, \"a-b-c\")\n|\u0026gt; IO.inspect\n\n\n\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"48:1-48:14\">\n<span id=\"実行結果\" class=\"fragment\"></span><a href=\"#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C\"><i class=\"fa fa-link\"></i></a>実行結果</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"50:1-63:3\"><div class=\"highlight\"><pre><code>{:ok, ~r/foo/}\n\"\\\\.\"\ntrue\n%{\"foo\" =\u0026gt; \"d\"}\n[\"foo\"]\n\"m\"\n\"adc\"\n[\"cd\", \"d\"]\n[[\"cd\", \"d\"], [\"ce\", \"e\"]]\n\"foo\"\n[\"a\", \"b\", \"c\"]\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"65:1-65:11\">\n<span id=\"成果物\" class=\"fragment\"></span><a href=\"#%E6%88%90%E6%9E%9C%E7%89%A9\"><i class=\"fa fa-link\"></i></a>成果物</h1>\n<p data-sourcepos=\"68:1-68:64\"><qiita-embed-ogp src=\"https://paiza.io/projects/gmPLW-JjBt_aDcSskc14Ww?language=elixir\"></qiita-embed-ogp></p>\n<p data-sourcepos=\"70:1-70:9\">以上。</p>\n","body":"# 概要\npaiza.ioでelixirやってみた。\nRegex使ってみた。\n\n# サンプルコード\n\n```\n\nRegex.compile(\"foo\")\n|> IO.inspect\n\nRegex.escape(\".\")\n|> IO.inspect\n\nRegex.match?(~r/foo/, \"foo\")\n|> IO.inspect\n\nRegex.named_captures(~r/c(?<foo>d)/, \"abcd\")\n|> IO.inspect\n\nRegex.names(~r/(?<foo>bar)/)\n|> IO.inspect\n\nRegex.opts(~r/foo/m)\n|> IO.inspect\n\nRegex.replace(~r/b/, \"abc\", \"d\")\n|> IO.inspect\n\nRegex.run(~r/c(d)/, \"abcd\")\n|> IO.inspect\n\nRegex.scan(~r/c(d|e)/, \"abcd abce\")\n|> IO.inspect\n\nRegex.source(~r/foo/)\n|> IO.inspect\n\nRegex.split(~r{-}, \"a-b-c\")\n|> IO.inspect\n\n\n\n\n\n```\n\n# 実行結果\n\n```\n{:ok, ~r/foo/}\n\"\\\\.\"\ntrue\n%{\"foo\" => \"d\"}\n[\"foo\"]\n\"m\"\n\"adc\"\n[\"cd\", \"d\"]\n[[\"cd\", \"d\"], [\"ce\", \"e\"]]\n\"foo\"\n[\"a\", \"b\", \"c\"]\n\n```\n\n# 成果物\n\n\nhttps://paiza.io/projects/gmPLW-JjBt_aDcSskc14Ww?language=elixir\n\n以上。\n","coediting":false,"comments_count":0,"created_at":"2022-11-08T18:41:42+09:00","group":null,"id":"e2e43065d3e9906f3f95","likes_count":1,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Elixir","versions":[]},{"name":"paiza.IO","versions":[]}],"title":"paiza.ioでelixir その52","updated_at":"2022-11-08T18:41:42+09:00","url":"https://qiita.com/ohisama@github/items/e2e43065d3e9906f3f95","user":{"description":null,"facebook_id":null,"followees_count":0,"followers_count":59,"github_login_name":"ohisama","id":"ohisama@github","items_count":3006,"linkedin_id":null,"location":null,"name":"","organization":null,"permanent_id":18104,"profile_image_url":"https://secure.gravatar.com/avatar/2e0bb506fbe90e6572bf92fa05db88d3?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","team_only":false,"twitter_screen_name":null,"website_url":null},"page_views_count":null,"team_membership":null},{"rendered_body":"<h1 data-sourcepos=\"1:1-1:8\">\n<span id=\"概要\" class=\"fragment\"></span><a href=\"#%E6%A6%82%E8%A6%81\"><i class=\"fa fa-link\"></i></a>概要</h1>\n<p data-sourcepos=\"2:1-3:30\">paiza.ioでelixirやってみた。<br>\n練習問題やってみた。</p>\n<h1 data-sourcepos=\"5:1-5:14\">\n<span id=\"練習問題\" class=\"fragment\"></span><a href=\"#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C\"><i class=\"fa fa-link\"></i></a>練習問題</h1>\n<p data-sourcepos=\"6:1-6:36\">マルチタスクを実装せよ。</p>\n<h1 data-sourcepos=\"8:1-8:23\">\n<span id=\"サンプルコード\" class=\"fragment\"></span><a href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89\"><i class=\"fa fa-link\"></i></a>サンプルコード</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"10:1-102:3\"><div class=\"highlight\"><pre><code>defmodule Tsk0 do\n\tdef tick(agent, interval \\\\ 50) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -\u0026gt; \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task0\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026amp;(\u0026amp;1))\n\tend\n\tdef succ() do\n\t\tfn(l) -\u0026gt; \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\ndefmodule Tsk1 do\n\tdef tick(agent, interval \\\\ 100) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -\u0026gt; \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task1\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026amp;(\u0026amp;1))\n\tend\n\tdef succ() do\n\t\tfn(l) -\u0026gt; \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\ndefmodule Tsk2 do\n\tdef tick(agent, interval \\\\ 200) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -\u0026gt; \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task2\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026amp;(\u0026amp;1))\n\tend\n\tdef succ() do\n\t\tfn(l) -\u0026gt; \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\n\nTsk0.start(Foo) \n|\u0026gt; IO.inspect\nTsk1.start(Foo1) \n|\u0026gt; IO.inspect\nTsk2.start(Foo2) \n|\u0026gt; IO.inspect\nTask.async(fn -\u0026gt; \n\tTsk0.tick(Foo) \nend) \nTask.async(fn -\u0026gt; \n\tTsk1.tick(Foo1) \nend) \nTask.async(fn -\u0026gt; \n\tTsk2.tick(Foo2) \nend) \n:timer.sleep(300)\n\n\n</code></pre></div></div>\n<h1 data-sourcepos=\"104:1-104:14\">\n<span id=\"実行結果\" class=\"fragment\"></span><a href=\"#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C\"><i class=\"fa fa-link\"></i></a>実行結果</h1>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"106:1-123:3\"><div class=\"highlight\"><pre><code>{:ok, #PID\u0026lt;0.101.0\u0026gt;}\n{:ok, #PID\u0026lt;0.102.0\u0026gt;}\n{:ok, #PID\u0026lt;0.103.0\u0026gt;}\ntask0\ntask1\ntask2\ntask0\ntask1\ntask0\ntask0\ntask2\ntask1\ntask0\ntask0\ntask1\ntask0\n</code></pre></div></div>\n<h1 data-sourcepos=\"125:1-125:2\"></h1>\n<p data-sourcepos=\"127:1-127:64\"><qiita-embed-ogp src=\"https://paiza.io/projects/PEFpcABIF8e9UfAsINQSgg?language=elixir\"></qiita-embed-ogp></p>\n<p data-sourcepos=\"129:1-129:9\">以上。</p>\n","body":"# 概要\npaiza.ioでelixirやってみた。\n練習問題やってみた。\n\n# 練習問題\nマルチタスクを実装せよ。\n\n# サンプルコード\n\n```\ndefmodule Tsk0 do\n\tdef tick(agent, interval \\\\ 50) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -> \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task0\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026(\u00261))\n\tend\n\tdef succ() do\n\t\tfn(l) -> \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\ndefmodule Tsk1 do\n\tdef tick(agent, interval \\\\ 100) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -> \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task1\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026(\u00261))\n\tend\n\tdef succ() do\n\t\tfn(l) -> \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\ndefmodule Tsk2 do\n\tdef tick(agent, interval \\\\ 200) do\n\t\tcast(agent)\n\t\t:timer.sleep(interval)\n\t\ttick(agent, interval)\n\tend\n\tdef start(agent) do\n\t\tAgent.start(fn -> \n\t\t\t[0] \n\t\tend, name: agent)\n\tend\n\tdef cast(agent) do\n\t\tAgent.update(agent, __MODULE__.succ())\n\t\tIO.puts(\"task2\")\n\tend\n\tdef get(agent) do\n\t\tAgent.get(agent, \u0026(\u00261))\n\tend\n\tdef succ() do\n\t\tfn(l) -> \n\t\t\t[hd(l) + 1 | l] \n\t\tend\n\tend\nend\n\nTsk0.start(Foo) \n|> IO.inspect\nTsk1.start(Foo1) \n|> IO.inspect\nTsk2.start(Foo2) \n|> IO.inspect\nTask.async(fn -> \n\tTsk0.tick(Foo) \nend) \nTask.async(fn -> \n\tTsk1.tick(Foo1) \nend) \nTask.async(fn -> \n\tTsk2.tick(Foo2) \nend) \n:timer.sleep(300)\n\n\n```\n\n# 実行結果\n\n```\n{:ok, #PID<0.101.0>}\n{:ok, #PID<0.102.0>}\n{:ok, #PID<0.103.0>}\ntask0\ntask1\ntask2\ntask0\ntask1\ntask0\ntask0\ntask2\ntask1\ntask0\ntask0\ntask1\ntask0\n```\n\n# \n\nhttps://paiza.io/projects/PEFpcABIF8e9UfAsINQSgg?language=elixir\n\n以上。\n","coediting":false,"comments_count":0,"created_at":"2022-11-08T15:54:01+09:00","group":null,"id":"621c9f15b1e1ff56d5cd","likes_count":1,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"Elixir","versions":[]},{"name":"paiza.IO","versions":[]}],"title":"paiza.ioでelixir その50","updated_at":"2022-11-08T15:54:37+09:00","url":"https://qiita.com/ohisama@github/items/621c9f15b1e1ff56d5cd","user":{"description":null,"facebook_id":null,"followees_count":0,"followers_count":59,"github_login_name":"ohisama","id":"ohisama@github","items_count":3006,"linkedin_id":null,"location":null,"name":"","organization":null,"permanent_id":18104,"profile_image_url":"https://secure.gravatar.com/avatar/2e0bb506fbe90e6572bf92fa05db88d3?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","team_only":false,"twitter_screen_name":null,"website_url":null},"page_views_count":null,"team_membership":null},{"rendered_body":"<h1 data-sourcepos=\"1:1-1:14\">\n<span id=\"はじめに\" class=\"fragment\"></span><a href=\"#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\"><i class=\"fa fa-link\"></i></a>はじめに</h1>\n<blockquote class=\"twitter-tweet\">\n<p>Phoenix 1.7.0-rc.0 is out! So much good stuff in this release – <a href=\"https://twitter.com/tailwindcss?ref_src=twsrc%5Etfw\" rel=\"nofollow noopener\" target=\"_blank\">@tailwindcss</a> by default, HTML-aware component system with compile-time checks, verified routes, and more!<br><br>👉<a href=\"https://t.co/lMjW4fGEKd\" rel=\"nofollow noopener\" target=\"_blank\">https://t.co/lMjW4fGEKd</a></p>— Chris McCord (@chris_mccord) <a href=\"https://twitter.com/chris_mccord/status/1589721565692067840?ref_src=twsrc%5Etfw\" rel=\"nofollow noopener\" target=\"_blank\">November 7, 2022</a>\n</blockquote> <script async src=\"https://platform.twitter.com/widgets.js\"></script>\n<p data-sourcepos=\"5:1-7:66\">さっそく試してみました。<br>\nすでに試された方もいらっしゃるとおもいます。<br>\nざーっと表面的なことだけを速報しておきます。</p>\n<p data-sourcepos=\"9:1-9:94\">Phoenix 1.7.0-rc.0 のデフォルトプロジェクトを立ち上げたときの図です。</p>\n<p data-sourcepos=\"11:1-11:162\"><a href=\"https://camo.qiitausercontent.com/f41c57d3b130081a1ac11016d60116a95817cdd8/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133313830382f33356332363135352d313361622d376562302d396562302d6666626564363938333964322e706e67\" target=\"_blank\" rel=\"nofollow noopener\"><img src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F131808%2F35c26155-13ab-7eb0-9eb0-ffbed69839d2.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=44206380a6c5a5151e23bdeb4f0d1264\" alt=\"スクリーンショット 2022-11-08 9.31.24.png\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/35c26155-13ab-7eb0-9eb0-ffbed69839d2.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F131808%2F35c26155-13ab-7eb0-9eb0-ffbed69839d2.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=33c08d25f5c4083b2e658e670fe4f184 1x\" loading=\"lazy\"></a></p>\n<h1 data-sourcepos=\"14:1-14:20\">\n<span id=\"ドキュメント\" class=\"fragment\"></span><a href=\"#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88\"><i class=\"fa fa-link\"></i></a>ドキュメント</h1>\n<p data-sourcepos=\"16:1-16:229\"><a href=\"https://phoenixframework.org/blog/phoenix-1.7-released\" rel=\"nofollow noopener\" target=\"_blank\">Phoenix 1.7-rc released: Built-in Tailwind, Verified Routes, and more</a>が、<a href=\"https://twitter.com/chris_mccord\" rel=\"nofollow noopener\" target=\"_blank\">Chris McCord</a>御大が書かれたドキュメントです。</p>\n<p data-sourcepos=\"18:1-18:54\"><qiita-embed-ogp src=\"https://phoenixframework.org/blog/phoenix-1.7-released\"></qiita-embed-ogp></p>\n<h1 data-sourcepos=\"20:1-20:20\">\n<span id=\"インストール\" class=\"fragment\"></span><a href=\"#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB\"><i class=\"fa fa-link\"></i></a>インストール</h1>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"22:1-24:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>mix archive.install hex phx_new 1.7.0-rc.0\n</code></pre></div>\n</div>\n<p data-sourcepos=\"26:1-26:27\">エラーがでました。</p>\n<div class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"28:1-36:3\"><div class=\"highlight\"><pre><code>Resolving Hex dependencies...\nDependency resolution completed:\nNew:\n phx_new 1.7.0-rc.0\n* Getting phx_new (Hex package)\nAll dependencies are up to date\n** (Mix) You're trying to run :phx_new on Elixir v1.13.1 but it has declared in its mix.exs file it supports only Elixir ~\u0026gt; 1.14\n</code></pre></div></div>\n<p data-sourcepos=\"38:1-40:57\"><a href=\"https://elixir-lang.org/\" rel=\"nofollow noopener\" target=\"_blank\">Elixir</a>は1.14以上が必要とのことです。<br>\n私は、<a href=\"https://asdf-vm.com/\" rel=\"nofollow noopener\" target=\"_blank\">asdf</a>を使っています。<br>\n以下のようにしてインストールしました。</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"42:1-48:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>asdf update\n\nasdf install erlang 25.1.2\n\nasdf install elixir 1.14.1-otp-25\n</code></pre></div>\n</div>\n<p data-sourcepos=\"50:1-51:74\">以下の通りにやる必要はありません。<br>\n私は<code>1.7</code>というフォルダを作りました、という例です。</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"54:1-60:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>mkdir 1.7\ncd 1.7\nasdf local elixir 1.14.1-otp-25\nasdf local erlang 25.1.2\nasdf reshim\n</code></pre></div>\n</div>\n<p data-sourcepos=\"62:1-62:24\">氣を取り直して、</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"64:1-66:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>mix archive.install hex phx_new 1.7.0-rc.0\n</code></pre></div>\n</div>\n<p data-sourcepos=\"68:1-68:63\">インストールできました<img alt=\":tada:\" class=\"emoji\" height=\"20\" src=\"https://cdn.qiita.com/emoji/twemoji/unicode/1f389.png\" title=\":tada:\" width=\"20\" loading=\"lazy\"><img alt=\":tada:\" class=\"emoji\" height=\"20\" src=\"https://cdn.qiita.com/emoji/twemoji/unicode/1f389.png\" title=\":tada:\" width=\"20\" loading=\"lazy\"><img alt=\":tada:\" class=\"emoji\" height=\"20\" src=\"https://cdn.qiita.com/emoji/twemoji/unicode/1f389.png\" title=\":tada:\" width=\"20\" loading=\"lazy\"><img alt=\":tada:\" class=\"emoji\" height=\"20\" src=\"https://cdn.qiita.com/emoji/twemoji/unicode/1f389.png\" title=\":tada:\" width=\"20\" loading=\"lazy\"><img alt=\":tada:\" class=\"emoji\" height=\"20\" src=\"https://cdn.qiita.com/emoji/twemoji/unicode/1f389.png\" title=\":tada:\" width=\"20\" loading=\"lazy\"></p>\n<h1 data-sourcepos=\"70:1-70:21\">\n<span id=\"postgresqlの起動\" class=\"fragment\"></span><a href=\"#postgresql%E3%81%AE%E8%B5%B7%E5%8B%95\"><i class=\"fa fa-link\"></i></a>PostgreSQLの起動</h1>\n<p data-sourcepos=\"72:1-72:36\">私は、Dockerを使いました。</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"74:1-76:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>docker run -d --rm -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres postgres:15\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"78:1-78:29\">\n<span id=\"プロジェクトの作成\" class=\"fragment\"></span><a href=\"#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90\"><i class=\"fa fa-link\"></i></a>プロジェクトの作成</h1>\n<p data-sourcepos=\"80:1-80:43\"><code>hello</code>プロジェクトを作ります。</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"82:1-86:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>mix phx.new hello\ncd hello\nmix setup\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"88:1-88:5\">\n<span id=\"run\" class=\"fragment\"></span><a href=\"#run\"><i class=\"fa fa-link\"></i></a>Run</h1>\n<p data-sourcepos=\"90:1-90:33\">迷わず動かしてみます。</p>\n<div class=\"code-frame\" data-lang=\"\" data-sourcepos=\"92:1-94:3\">\n<div class=\"code-lang\"><span class=\"bold\">CMD</span></div>\n<div class=\"highlight\"><pre><code>mix phx.server\n</code></pre></div>\n</div>\n<p data-sourcepos=\"96:1-96:29\">Visit: <a href=\"http://localhost:4000/\" class=\"autolink\" rel=\"nofollow noopener\" target=\"_blank\">http://localhost:4000/</a></p>\n<p data-sourcepos=\"99:1-99:162\"><a href=\"https://camo.qiitausercontent.com/25b4c443fbd57422f398a3bc91dd6bb478e702b5/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133313830382f38663039303136382d613863652d303539622d353334642d3637633663306263306639382e706e67\" target=\"_blank\" rel=\"nofollow noopener\"><img src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F131808%2F8f090168-a8ce-059b-534d-67c6c0bc0f98.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=497f78c960b73fa79334064830ba6239\" alt=\"スクリーンショット 2022-11-08 9.31.24.png\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/8f090168-a8ce-059b-534d-67c6c0bc0f98.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F131808%2F8f090168-a8ce-059b-534d-67c6c0bc0f98.png?ixlib=rb-4.0.0\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=22491b9a03dea0291e20912df93620af 1x\" loading=\"lazy\"></a></p>\n<p data-sourcepos=\"101:1-101:33\">うぉーかっこいい!!!</p>\n<p data-sourcepos=\"103:1-103:63\">以下、速報レベルでさらっと書いておきます。</p>\n<h1 data-sourcepos=\"105:1-105:59\">\n<span id=\"tailwindcssがデフォルト\" class=\"fragment\"></span><a href=\"#tailwindcss%E3%81%8C%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88\"><i class=\"fa fa-link\"></i></a><a href=\"https://tailwindcss.com/\" rel=\"nofollow noopener\" target=\"_blank\">TailwindCSS</a>がデフォルト</h1>\n<p data-sourcepos=\"107:1-107:58\">カッコいいトップ画面の<code>.heex</code>はこれです。</p>\n<blockquote data-sourcepos=\"109:1-110:9\">\n<p data-sourcepos=\"109:3-110:9\">Phoenix 1.7 ships with TailwindCSS by default, with no dependency on nodejs on the system.<br>\nです。</p>\n</blockquote>\n<p data-sourcepos=\"112:1-112:66\"><a href=\"https://tailwindcss.com/\" rel=\"nofollow noopener\" target=\"_blank\">TailwindCSS</a>がデフォルトです。</p>\n<div class=\"code-frame\" data-lang=\"elixir\" data-sourcepos=\"114:1-352:3\">\n<div class=\"code-lang\"><span class=\"bold\">lib/hello_web/controllers/page_html/home.html.heex</span></div>\n<div class=\"highlight\"><pre><code><span class=\"o\">\u0026lt;</span><span class=\"n\">div</span> <span class=\"n\">class</span><span class=\"o\">=</span><span class=\"s2\">\"fixed inset-y-0 right-0 left-[40rem] hidden lg:block xl:left-[50rem]\"</span><span class=\"o\">\u0026gt;</span>\n <span class=\"o\">\u0026lt;</span><span class=\"n\">svg</span>\n <span class=\"n\">viewBox</span><span class=\"o\">=</span><span class=\"s2\">\"0 0 1480 957\"</span>\n <span class=\"n\">fill</span><span class=\"o\">=</span><span class=\"s2\">\"none\"</span>\n <span class=\"n\">aria</span><span class=\"o\">-</span><span class=\"n\">hidden</span><span class=\"o\">=</span><span class=\"s2\">\"true\"</span>\n <span class=\"n\">class</span><span class=\"o\">=</span><span class=\"s2\">\"absolute inset-0 h-full w-full\"</span>\n <span class=\"n\">preserveAspectRatio</span><span class=\"o\">=</span><span class=\"s2\">\"xMinYMid slice\"</span>\n <span class=\"o\">\u0026gt;</span>\n <span class=\"o\">\u0026lt;</span><span class=\"n\
成果物
以上。