病みつきエンジニアブログ

機械学習、Python、Scala、JavaScript、などなど

そろそろニューラルネットやディープラーニングを「人間の脳を模倣してる」というのをやめませんか?

最近(?)ニューラルネット(Neural Network)やらディープラーニング(Deep Learning; 深層学習)やらが流行ってきて、人工知能やらシンギュラリティやら言われるようになって、その中でよく言われるのが「ディープラーニングは人間の脳を模倣してる」とか「特徴量を選ばずに学習できる」とか、そんなことが言われるわけです。

けど、そういったキーワードが一人歩きして、「人工知能は危険だ」論とか、人工知能に対する過剰な期待論がはびこってしまっている気がする。そこで言いたいのが「ディープラーニングは人間の脳を模倣している」と言ってしまうのをやめましょう、という話。

ニューラルネットワークが「人間の脳を模倣」してる話

まず最初に、「ニューラルネットワークが人間の脳を模倣してる」論が、あながち間違ってないよ、ということを話しておきたい。あながち間違ってないんだけど、それでもやめたほうが良いよということを言いたい。

そもそも、ニューラルネットワークは、「Artificial Neural Network=人工ニューラルネットワーク」とか言われたりする。つまり、わざわざ「人工」という言葉をつけている。逆に「人工」じゃないものが何かというと、それはBiologicalなニューラルネットワークであって、つまり生物に備わる脳の話だ。

ニューラルネットワーク系に出現する用語も、明らかに脳の用語から出現するものがある。わかりやすいものだと「ニューロン」とかもそうだし、視覚野を模しているものもあると聞く。「細胞」という言葉が出てくることもある。

実際、PRMLにはこう書いてある(上巻5章 p.226)

ニューラルネットワーク」という語は、生体システムにおける情報処理を数学的に表現しようという試みにその起源がある(McCulloch and Pitts, 1943, Widrow and Hoff, 1960; Rumelhart et al., 1986)

「脳から学ぶ」という分野もあるし、生物から学ぶこと自体、とても価値のあることだと思う。

それでもなお、「ニューラルネットワークは人間の脳を模倣している」という表現は、かなりのミスリーディングを生んでいると思う。その話をしたい。

理由1:ニューラルネットワークは関数であって、「意識」ではない

そもそも、ニューラルネットワークは確定的な関数として表現されたりする。単純な例で、三層パーセプトロンの話を持ちだそう。

三層パーセプトロンは、次のような図式で表現される。多層パーセプトロンより引用

f:id:yamitzky:20160513011244j:plain

確かに、これではまるで脳に見えてくるかもしれない。しかし数式化するとこうなる。(PRML p.228より引用し、簡略化のためバイアス項を削除)

{ \displaystyle
y=\sigma \sum_{j=1}^{M}{w_{kj}^{( 2)} h \left ( \sum_{i=1}^{D}{w_{ji}^{( 1 )}x_{i}} \right )}
}

この式は、かなり乱暴に言えば「出力=係数2×(係数1×入力)」だ。ちなみに、「係数×入力」というのは、有名な「線形回帰」だ。つまり、かなり単純には線形回帰を2段階にしたもの、ということができる。「線形回帰」をもっと単純な話に言い換えると、中学だか高校の数学の「y = ax + b」だ。これを多段階にしただけで人間の「意識」と呼ぶのはさすがにおこがましいし、この三層パーセプトロンは入力に対して掛け算をしていくだけのものだ。途中でニューロンがプッツンすることはないし、アルツハイマーになることはない。

ニューラルネットワークのキーポイントの1つは、関数として目標と近似できる能力の高さではないかと思う。「意識」というものがあって、「人格」というものがあって、「考える」という能力があるような「人間シミュレーション」とは、現状は根本的に異なる。(そのうちぶつかるかもしれないけど)

ここにあげた例はかなり単純な例であるが、画像処理に使われる畳込みニューラルネットワークなども同様に、パラメータと入力に対して確定的に計算することになる。もちろんそこに確率的な枠組みを導入することはできるが、そうでなければ必ずしも精度が出ないということではない。ましてや、ここに意識という存在を考えるのは、さすがにバカバカしい。

