DRYな備忘録

Don't Repeat Yourself.

Azure CLIを使ってインスタンスの作成、sshまで

前回 Azureことはじめ - DRYな備忘録 をやったので、今回はCLIをやります。

とりあえずbrewでやるか

% brew update
% brew search azure-cli
% brew install azure-cli
% which az
/usr/local/bin/az
% az --version
pyenv: python3.6: command not found

The `python3.6' command exists in these Python versions:
  3.6.1

うーん、Python。とりあえずローカルで動くようにしてみるか。

% pyenv install 3.6.0
% cd /tmp
% pyenv local 3.6.0
% az --version
azure-cli (2.0.22)

# 以下略

とりあえずローカルでazコマンドがうごくようになった。

というのがだるいので

docker使お?ね?

% docker run -it --rm azuresdk/azure-cli-python
Unable to find image 'azuresdk/azure-cli-python:latest' locally
latest: Pulling from azuresdk/azure-cli-python
# 中略
Status: Downloaded newer image for azuresdk/azure-cli-python:latest
bash-4.3#
bash-4.3# az --version
azure-cli (2.0.23)

# 以下略
bash-4.3# exit
% docker 

これで十分である。

ということで、brew uninstall azure-cliしてめでたしめでたし。

ログインをする必要がある

% docker run -it azuresdk/azure-cli-python
bash-4.3#
bash-4.3# az login
To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code XXXXXXX to authenticate.

ほう。gcloud init とかでは、callback付きのURLを開かせて、ブラウザで表示されたワンタイムトークンをCLIに食わせるタイプだったけど、az loginだと、CLIが表示するワンタイムトークンをブラウザに食わせて認証を完了させるタイプなのか。

で、ブラウザで https://aka.ms/devicelogin に行き、 XXXXXXX を食わせると、認証が完了し、

bash-4.3# az account list

で、確認できる。

Computeインスタンスをつくるまでのみちのり

まず、location idのリストがインターネッツに一切無いという...

bash-4.3# az account list-locations | grep -B1 -A6 Japan
  {
    "displayName": "Japan West",
    "id": "/subscriptions/caa7f0e9-5fbf-4ba0-971d-4e038b0deaff/locations/japanwest",
    "latitude": "34.6939",
    "longitude": "135.5022",
    "name": "japanwest",
    "subscriptionId": null
  },
  {
    "displayName": "Japan East",
    "id": "/subscriptions/caa7f0e9-5fbf-4ba0-971d-4e038b0deaff/locations/japaneast",
    "latitude": "35.68",
    "longitude": "139.77",
    "name": "japaneast",
    "subscriptionId": null
  },

japaneast やね。

Resource Groupをつくる

bash-4.3# az group create -n myRG -l japaneast
bash-4.3# az group list

できてることが確認できる。

Computeインスタンスつくる。

まずssh keyつくって

bash-4.3# mkdir -p ~/.ssh/azure
bash-4.3# ssh-keygen -f ~/.ssh/azure/id_rsa
bash-4.3# chmod 600 ~/.ssh/azure/id_rsa.pub

いざ

bash-4.3# az vm create -n TestTestHoge \
  -g myRG \
  --size Standard_A0 \
  --image debian \
  --admin-username otiai10 \
  --ssh-key-value ~/.ssh/azure/id_rsa.pub

レスポンス↓

{
  "fqdns": "",
  "id": "/subscriptions/xxxxxx/resourceGroups/myRG/providers/Microsoft.Compute/virtualMachines/TestTestHoge",
  "location": "japaneast",
  "macAddress": "00-0D-3A-50-66-07",
  "powerState": "VM running",
  "privateIpAddress": "10.0.0.4",
  "publicIpAddress": "52.243.44.159",
  "resourceGroup": "myRG",
  "zones": ""
}

確認

bash-4.3# az vm list

sshしてみる

bash-4.3# ssh -i ~/.ssh/azure/id_rsa otiai10@52.243.44.159
otiai10@TestTestHoge:~$
otiai10@TestTestHoge:~$ uname -a
Linux TestTestHoge 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2+deb8u5 (2017-09-19) x86_64 GNU/Linux
otiai10@TestTestHoge:~$
otiai10@TestTestHoge:~$ exit
bash-4.3# uname -a
Linux 58218864392b 4.9.49-moby #1 SMP Fri Dec 8 13:40:02 UTC 2017 x86_64 Linux
bash-4.3#

いい感じ。

あとかたづけ

まずリソース一覧を取得したい

bash-4.3# az resource list -g myRG -l japaneast

つぎに、消せるものから消していく。

まずはVM

bash-4.3# az resource list -g myRG -l japaneast --resource-type=Microsoft.compute/virtualmachines
[
  {}
]
bash-4.3# az vm delete -g myRG -n TestTestHoge
bash-4.3# az resource list -g myRG -l japaneast --resource-type=Microsoft.compute/virtualmachines
[]

done。

Public IP Address消す。

bash-4.3# az resource list -g myRG -l japaneast --resource-type=Microsoft.Network/publicIPAddresses
bash-4.3# az network public-ip list -g myRG
[
  {}
]
bash-4.3# az network public-ip delete -n TestTestHogePublicIP -g myRG
# ネットワークインターフェースを先に削除しろというエラー
bash-4.3# az network nic list -g myRG
[
  {}
]
bash-4.3# az network nic delete -n TestTestHogeVMNic -g myRG
bash-4.3# az network nic list -g myRG
[]
bash-4.3# az network public-ip delete -n TestTestHogePublicIP -g myRG
bash-4.3# az network public-ip list -g myRG
[]

done。

Disk消すか。

bash-4.3# az disk list -g myRG
[
  {}
]
bash-4.3# az disk delete -n TestTestHoge_OsDisk_1_86297f169b6045618fb6c40fe2172657 -g myRG
bash-4.3# az disk list -g myRG
[]

done。

SecurityGroup消す。

bash-4.3# az resource list -g myRG --resource-type=Microsoft.Network/networkSecurityGroups
[
  {}
]
bash-4.3# az resource delete -n TestTestHogeNSG -g myRG --resource-type=Microsoft.Network/networkSecurityGroups
bash-4.3# az resource list -g myRG --resource-type=Microsoft.Network/networkSecurityGroups
[]

ラスト、VN消す。

bash-4.3# az resource list -g myRG
[
  {}
]
bash-4.3# az resource delete -n TestTestHogeVNET -g myRG --resource-type=Microsoft.Network/virtualNetworks
bash-4.3# az resource list -g myRG
[]

これで綺麗になった。

f:id:otiai10:20171217185431p:plain

雑感

  • azure cli、べんり。というか親切。--helpが充実している。
  • 5000兆円とか言わないので、200万円ぐらいほしい。

DRYな備忘録として

Azureことはじめ

アカウント登録

が終わった図↓

f:id:otiai10:20171217105454p:plain

Computeリソースの作成

f:id:otiai10:20171217134811p:plain

必要な前提作業があった

  • AWSなどと違い、インスタンスsshするためのIdentityファイルを自分で作成する必要がある
    • ssh-keygen -f ~/.ssh/azure/id_rsa みたいにしてつくった
  • Azureでは、Accountに紐付いたクレジットカードと、さらにそれに紐付いたSubscriptionというモデルをつくる必要がある(画像赤枠部分に警告が出ている場合)

f:id:otiai10:20171217135223p:plain

次に、インスタンスタイプを選ぶ。ここでスペックを選べる。ここで提示されてるestimated price、完全に購買障壁になってる気がするんだけど。

f:id:otiai10:20171217133326p:plain

Public IPなんかはここでNoneに指定できるようだ。今回はローカルから直でsshしたいので、とりあえずpublic ipつけとく。

f:id:otiai10:20171217135517p:plain

インスタンス立った

2,3分ぐるぐるがあったのち、インスタンスが立つ。

f:id:otiai10:20171217140538p:plain

Public IP Addressをモザイクかけるか迷ったけど、まあどうせすぐ殺すしええやろ。

sshを試みる

% ssh -i ~/.ssh/azure/id_rsa 13.78.120.58
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.11.0-1016-azure x86_64)

otiai10@testtest:~$ uname -a
Linux testtest 4.11.0-1016-azure #16-Ubuntu SMP Tue Dec 5 22:52:08 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
otiai10@testtest:~$

いいですね!

Webサーバでも立ててみるか

せっかくPublic IP Addressがあるので、ウェブサーバでも立ててみるか、というはこびになった。まぁGoでいっか。

otiai10@testtest:~$ sudo apt-get update -qq
otiai10@testtest:~$ sudo apt-get install -qq -y golang vim
otiai10@testtest:~$ vi server.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Request has come!")
        fmt.Fprintf(w, "Hello! This is a server running on Azure!!")
    })
    fmt.Println("The server is up on port 9980")
    http.ListenAndServe(":9980", nil)
}
otiai10@testtest:~$ go run server.go
The server is up on port 9980

してから、ローカルのターミナル(あるいはふつうにウェブブラウザで)

% curl http://13.78.120.58:9980/
curl: (7) Failed to connect to 13.78.120.58 port 9980: Operation timed out

oh... 到達していないような気がする。22番ポートは開いてるってことだから、9980(自分でserver.goで勝手に決めたポート)を開ける必要があるな。

SecurityGroupというものがある

f:id:otiai10:20171217142851p:plain

9980開けた。

うごいた

再度、ローカルから

% curl http://13.78.120.58:9980/
Hello! This is a server running on Azure!!%                                                                                                                                       %

同様に、ブラウザ

f:id:otiai10:20171217143310p:plain

あとかたづけ

まず単純にインスタンスを削除(delete)してみる。

f:id:otiai10:20171217143627p:plain

で、削除されたら、All resources見てみるじゃないですか?

f:id:otiai10:20171217144927p:plain

_人人人人人人人人人人_ > けっこうのこってる <  ̄YYYYYYYYYY^ ̄

  • Storage account: ストレージの管理用アカウントなんだろうな
  • Virtual network: AWSにおけるVPCみたいなものだろうな
  • Network interface: その名の通りだろうな
  • Public IP address: その名の通り。インスタンス消したら消えてもいいんだけどな
  • Network security group: はい

インスタンスを殺しても残るもの」的な意味ではわりと納得できるリソース群ですね。殺そ。

全部消して、終了。とりあえず最初なのでこんなものかというかんじ。

f:id:otiai10:20171217145604p:plain

雑感

  • 5000兆円ほしい

DRYな備忘録として

Cgoを使ったパッケージと「Docker as Bug Report/Reproduce」というOSS運用について

このエントリはGo2 Advent Calendar 2017 - Qiitaの4日目です。

2017年は、着実にエロリツイート先生として実績を上げた1年でした、otiai10です。WETな方もよろしくお願いします。

Cgoを使った文字認識ライブラリがv2になりました 🎉

Go言語には、Cgoという、Go言語からC/C++を叩いたり、C/C++からGoを叩いたりできる機能があります。(参考: Go言語のcgoことはじめ)

僕自身、Goを書き始めたぐらいから、有名な文字認識ライブラリであるTesseract-OCRのラッパーパッケージをGoで作っていたんですが、作り始めた当初はGoの知識もCの知識も無くて、ただのコマンドラッパー(つまりtesseractのbinへPATHが通ってる環境で、stdout/stdinのバッファを介する入出力)の部分がありました。これはかっこよくない。

ので、苦節3年この度、上記のcgoを使って、完全にTesseractのC++APIをブリッジする形に作り直しました 🎉

github.com

Cgoの使い方・その他詳細については、Goのアドベントカレンダーは今年「その4」まであるんで、きっと誰かがやると思うし、本エントリでは上記OSSの運用について、Dockerがめっちゃ便利やったで!という話をしたいと思います。Dockerって内部実装はGoだし、まあGoアドベントカレンダーでいいでしょ。

Cgoを使ったパッケージの「Portability」

Go言語の魅力のひとつに、Potability(可搬性)があります。Go言語はGo自身が依存するCのライブラリなどが無いため、たとえばマシンにPythonをインストールしようするときにBuild Failedになったりとかそういうことがなく、ダウンロードページからtar落としてきて展開してPATH通したら今日からあなたもGopherになれます。Enjoy!

また、Go内部に各プラットフォーム、たとばWindows用のコンパイラの実装を持つので、MacOS上でWindows用の実行ファイルを出力することもできる点もGoの魅力的な「可搬性」と言っていいでしょう。

ただしCgoお前は別だ。

GoConでもid:hajimehoshiさんがぼやいていました。当たり前っちゃ当たり前なんですが、Cgoで、GoのソースからC/C++を参照するときは、当然マシンにC/C++のオブジェクトファイル・ヘッダファイルがインストールされていて、ライブラリをインストールしたパスにLD_INCLUDE_PATHなどが通ってる必要があります。そして、OSSとして公開する以上「俺の環境で動かねえんだが」みたいなissueはボカスカ投げつけられてくるわけです。勉強になります。

Docker as Bug Report/Reproduce という運用

様々な環境から投げつけられるissueのつらさは、主に以下の2点に集約されるかと感じています

  1. 手元で再現できない
  2. 問題が切り分けられていない

1000歩譲って、1番は僕側がどうにかするとして、2番はissue reporter側の責任じゃね?って思うんですが、みなさんどうですか。だいたい今までのケースだと「お使いの環境はなんですか?uname -aとか、go envとかの出力ください」みたいなやりとりしてたんですが、これも結局かったるいので、もうどうせなら、

「動くバグをくれ」 🐛

という結論に達しました。どうやるか。できるんですよ。そう、Dockerならね。
"バグが動く環境" ごとDockerに固めてしまって、それをsubmitしてくれれば、Dockerfileを作る側、つまりissue reporterに問題の切り分けを強いることができるし、僕もデバグ環境が簡単に手に入って一石二鳥となります。

幸い、Travis-CIでもDockerをserviceとして利用することができるため、issue reportに使われたDockerfileをそのままCIに組み込んで「この環境で動くことは保証されました」という使い方ができ、これは便利です。

例)

FROM debian:lenny
# とかそういう古めのOS

# 再現のためのapt-getとかしてもらう
# 任意のバージョンのGoのインストール

ADD . ${GOPATH}/src/github.com/your/repo
ENTRYPOINT go test github.com/your/repo

たとえばこれなんかは、まあissue reporterではなく自分でDockerfile作ったんですが、見事にDockerfileで再現できて、最終的にDockerfileを修正することでテストもpassしたケースです。 Fail in CentOS6.7 / Tesseract3.02.02 / Golang1.7.6 · Issue #97 · otiai10/gosseract · GitHub

f:id:otiai10:20171203232626j:plain 動くバグは美味えぜ!

今後の課題

Dockerfileでテストケース書くの、基本的に良いことばっかりなんですが、唯一問題があって、CIのビルドが遅い。テストケースの数だけdocker buildしているので。

otiai10/gosseract - Travis CI

たいして厚みのあるパッケージじゃないのに、平均して30分ぐらいかかってます。これTravis-CI側にビルド済みイメージのキャッシュかなんか持たせることって可能ですか(それサポートするとディスクサイズやばそうだけど)? あるいは、Docker Hubを上手いこと使って、buildの必要が無ければpullで済ます、みたいな判定を入れるかかな。 ご意見・ご助言・ご鞭撻、お待ちしております。

まとめ

というわけで「俺の環境で動かねえんだが」というissueには「Dockerfileでくれ」みたいな殺伐さを醸し出していきましょう。*1

雑感

  • 最近Goで遺伝子解析ツールを書く仕事してる
    • 画像解析とか文字認識とかはいっさい関係ない
  • Go書いてると小さいパッケージをどんどん切り出しやすいので、GitHubリポジトリが無限に増える
  • 去年、個人開発程度のOCRサーバならHerokuに立てればいいじゃない - DRYな備忘録というのを書いたんですが、いつのまにかHerokuが任意のDockerをデプロイできるようになってて、最高。
    • そっちに移行した影響で、Deploy to Herokuボタンが死んでます。Heroku Container Registryというのを使ってるので、app.jsonに依存しないため。
  • 12月になった途端に忙しくて、師走の魔力って凄いなって思った

現場からは以上です。良いお年を! Happy Hacking

DRYな備忘録として

人工知能とか機械学習とかニューラルネットワークとかディープラーニングとかぜんぜん分からんのでインターネットかき集めてざっくり理解したリンク集とまとめ

実施したルール

  • 読み始めたら途中で投げない
    • わかんなくてもとりあえず最後まで読む
  • 100%理解しようとしない
    • ざっくりでいいので自分なりに一言でまとめる
    • ぜんぜんわからん、でも可

下記のリンクから、特に理解を助けたものの抜粋

以下、僕が読み進めたときのログなので読まなくていいです。あと、下記のリンクを読み漁ったあとの、自分なりのまとめが最後にあります。すっ飛ばしたいひとはどうぞ。







f:id:otiai10:20171112190654p:plain

すげー雑に読み漁った

  1. 機械学習とは?
    1. 機械学習 - Wikipedia
      • なお、データ集合を解析するので、統計学との関連が深い
      • 1959年、アーサー・サミュエルは、機械学習を「明示的にプログラムしなくても学習する能力をコンピュータに与える研究分野」だとした。
    2. 機械学習をこれから始める人に押さえておいてほしいこと - Qiita
    3. 「機械学習」と「ディープラーニング」は何が違うのか? | MUFG Innovation Hub
      • ディープラーニングでは区別するための「目の付けどころ」をAIが自分で学習し、その性能を向上させていく。
    4. 「機械学習とは何ぞや」をゆるーく説明してみる - 六本木で働くデータサイエンティストのブログ
      • 本人いわく古いが、参考になるものが多くあった
    5. 「統計学と機械学習の違い」はどう論じたら良いのか - 六本木で働くデータサイエンティストのブログ
      • ただ、線形モデル族のようにヒトが直感的に理解できる形でモデルが出来上がるとは限らないのが機械学習の特徴で、そこが統計学との大きな違いかもしれません。
    6. ヒトの直感的理解は単変量モデルまで、直感を超えたければ多変量モデルへ - 六本木で働くデータサイエンティストのブログ
      • このように、多変量モデルを用いることでヒトの直感的理解を超えた「全体論」的な特徴を捉えることができるというのが今回の取り組みで示したかったことです。
    7. 「正答率100%」になってしまう機械学習モデルの例を挙げてみる - 六本木で働くデータサイエンティストのブログ
      • つまり、今回のテニス四大大会のデータで言えば「同一カードでの対戦が5回とか10回とか当該期間内にある場合」なら説明変数に含めても良いわけです。
    8. おまけ: クラウド機械学習の進歩で「プラモデルのように機械学習システムが作れる」時代が到来しつつある - 六本木で働くデータサイエンティストのブログ
    9. 「ニューラルネットワーク」や「機械学習」って何?--AIの基本用語をおさらい - CNET Japan
  2. 人工知能とは?
    1. 人工知能のやさしい説明「What's AI」
    2. 人工知能は人間を超えるか ディープラーニングの先にあるもの (角川EPUB選書)
    3. 【5分でわかる】人工知能(AI)とは?概要や種類をわかりやすく解説 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
      • 雑誌っぽい読み物だった↑ かつPR
    4. 人工知能 - Wikipedia
      • 近年では「サポートベクターマシン」が注目を集めた。また、自らの経験を元に学習を行う強化学習という手法もある。
    5. 人工知能とは - IT用語辞典 Weblio辞書
    6. 人工知能(じんこうちのう)とは - コトバンク
    7. 総務省|平成28年版 情報通信白書|PDF版
  3. ニューラルネットワークとは?
    1. ニューラルネットワーク - Wikipedia
      • 狭義には誤差逆伝播法を用いた多層パーセプトロンを指す場合もあるが、
        • たぶん「機械学習」の実装パターンのうちのひとつとして、複数のニューロンが限られた演算をし、その集約としてアウトプットを出す、ということなのかな?
      • バックプロパゲーションは主に中間層が1層の時に使われ、中間層が2層以上ある時は深層学習と呼ばれ、
        • お、いいですね、深層学習の定義が出てきた
    2. ニューラルネットワークの基礎解説:仕組みや機械学習・ディープラーニングとの関係は |ビジネス+IT
      • 逆伝搬法「Back Propagation」。正解値の誤差をとり、各層にフィードバックし、重みを調整しながら、正解値に近づけていく
      • ↑ この資料はかなり分かりやすかった
    3. 「ニューラルネットワーク」とは何か:「AI」「機械学習」「ディープラーニング」は、それぞれ何が違うのか - @IT
      • 最初に生まれた、最も包括的な概念がAI。次に発展した機械学習がその中に含まれ、最後に登場したディープラーニングがさらにその中に含まれる構図だ。
    4. 数学知識もいらないゼロからのニューラルネットワーク入門 | TechCrunch Japan
      • 例えば画像認識においては、畳み込みニューラルネットワーク(Convolutional Neural Network=CNN)というタイプのニューラルネットワークが使われている。
      • モノをまとめて(本、おもちゃ、電子機器、アート、服などへ)分類していく作業についてよく知っていることだろう。畳み込みレイヤーも同じような作業を通じて、画像をピクセルの特徴ごとにバラバラにしていっているのだ。
        • なるほどなぁ
    5. ニューラルネットワークとは?人工知能の基本を初心…|Udemy メディア
    6. ニューラルネットワークと深層学習
      • 今のところ、パーセプトロンで構成されたニューラルネットワークに上手に学習させる方法は明らかになっていません。この問題は、シグモイドニューロンと呼ばれる、新しいタイプの人工ニューロンを導入することによって克服することができます。
      • 紛らわしいことに、歴史的理由から、このような複数層のネットワークをときおり多層パーセプトロン(multilayer perceptrons)、またはMLPsと呼びます。しかしこれらはパーセプトロンではなく、シグモイドニューロンです。
      • Cauchy–Schwarz inequality - Wikipedia
        • コーシー・シュワルツの不等式、なつかしすぎて吹いたww
    7. ニューラルネットワーク
    8. 強化学習入門 ~これから強化学習を学びたい人のための基礎知識~ - Platinum Data Blog by BrainPad
      • 教師付き学習、教師無し学習、強化学習、の対比がわかりやすく書かれている
  4. ディープラーニングとは?
    1. ディープラーニング(Deep Learning)とは?【入門編】 |
    2. ディープラーニング - Wikipedia
      • 前文をほぼすべて抜粋します
      • 深層学習登場以前、4層以上の深層ニューラルネットは、局所最適解や勾配消失などの技術的な問題によって充分学習させられず、性能も芳しくなかった。しかし、近年、ヒントンらによる多層ニューラルネットワークの学習の研究や、学習に必要な計算機の能力向上、および、Webの発達による訓練データ調達の容易化によって、充分学習させられるようになった。その結果、音声・画像・自然言語を対象とする問題に対し、他の手法を圧倒する高い性能を示し、2010年代に普及した。しかしながら、多層ニューラルネットが高い性能を示す要因の理論的な解明は進んでいない。
      • ここ → しかしながら、多層ニューラルネットが高い性能を示す要因の理論的な解明は進んでいない。
        • これヤバない!? めちゃくちゃ中二心くすぐられる!!
    3. ディープラーニングは何が「ディープ」なのか :日本経済新聞
    4. ディープ・ラーニングとは? | SAS
      • 具体的な用途などについて
    5. ディープラーニング – これだけは知っておきたい3つのこと - MATLAB & Simulink
    6. ディープラーニングとは - コトバンク
    7. 初心者向け「機械学習とディープラーニングの違い」をシンプルに解説 - GIGAZINE
      • ディープラーニングを用いるかべきかという動画
    8. ディープラーニングの判断根拠を理解する手法 - Qiita
      • 最後に、ディープラーニングの「解釈性」の問題
      • 「何かを学んでいるはずだが、何を学んでいるかはよくわからない」
      • 今後より多くの課題を解決していくために、これらの「説明」を行う手法はより重要になってくると思います。
      • 機械学習ないしディープラーニングは、もともと「説明」ではなく「予測」「判断」に特化して進化していき、実用に至るまでに高度に発達した一方で、1周まわって、なぜそう判断されたかが、もはや人間には理解しえない形になっており、それを「説明する」という学術分野がすでにある
      • これはもう、おもしろいことに、いわゆる生物学の生物に対する態度に似ている、と思いました

以上。

上記を読んで、自分なりのまとめ

  • AIというのは概念。知能っぽいものを人工的につくりたい!的な気持ち
    • 人間がアルゴリズムであったり物事の特徴を完全に捉えたうえで実装するのに対し
    • ある程度、コンピュータが「自律的に考えている」ように見える、という状態を指す、あくまで概念
  • 機械学習(ML)というのは、AIという概念の実現手法のカテゴリのひとつ
    • よく統計と比較される
    • 統計を既存データのグループ分けと位置づけた場合、機械学習がめざすものは、既存データを元にした、未来の入力に対してあるていど予想ができる状態
    • 単純な漸近線によるグループ分けよりも、複雑な回帰曲線で表現される曖昧な事象に対応したい
  • ニューラルネットワーク(NN)というのは、機械学習実装パターンのひとつ
    • 脳神経回路網を模した設計
    • ニューロン(計算ノード)が独立して入力に対して出力を計算する
    • ニューロンは、重みバイアス、あと活性化関数という個性を持つ
    • その連鎖によって、全体的に複雑な回帰曲線を実現する
  • ディープラーニング(DL)というのは、ニューラルネットワーク構築の流派、あるいは派生
    • 歴史的には、3層以上のNNを「深層学習(ディープラーニング)」と呼ぶ
    • 層がたくさん、って意味
    • 層をたくさんにすると、豊かな判断や、思いがけない予測を、したりするかもね!しないかもね!

雑感

各層をXⅰと置くと、下記漸化式で表現される。3層の場合は、X1が入力層、X2が中間層、X3が出力層。

AiとBiはパラメータ。Aiは行列、BiとXiは縦ベクトル。Aを重みパラメータ、Bをバイアスパラメータと呼ぶ。fは活性化関数と呼び、単純パーセプトロンでは使われていなかった、つまり、 f(x)=xであったが、すると線形になってしまうので、現在は何らかの非線形関数を使う。微分可能な単調関数を使うことが一般的。最もよく使われるのはシグモイド関数f(x)=1/(1+e^{-x})
ニューラルネットワーク#順伝播型ニューラルネットワーク

  • あとこれ見ながらコード写経するのは非常に勉強になる↓

DRYな備忘録として

【Go言語】準標準のWebSocketパッケージを使ったミニマムなチャットのサンプル

をつくって、こういう知見がたまったよ、みたいなの書こうと思ったんですが、Goの準標準パッケージである golang.org/x/net/websocket が便利すぎて「あ...できたわ」以上の感想が無いっていう現象になりました。

成果物はこちらです。ご査収ください。HTML入れても160行ぐらいしかないです。

github.com

f:id:otiai10:20171109005002p:plain

というかGoのチュートリアルでチャットってよく使われるからGoエンジニア飽きもせず何度もチャットつくるマンみたいになってる気がする。

DRYな備忘録として

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

【追記あり】【解決】Mac上のVagrantでFreeBSDが動かない

2017/11/28 追記

このVagrantfileですべてが動くことを確認できたので【解決】としました。

github.com

2017/11/16 追記

どうやらFreeBSDにおけるsudoの実装が内包しているバグだった模様で、公式が「数日内にバグフィックス出すよ」と言っている。とりあえず全裸待機。


以下原文


目的

環境

% vagrant --version
Vagrant 2.0.0
% VBoxManage --version
5.1.30r118389
% system_profiler SPSoftwareDataType | grep Version
      System Version: macOS 10.12.6 (16G29)
      Kernel Version: Darwin 16.7.0
%

公式ドキュメントに書かれたやりかた

Vagrant CloudにあるFreeBSDのbox

% mkdir -p ~/tmp/vagrant-freebsd-test
% cd ~/tmp/vagrant-freebsd-test
% vagrant init freebsd/FreeBSD-10.4-STABLE
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
% ls
Vagrantfile

で、

% vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'freebsd/FreeBSD-10.4-STABLE'...
No base MAC address was specified. This is required for the NAT networking
to work properly (and hence port forwarding, SSH, etc.). Specifying this
MAC address is typically up to the box and box maintainer. Please contact
the relevant person to solve this issue.

ふぇぇ

No base MAC address was specified.

FreeBSD側で書いてあったVagrantfile

base_macもコピペなので動かねえんじゃねえの?という予想がありつつ、

Vagrant.configure("2") do |config|
  config.vm.guest = :freebsd
  config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
  config.vm.box = "freebsd/FreeBSD-10.4-STABLE"
  config.ssh.shell = "sh"
  config.vm.base_mac = "080027D14C66"

  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
    vb.customize ["modifyvm", :id, "--cpus", "1"]
    vb.customize ["modifyvm", :id, "--hwvirtex", "on"]
    vb.customize ["modifyvm", :id, "--audio", "none"]
    vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
    vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
  end
end
% vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'freebsd/FreeBSD-10.4-STABLE'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'freebsd/FreeBSD-10.4-STABLE' is up to date...
==> default: Setting the name of the VM: vagrant-freebsd-test_default_1509123869695_7924
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Connection reset. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Connection reset. Retrying...
#
# これのクッソ繰り返し
#
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Connection reset. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Connection reset. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it is present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 5.2.0
    default: VirtualBox Version: 5.1

なんかSSH Connectionのリトライめっちゃしているように見えるが、Machine booted and ready!と自信満々に言われたので、とりあえずsshを試す。

% vagrant ssh
FreeBSD 10.4-STABLE (GENERIC) #0 r324749: Thu Oct 19 15:55:47 UTC 2017

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

Edit /etc/motd to change this login announcement.
"man firewall" will give advice for building a FreeBSD firewall
        -- David Scheidt <dscheidt@tumbolia.com>
vagrant@:~ % uname -a
FreeBSD  10.4-STABLE FreeBSD 10.4-STABLE #0 r324749: Thu Oct 19 15:55:47 UTC 2017     root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64
vagrant@:~ %
vagrant@:~ % echo "Hello, FreeBSD!"
Hello, FreeBSD!
vagrant@:~ %

まあsshはできてる。

再現性を確認するために、お掃除しとく。

% vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...
% ls
Vagrantfile
%

Provisionを試みる: Segmentation fault

Vagrantfile編集

Vagrant.configure("2") do |config|
  config.vm.guest = :freebsd
  config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
  config.vm.box = "freebsd/FreeBSD-10.4-STABLE"
  config.ssh.shell = "sh"
  config.vm.base_mac = "080027D14C66"

  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
    vb.customize ["modifyvm", :id, "--cpus", "1"]
    vb.customize ["modifyvm", :id, "--hwvirtex", "on"]
    vb.customize ["modifyvm", :id, "--audio", "none"]
    vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
    vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
  end
+
+  config.vm.provision "shell", inline: "echo hello"
+
end

で、

% vagrant up
# 中略
==> default: Running provisioner: shell...
    default: Running: inline script
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.
%

Vagrant assumes that this means the command failed.

って、echoが失敗してるとでも言うのかお前は。ためしに、

% vagrant ssh --command "echo hgoeeee"
hgoeeee
Connection to 127.0.0.1 closed.
%

Vagrantのログは、providerがVirtualBoxの場合(VirtualBoxのインストールディレクトリにもよるとは思うけれど)、
~/VirtualBox VMs/vagrant-freebsd-test_default_1509154848753_31244/Logs
にあるっぽい。

他には、

% vagrant destroy -f && vagrant up --debug

で得られるものもある。で、それっぽいエラー箇所抜粋↓

DEBUG virtualbox_5_1:   - [1, "ssh", 2222, 22, "127.0.0.1"]
DEBUG ssh: Checking key permissions: /Users/otiai10/tmp/vagrant-freebsd-test/.vagrant/machines/default/virtualbox/private_key
DEBUG ssh: Re-using SSH connection.
 INFO ssh: Execute: chown -R vagrant /tmp/vagrant-shell (sudo=true)
DEBUG ssh: stderr: Segmentation fault

DEBUG ssh: Exit status: 139
DEBUG ssh: Uploading: /var/folders/__/xxcbtw6j0tb681fjv1lbnlg40000gn/T/vagrant-shell20171028-68133-1nvns04.ps1 to /tmp/vagrant-shell
DEBUG ssh: Re-using SSH connection.
 INFO interface: detail: Running: inline script
 INFO interface: detail:     default: Running: inline script
    default: Running: inline script
DEBUG ssh: Re-using SSH connection.
 INFO ssh: Execute: chmod +x '/tmp/vagrant-shell' && /tmp/vagrant-shell (sudo=true)
DEBUG ssh: stderr: Segmentation fault

DEBUG ssh: Exit status: 139

Segmentation fault

ふむ。

sudoerではないprovisionの実行は成功

ためしに、sudo=falseとしてみる。Vagrantfileで、

     vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
   end

-  config.vm.provision "shell", inline: "echo hello"
+  config.vm.provision "shell", inline: "echo hello", privileged: false
 end

そんでふたたび、

% vagrant destroy -f && vagrant up --debug

とすると、

f:id:otiai10:20171028105826p:plain

ProvisionにおけるユーザのPrivilegeの問題であることが切り分けられた。

provisionにおけるユーザのsudoについて

前述の

をちゃんと読む

Seems like sudo will segfault on official FreeBSD STABLE (but not RELEASE) Vagrant boxes if a hostname isn't set. Problem is Vagrant uses sudo to set any hostname specified in the Vagrantfile or run any shell commands.

Setting it manually worked for me:

% vagrant ssh
vagrant@:~ % su
root@:/home/vagrant # sysrc hostname=myhost.local (modifies rc.conf)
root@:/home/vagrant # halt -p
% vagrant up --provision

f:id:otiai10:20171028111520p:plain

うーん、動いたけど、vagrant sshしてる時点でプロビジョニングツールとしてどうなんだという感じ。

Seems like sudo will segfault on official FreeBSD STABLE (but not RELEASE) Vagrant boxes if a hostname isn't set.

ほんまかいな。-RELEASE使ったろ。

Vagrant.configure("2") do |config|
  config.vm.guest = :freebsd
  config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
-  config.vm.box = "freebsd/FreeBSD-10.4-STABLE"
+  config.vm.box = "freebsd/FreeBSD-10.4-RELEASE"
  config.ssh.shell = "sh"
  config.vm.base_mac = "080027D14C66"

で、

% vagrant destroy -f && vagrant up
DEBUG virtualbox_5_1:   - [1, "ssh", 2222, 22, "127.0.0.1"]
DEBUG ssh: Checking key permissions: /Users/otiai10/tmp/vagrant-freebsd-test/.vagrant/machines/default/virtualbox/private_key
DEBUG ssh: Re-using SSH connection.
 INFO ssh: Execute: chown -R vagrant /tmp/vagrant-shell (sudo=true)
DEBUG ssh: stderr: Segmentation fault

DEBUG ssh: Exit status: 139
DEBUG ssh: Uploading: /var/folders/__/xxcbtw6j0tb681fjv1lbnlg40000gn/T/vagrant-shell20171028-72476-1wwln9a.ps1 to /tmp/vagrant-shell
DEBUG ssh: Re-using SSH connection.
 INFO interface: detail: Running: inline script
 INFO interface: detail:     default: Running: inline script
    default: Running: inline script
DEBUG ssh: Re-using SSH connection.
 INFO ssh: Execute: chmod +x '/tmp/vagrant-shell' && /tmp/vagrant-shell (sudo=true)
DEBUG ssh: stderr: Segmentation fault

ふつうにSegmentation fault出るやん。一応検証のため、

% vagrant ssh
vagrant@:~ % su
root@:/home/vagrant # sysrc hostname=testtest.local
root@:/home/vagrant # halt -p
Connection to 127.0.0.1 closed by remote host.
Connection to 127.0.0.1 closed.
% vagrant up --provision

f:id:otiai10:20171028112741p:plain

んなぁ〜動くなぁ〜。

Vagrantfileによるhostnameの指定は可能か?

config.vm.hostname - The hostname the machine should have. Defaults to nil. If nil, Vagrant will not manage the hostname. If set to a string, the hostname will be set on boot.

いけるっぽいぞ。ためしに、Vagrantfileを、

Vagrant.configure("2") do |config|
  config.vm.guest = :freebsd
  config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
  config.vm.box = "freebsd/FreeBSD-10.4-RELEASE"
  config.ssh.shell = "sh"
  config.vm.base_mac = "080027D14C66"
+
+  config.vm.hostname = "testtest.local"
+

としてみるものの、

f:id:otiai10:20171028113445p:plain

hostnameを実行しようとするとき、同様にSegmentation faultが出ている。

ここまでの結論

  • sudoしようとするときにSegmentation faultになる
  • sshしてhostnameを設定すると解決する
  • 再現可能

Next Action

ElectronアプリをMac上でWindows向けにビルドする

ゴール

  • MacOS上で動いてるElectronアプリがある
  • electron-packagerを使い、Mac用に.appというフォルダを作って配布できている
  • Windowsのひとたちにも配布したい

参考

手順

  1. electron-packagerを使って、ビルドディレクトリをつくる
  2. electron-winstaller を使って、インストーラ .exe をつくる

Windows用のビルドディレクトリをつくる

Building Windows apps from non-Windows platforms に従って、

% electron-packager . MyApp \
  --platform=win64 \
  --arch=x64 \
  --version=0.0.1 \
  --out=builds/windows \
  --icon=assets/myapp.icns --overwrite

エラー: Unsupported platform=win64 (string); must be a string matching: darwin, linux, mas, win32

Supported Platforms に、

Windows (also known as win32, for both 32/64 bit)

とある。ので、

% electron-packager . MyApp \
-  --platform=win64 \
+  --platform=win32 \
  --arch=x64 \
  --version=0.0.1 \
  --out=builds/windows \
  --icon=assets/myapp.icns --overwrite

エラー: Could not find "wine" on your system.

Packaging app for platform win32 x64 using electron v1.7.5
Could not find "wine" on your system.

Wine is required to use the appCopyright, appVersion, buildVersion, icon, and
win32metadata parameters for Windows targets.

Make sure that the "wine" executable is in your PATH.

Building Windows apps from non-Windows platforms をよく読むと、

so on non-Windows host platforms, Wine 1.6 or later needs to be installed. On OS X, it is installable via Homebrew.

とあるので、

% brew search wine
% brew install wine
wine: XQuartz is required to install this formula.X11Requirement unsatisfied!

You can install with Homebrew-Cask:
  brew cask install xquartz

You can download from:
  https://xquartz.macosforge.org
Error: An unsatisfied requirement failed this build.
# ほう?
% brew cask install xquartz
% brew install wine
==> Summary
🍺  /usr/local/Cellar/wine/2.0.3: 8,252 files, 591.9MB
# 入った
% which wine
/usr/local/bin/wine
# PATHも通ってる

electron-packagerによるビルドの成功

% electron-packager . MyApp \
  --platform=win64 \
  --arch=x64 \
  --version=0.0.1 \
  --out=builds/windows \
  --icon=assets/myapp.icns --overwrite

Packaging app for platform win32 x64 using electron v1.7.5
Wrote new app to builds/windows/MyApp-win32-x64

いい感じ。

インストーラの作成

% mkdir scripts
% vi scripts/windows-build-installer.js
/* eslint no-console:0 */
var winstaller = require('electron-winstaller');

winstaller.createWindowsInstaller({
  appDirectory: './builds/windows/MyApp-win32-x64/',
  outputDirectory: '/tmp/build/installer64',
  authors: 'My App Inc.',
  exe: 'myapp.exe'
})
  .then(() => console.log('It worked!'))
  .catch(e => console.log(`No dice: ${e.message}`));

エラー: No dice: spawn mono ENOENT

% node ./scripts/windows-build-installer.js
No dice: spawn mono ENOENT

ふむ。

ほう?

% brew search mono
% brew info mono
% brew install mono
% wich mono
/usr/local/bin/mono

インストーラ作成成功

ふたたび

% node ./scripts/windows-build-installer.js
It worked!
% ls -la /tmp/build/installer64
RELEASES        MyApp-0.0.1-full.nupkg  Setup.exe

いけてるっぽいぞ。

この.exeWindowsで実行したら、無事デスクトップアプリがWindowsで起動した!

DRYな備忘録として