理由2:脳を模倣するほど精度があがるわけではないし、必ずしも脳の模倣ではない

自然言語に対するニューラルネットワークの適用で言うと、LSTMというものが使われることがある。LSTMについてはわかるLSTM ~ 最近の動向と共に - Qiitaが詳しいが、その発展の仕方が興味深い。

もともとRNNのような構造があって、そこに「勾配消失問題」と呼ばれる課題があり、それによって精度が出ない類のタスクがあった(超深い層のNNを学習するようなものだった)。そこで、入力ゲート・出力ゲート・忘却ゲート、etc...みたいなものが提案され、精度が改善されて、、、という進化をたどっている。

そこで疑問なのは、果たして人間の脳はLSTMのような構造を持つだろうか? もしくは、生物の脳はLSTMのような進化を経ただろうか?

答えについては、自分は知らない(正しいか間違っているかわからない)。ひょっとしたら繋がりがあるかもしれないが、提案されている論文には「人間の脳がそういう風にできているから」という話は書いていない。

それよりもむしろ、提案者は「モデルとして現在勾配消失問題があって、それを解決するためにはどういう構造を提案すればよいか?」と考えているだろう。脳を模倣するという話は、1つのアイディアの起点でしかなくて、既存の課題を解決する構造は何か、という話の方がむしろ大事だと思う。

まとめ

言いたいのは、ニューラルネットは人間の脳とは全く関係がないだとか、脳を模倣することに意味はないだとかではなくて、「ニューラルネットが人間の脳を模倣している」ということによって、過剰な恐怖を煽ったり、過剰な期待を煽ったり、誤った認識を導いてたり、NNのブレイクスルーの本質を見誤ったりないですか?ということ。

そろそろ、ニューラルネットやディープラーニングを「人間の脳を模倣してる」というのをやめませんか?

今更始めるDocker on Mac、今更覚えるDockerコマンド

賢い読者はお気づきだと思いますが、このページの情報は2年前ぐらいの記事です。古いのでオススメしません。Docker for mac とかない時代っぽい時期の個人的なメモです


今更ながらDocker始めてみた。モチベーションとしては、Sparkとか試すために、手元に仮想環境がほしいから。なので、Immutable Infrastructureとか、KubernetesとかPackerはもちろん、Dockerfileとかにも踏み込まず、Dockerを始めてみる

Docker始めるにあたり読んだ記事

基本的には Installation on Mac OS X を参考にしながら、若干逸脱しつつ、基本コマンドなどを触ってみる。

インストール方法

Installation on Mac OS X を参考にする。 boot2dockerは非推奨なので Docker Toolbox使う。基本的にはGUIに従えば良い。

OSXでは、Linux上のDockerと違い、default というLinux VM上で動く。このVMdocker-machine コマンドで動かす

GUIからインストールしていると、VMは既に作成されているはず。Linux上でのDockerとの違いにより、この“URL”がちょっと重要

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.9.1

default VMが死んでいると、dockerコマンドは動かないので、docker-machine コマンドから立ち上げるなり作成するなり

$ docker images
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
$ docker-machine start default  # 立ち上げ
(default) Starting VM...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
$ docker-machine env default  # 環境変数が設定されていないと、dockerコマンドが動かないため
$ eval "$(docker-machine env default)"  # dockerコマンドが動くようにする
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

基本的な用語:イメージとコンテナ

イメージは、docker pullしてくるやつ。特定の生きたインスタンスじゃなくて、テンプレート的なもの。Dockerfileなどの定義体を含むもの。AWSでいうところのAMI。一覧を見るには、docker images

コンテナは、イメージから作成するもの。特定の生きたプロセス。AWSでいうところのインスタンス。一覧を見るには、docker ps

コンテナの作成

コンテナを作成するためには、イメージを取ってきて、そのイメージを元にコンテナを作る。まずはhello-worldというイメージを使ってみる。

コンテナの作成はdocker run 。runというと走らせる=起動っぽく感じるけど、AWSで言うとrun-instances に当たり、新規に作るもの。docker run する際、イメージがなければ自動で取ってくるようなので、docker pull をする必要は本当はない。

$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world

b901d36b6f2f: Pull complete
0a6ba66e537a: Pull complete
Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
Status: Downloaded newer image for hello-world:latest

$ docker images  # イメージが取得できている
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              0a6ba66e537a        9 weeks ago         960 B

$ docker run hello-world
Hello from Docker(ry

hello-dockerのイメージの中身は、 docker-library/hello-world で見ることができる(Dockerfile)。

一瞬で死ぬためよくわからないが、コンテナが作成された過去を垣間見ることができる(StatusはExited)。そして変な名前がついているw

$ docker ps --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
15eb91d087e0        hello-world         "/hello"            4 minutes ago       Exited (0) 4 minutes ago                        amazing_mahavira

コンテナへのアクセス

ubuntu イメージをrunしてみてもわかるが、コンテナは基本一瞬で死ぬ。コンテナ内で作業するには、 -it オプションを付ける。exitをすると(またはCtrl-D)、コンテナはまた停止する。

$ docker run -it ubuntu
root@a46509616ebe:/# exit

コンテナを立ち上げっぱにしておきたければ docker run -idt する。

$ docker run -idt --name my_ubuntu ubuntu
$ docker attach my_ubuntu
root@6acce8e05501:/#

立ち上げっぱのまま抜けるのは、Ctrl+p→Ctrl+q。

コンテナの再開

runして暗黙的に停止するライフサイクルだけではなく、停止したコンテナを docker start で再開することもできる。

当たり前だが、作成したコンテナのファイルは別に消えない。

$ docker run --name="my_ubuntu" -it ubuntu
root@7bd211d00874:/# echo "hogehoge" > hoge; exit  # てきとーにファイル作る
$ docker start -i my_ubuntu
root@7bd211d00874:/# cat hoge
hogehoge

ライフサイクル周りは Dockerライフサイクルをハンズオンで学ぶ - Qiita

コンテナのスナップショット

コンテナをイメージとして登録する=スナップショットを取るには、commit をする。gitと同じく、コミットメッセージもつけられる。イメージ間では特に差分の概念とか取らないんだろうか?

$ docker commit -m "hoge" a46509616ebe my_ubuntu
25185d37f98957a60309c73ae6c5d11ca8beea821306ef7b3edd37644d236677
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
my_ubuntu           latest              25185d37f989        21 seconds ago      187.9 MB
ubuntu              latest              89d5d8e8bafb        13 days ago         187.9 MB

これで、特にDockerfileなどは意識していないが、仮想環境のスナップショットを取ってイメージを作成する、という手順が出来たことになる。仮にクラスターなどを作る場合、一つのイメージを複製すれば良さそう。

ネットワーク周り

nginxのイメージで試す(参考:Dockerfile)。他にもJenkinsイメージとかもある。

$ docker run -d -P --name web nginx
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
cc343576e1aa        nginx               "nginx -g 'daemon off"   16 minutes ago      Up 16 minutes       0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   web

ここで、ポートのマッピング情報が書いてある。nginxの普通のポート80番は、32769番にマッピングされている。これは、VMのIPに対してのポート番号である

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.9.1

よって、http://192.168.99.100:32769 にアクセスすると、nginxの画面が表示される。

コンテナへのログイン

nginxサーバーを立ち上げているということで、例えばサーバー内に何か不具合があって、調査する場合など、コンテナにログインしたいケースは、exec コマンドに使うことができるようだ。

$ docker exec -it web bash

ちなみに、この場合はexitしてもコンテナは停止しない。

コンテナへのディスクマウント

ログなどの永続化したいファイルなどを入れるために、コンテナにローカルの(Macの)ディレクトリをマウントさせることができる。

$ echo "my new site" > /path/to/site/index.html  # ローカルに適当なhtmlファイルを作る
$ docker run -d -P -v /path/to/site:/usr/share/nginx/html --name web nginx
$ open "http://xxxxx"  # コンテナのnginxを開く

上記はローカルのファイルをコンテナが参照した形だが、逆に、コンテナからファイルを書き込むこともできる。

$ docker exec -it web bash
root@35f1b0480264:/# echo "hogehoge" > /usr/share/nginx/html/hoge.html; exit
$ cat /path/to/site/hoge.html
hogehoge

その他

15 Docker Tips in 5 Minutes // Speaker Deck より

最後に作ったコンテナIDを指すエイリアスを貼っておくと便利

alias dl="docker ps -l -q"

GUIインターフェース

以上説明したコマンドは、KitematicというGUIアプリケーションでもできる。GUIでインストールしていると、Applicationフォルダに勝手にインストールされているはず。

f:id:yamitzky:20151224114622j:plain

まとめ

使ったコマンドは、だいたい下記の通り

docker-machine ls # 起動しているVMの確認
docker-machine start # default VMを起動

docker images # イメージの一覧
docker ps # コンテナの一覧
docker run # コンテナの作成
docker start # コンテナの開始
docker attach # コンテナへのアタッチ
docker exec # コンテナでのコマンド実行; bashログインなど
docker commit # コンテナのコミット=スナップショットを取る

保存できないけどread-onlyではないJupyter Notebookサーバーを立ち上げる

誰でも触れる、かつ、誰でもパラメータ変更できる、けど保存はしないでほしいJupyter(a.k.a IPython) Notebookサーバー作りたいことってあるじゃないですか。

例えば、社内のMySQLサーバーとかHadoop環境とかのクエリを叩けるようなJupyter Notebookを作ったとき。 誰でもクエリの内容は変えられていいけど、それが保存されると、他の人が叩くときに困る。 こんな感じ↓

f:id:yamitzky:20151204192809p:plain

configを変更する

Jupyterの場合は「~/.jupyter/jupyter_notebook_config.py」の設定ファイルに、次のような設定を加えます。

import notebook
from tornado import web

class FreezeFileContentsManager(notebook.services.contents.filemanager.FileContentsManager):
    def save(self, model, path=''):
        raise web.HTTPError(400, "You cannot save notebook on this server.")

c.NotebookApp.contents_manager_class = FreezeFileContentsManager

FreezeFileContentsManagerというふうにファイルマネージャーを自分で定義することによって、処理を乗っ取ることができます。 この場合は、saveの処理を上書きしています。

元になっているFileContentsManagerのコードはこちら。他にもいろいろoverrideすれば、処理を変えられそうです。

github.com

アウトプット変更とかだけだったら、 pre_save_hookを変更するのが良いかと思います。(参考)

AWS IAMによる権限設定のハマりどころと、効率的なデバッグ方法

Amazon Web ServiceのIAM(Identity and Access Management)は、AWSの各種サービスに対してのアクセス制御を(結構細かく)設定するためのシステムです。

ただ、いくつか掛けられる制約にも制限があり、いろいろハマるところがあったので、メモを。

シナリオ

Jenkins経由で、特定のAMIからのみ、EC2インスタンスを一時的に立ち上げたり(run-instances)、消したりしたい(terminate-instances)。
停止(stop-instances)したり再開(start-instances)したり、というライフサイクルではない。
誤って全然関係ないインスタンスを消せないように制約をつけたいし、関係ないAMIから立ちあげられないように制限したい。
ついでにインスタンスタイプにしぼりたい。
また、安全のため特定のIPからのみアクセスできるようにしたい。

このようなシナリオでも、一応それっぽい権限で設定することができます。

IAMポリシーファイルの説明

IAMのポリシーファイルは、下記のような感じです。

{
  "Version": "2012-10-17", // バージョンは2012-10-17で固定
  "Statement": [
    {
      "Effect": "Allow",  // 許可するのか拒否するのか。デフォルトは全て"Deny"なので、"Allow"を記載していく感じ
      "Action": [ "ec2:TerminateInstances" ],  // 何のアクションを許可|拒否するのか。
      "Resource": [ "arn:aws:ec2:ap-northeast-1:1234567890:instance/*" ],  // そのアクションはどのリソース(インスタンスとかセキュリティーグループとか)へアクセス可能か
      "Condition": {  // どのような条件下でのみ、このStatementが有効か
        "StringEquals": { "ec2:InstanceType": "t2.micro" }
      }
    }
  ]
}

Statementが配列なので、いっぱい増やしていく感じ。

リソース条件はアスタリスク( "*" とか "arn:aws:ec2:ap-northeast-1:1234567890:instance/*" )で指定することもできるが、リソースを絞り込めば「そのリソースにしかアクセスできない」という状態を担保できる( "arn:aws:ec2:ap-northeast-1:1234567890:instance/id-hogehoge" )。

リソース指定できるアクションに制約がある

リソース指定によってIAMに制約をかけられる・・・と思いきや、全てのアクションがリソース指定できるわけではありません

特に、DescribeInstancesなどのGET系はだいたいダメで、他にもCreateTagsもダメです。その一覧はこちら

下記のようなresource指定してしまうと、そのStatementは無効になり、その操作は許可されなくなってしまいます。 リソースに指定できるのは "*" だけです。

{
  "Effect": "Allow",
  "Action": "ec2:DescribeInstances",
  "Resource": [ "arn:aws:ec2:ap-northeast-1:1234567890:instance/*" ], // NGな例
}

アクションとリソースと条件の組み合わせに制約がある

ここに書いてある通りですが、アクションごとに指定できるリソースに種類があり、リソースごとに指定できる条件キーが決まっています。

例えば、TerminateInstancesのアクションは、インスタンスIDに関するリソースのみ指定できます。 RunInstancesはイメージ、インスタンス、キーペア、etc。。。が指定できます。逆に、指定しないとそのリソースを使うことはできません。例えば、既存のキーペアを使ってインスタンスを作成したいなら、キーペアに対するリソース指定が必要になります。

RunInstancesのように複数のリソース指定をする場合に注意が必要なのが、複数のリソースで設定できる条件キーが異なることです。 例えば、イメージには「InstanceType」を指定できますが、キーペアには「Region」しか指定できません。 そのため、次のような設定をすると、「このキーペアにアクセスできないよ><」って言われます。

{
  "Effect": "Allow",
  "Action": "ec2:RunInstances",
  "Resource": [
    "arn:aws:ec2:ap-northeast-1:1234567890:instance/*",
    "arn:aws:ec2:ap-northeast-1:1234567890:key-pair/test-key-pair"
  ],
  "Condition": {
    "StringEquals": {
      "ec2:InstanceType": "t2.micro"
    }
  }
}

この場合は、おとなしく2つのStatementに分割します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:ap-northeast-1:1234567890:instance/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:InstanceType": "t2.micro"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:ap-northeast-1:1234567890:key-pair/test-key-pair",
        // その他のリソース許可の指定
      ]
    }
  ]
}

このシナリオを「リソースタグ」でクリアするのは厳しい

AWSのブログにて言及されていますが、リソースタグを活用すれば「特定のAMIから、特定のタグを設定したインスタンスを作成し、特定のタグのインスタンスのみ削除できる」ということができそうです(まぁできないんですけど)。 作るStatementとしては、

  • 特定のAMIからのみ run-instances できるStatement
  • 特定のResourceTagを持つインスタンスのみ terminate-instances できるStatement

の2つを作る、という感じ。

しかし、 run-instances する際にResourceTagは設定できず(例えばインスタンス名とか)、 create-tags しないといけないのですが、CreateTagsアクションにはリソース条件などが設定できないのです(=全許可しかできない)。ブログでもコメント欄で突っ込まれています。

create / terminate のライフサイクルではなく、start / stop のライフサイクルであれば、この方式は良さそうです。ただ今回の場合は、インスタンスは消し去りたかったので、この方式は取れませんでした。

IP制御もできるが、IPはグローバルIP

ec2に限らず、「どこのIPからリクエストがあったか?」を条件とできる、 aws:SourceIp という条件キーもあります。指定する場合は、一番最初にDenyしておくと良いです。

{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
      "NotIpAddress": {
          "aws:SourceIp": "123.45.67.89"
      }
  }
}

一点注意点なのが、IPはグローバルIPとして展開されます。なので、EC2インスタンス上からのみ「俺をTerminateしてくれ」という処理をできるように制限したい場合、グローバルIPが事前にわかっていないといけません。

IAMPolicy Simulatorが使いづらい

IAM Policy Simulatorは正直使いづらいです。条件に合致しないときには、「何も一致しませんでした」としか言われません。何がダメだったのかもわからないです。

そこで、AWS CLIから実際にdry-runすると良いです。

aws ec2 run-instances --dry-run --image-id=ami-abcdefg --count=1 --instance-type t2.micro

こうすると、権限が不足してれば、エンコードされたエラーメッセージが出てきます。エラーメッセージのデコードは Management Consoleの権限不足エラーをデコードする | Developers.IO を参考に、resourceという項目を見ると良いです。このresourceに対して、適切な条件が設定されていない、ということがわかります。

zshの場合は、こんな感じで関数作るとデバッグが楽です(bashは知らん)。

function sts() {
  aws sts decode-authorization-message --encoded-message $1 | jq -r ".DecodedMessage" | jq -c ".context.resource"
}

sts "エンコードされたエラーメッセージ"

最終的に取った手段

結局、うまくTerminateInstancesの条件を指定できないため、TerminateInstancesの権限を与えるのはやめました。 代わりに、次の手段を取りました。

  • EC2の作成時、shutdown時の動作を「terminate(削除)」になるようにした
  • AWS CLI経由で terminate-instances するのをやめ、EC2インスタンス内で shutdown -h now した

shutdown時の動作をterminateにするには、

aws ec2 run-instances --image-id=ami-abcdefg --count=1 --instance-type t2.micro --instance-initiated-shutdown-behavior=terminate

というように、「 --instance-initiated-shutdown-behavior=terminate 」をつけます。こうすれば、terminate-instances しなくても、shutdownするだけで同じことができます。

最終的なポリシーファイルは、下記のような感じ。思い出しながら書いてるからいろいろ間違っているかもしれんけど。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "123.45.67.89"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:ap-northeast-1:1234567890:instance/*",
      "Condition": {
        "StringEquals": {
          "ec2:InstanceType": "t2.micro"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:ap-northeast-1::image/ami-abcdefg",
        "arn:aws:ec2:ap-northeast-1:1234567890:security-group/*",
        "arn:aws:ec2:ap-northeast-1:1234567890:network-interface/*",
        "arn:aws:ec2:ap-northeast-1:1234567890:subnet/*",
        "arn:aws:ec2:ap-northeast-1:1234567890:volume/*",
        "arn:aws:ec2:ap-northeast-1:1234567890:key-pair/test-key-pair"
      ]
    }
  ]
}

vim-slimeで「for ... in ...」構文を便利に転送する

Vimにはvim-slimeという便利なプラグインがあり、Vim上で書いているコードを、tmuxやscreen経由で別ペインに転送することができる。

これの何が嬉しいかというと、「左はPythonソースコード」「右はPythonの実行結果」みたいな感じで、書きながら実行できる。↓

f:id:yamitzky:20151006175309p:plain

RStudioとか使ったことがある人は、便利さがイメージし易いはず。

f:id:yamitzky:20151006175521p:plain

Download and Install RStudio | RProgramming.net

for文の中だけ実行したいとき、iterableなオブジェクトの先頭を仮で入れたいケースがよくある
下記のようなコードを、

array = [1, 2, 3]
for i, x in enumerate(array):
    print(i, x)

下記のように実行したい。

i, x = enumerate(array).next()
print(x)

Vim力が足りないので、下記のような手順でとりあえず対応した。

~/.vim/after/ftplugin/python.vim を開いて、下記のような関数を追加

function! _EscapeText_python(text)
  if exists('g:slime_python_ipython') && len(split(a:text,"\n")) > 1
    return "%cpaste\n".a:text."--\n"
  else
    let no_empty_lines = substitute(a:text, '\n\s*\ze\n', "", "g")
    let stripped = substitute(substitute(a:text, '^\s*', '', ''), '\s*$', '', '')
    if stripped[:3] == 'for ' && stripped[-2:-2] == ':'
      return  substitute(stripped[4:-3], ' in ', ' = iter(', '') . ').next()
'
    else
      return substitute(no_empty_lines, "\n", "
", "g")
    end
  end
endfunction

これで、

for i, x in enumerate(array):

i, x = iter(enumerate(array)).next()  # i = 0; x = 1

で転送される、最高

TensorFlowを社内向けにざっくりLTして回帰した(+資料とか)

Googleが先日「TensorFlow」という機械学習ライブラリを発表していて、話題になっています。

さっそく今日社内で紹介LTしてきました。

「社内」のエンジニアの話で言うと、機械学習の会社ではないので、機械学習とかDeep Learningとかには深掘りして話していないです。もちろん、機械学習ライブラリとかも知らない、けど、「なんかGoogleからディープラーニングをOSSで出したって話題になっているぞ」っていう感じの人向けに話しています。

公式チュートリアルをちょっとだけ逸脱した線形回帰をやってみたサンプルもあります。

ちゃんと自動で微分できてます。

github.com

このライブラリ、結構良いなあと思うのは、Googleが使っているという実績力かなと思います。公開初日に「Googleのプロダクションに使ってるんで」の実績は、ちょっとずるい(厳密にどれくらい使ってるかはわからないけど)。

ライブラリ自体がどう良いかについては、きっと誰かがまとめてくれると思う。パフォーマンステストとかも。

個人的に気になるのは、分散環境での実行について。彼らのペーパーの中には、分散コンピューティングについていろいろ書いてあるっぽいんだけど(読んでない)、ライブラリ中に陽に機能はない気がする。有効グラフのやつなのかな。誰かチュートリアル書いてください。

流行るかどうかはわからないけど、Googleで使ってるって言われちゃうと、過不足はなさそう(か、不足があれば実装されていく、だろう)。 そろそろちゃんとDeepLearningを実装しながら勉強したいと思っていたので、今年の残りはTensorFlowやろうかなあと思っている。

dotfiles公開した+vim/zshのおすすめ設定とか

yamitzky/dotfiles

会社のPCを新調して、環境設定するタイミングだったので、いい機会だしdotfilesを公開した。 今までは自分のプライベートgitサーバーに置いてたんだけど。

やはり、公開すると、綺麗に書くようになるしいいなあという感じします。

これだけだとブログとして寂しいので、いくつか解説を。

homesickを使った

homesick という、ホームディレクトリ構築用のOSSを使いました。

/home以下にあるファイルだけシンボリックリンクが貼られる、という仕様。homeディレクトリを作らないといけないので、なんとなく不格好だけど、シンボリックリンク貼る対象が明確になってわかりやすいです。

brew-bundleはなくてもいい

rcmdnk/homebrew-file みたいな解決策があるのですが、あまりいらないかなと思います。

インストールしたいものをテキストファイル(例えば、Brewlist)に一覧に書いて、

brew install `cat Brewlist`

みたいな感じで叩いてあげると、自動でインストールできます。逆に、Brewlist的なものを出すには

brew list > Brewlist

サブ設定を分割

.zshrcや.vimrcがどうしても肥大化してしまうので、「alias.zsh」とか「plugin.vim」みたいな感じで分割して、ロードしてあげる仕様にした。

vimの設定について

気に入っているのが、

  • 移動がjkilのゆとり仕様
  • カラースキームはwombat
  • バックアップファイルは ~/.vim/tmp に吐き出す
  • Pythonの「# -- coding: utf-8 --」をコマンド化

zsh用便利関数

  • SHA1を作る関数 sha1
  • Macの通知をする関数 notify
  • 任意サイズのランダムな画像を作る randimg
  • ファイル更新があったら通知する quickwatch
  • :tabe って書くとvimが立ち上がる
  • cd..って書くと cd .. になる
  • その他、Python経由のサーバーとかJSONパースとかURLエンコードとか

便利なOSS

  • よく使うディレクトリへすぐに飛べる autojump
  • peco を使った履歴検索
  • zsh用補完の、zsh-completions
  • コマンドエラーがないかわかりやすい、zsh-syntax-highlighting

直したいところ

  • OS依存
  • オレオレソフトウェアのgithub公開

何かご意見あれば、リプライください!

そんじゃーね!