18 Jun 2017, 07:51

CEM で CartPole-v0 を試したメモ

はじめに

前回の続き。前回はなんの戦略もなく、ただ試した。

今回は、CrossEntropy Method(CEM)をつかって、OpenAI gym の CartPole-v0 を試した。

CrossEntropy Method(CEM)について

クロスエントロピー法は、2006 年に登場したモンテカルロ法を応用したアルゴリズム。

レアなイベントについてサンプリングすることで(政策改善)、 エリートのみであらたなポリシーをつくる(政策評価)するところに特徴がある。

自分のイメージでは、ランダムにシミュレーションして、 ラッキーな場合のみを選び出して、ポリシーに反映させていくように考えている。

Berkeley の John Schulman さん曰く、このアルゴリズムは、

  • Evolutionary algorithm
  • Works embarrassingly well

と、激ホメしている。

アルゴリズム

Schulman さんの講義スライドより引用。

この gist の資料も参考になった。以下、アルゴリズムの定義を引用。

平均(mean)とガウシアンの共分散(sigma)を初期化し、n_iter 回以下を繰り返す。

  1. batch_size 分の theta を mean と sigma からなるガウス分布から集める
  2. noisy evaluation を実施して、これらの theta からの報酬を得る
  3. top p% のサンプルを選択する(これをエリート集合と呼ぶ)
  4. エリート集合の mean と sigma で 現在の値を更新する。

Lab1

Schulman さんの 2016 年 Deep Reinforcement Learning サマースクールの課題をやる。

クロスエントロピーメソッドで cartpole を攻略するためのスターターコードがある。

Code

スターターコードの穴埋め部分を埋めてみた。nv.monitor.clos のコードを参考にした。

Result

結果は、OpenAI Gym にアップロードした。

132.20 ± 6.42. という結果で、合格ラインの 195 には程遠いが、前回よりはずっと改善した。

embarrassingly だ!

参考リンク

18 Jun 2017, 07:51

Python で勾配降下法を使って線形の単回帰分析をしてみた

Python で勾配降下法を使って線形の単回帰分析をしてみた。

はじめに

Siraj Ravel さんの新しい動画シリーズ, “The Math of Intelligence”が始まった。

機械学習のための数学を毎週カバーしていくようだ。シラバスは以下。

数学に苦手意識があるので、おもしろそうなトピックだけ Coding Challenge に取り組んでいこうと思う。

Coding Challenge

初めのトピックは Gradient Descent(勾配降下法)。

昔、勉強したのだけれども、すっかり忘れていた。以下の本がとても今回役に立った。

Coding Challenge は Kaggle のデータで、勾配降下法を使って線形の単回帰分析をすること。

今回 チャレンジした Jupyter Notebook は以下です。

データセット

Kaggle のデータを使うようにとのことなので、入門用のデータセット, House Prices を使っていこうと思う。

とりあえずいちばん簡単な方法を試したいので、家の面積と価格の相関関係に注目することにした。

  • SalePrice - the property’s sale price in dollars. This is the target variable that you’re trying to predict
  • GrLivArea: Above grade (ground) living area square feet

データをプロットしてみると正の相関関係がありそうなので、直線が引けそう。

勾配降下法

本当は、偏微分の数式とか書きたいけれど、数式の書き方がよくわからなかった orz

というわけで、説明抜きでいきなりコードですみません m(._.)m

参考リンクだけはっておきます。この記事のコードを参考にしました。

def calcurate_mean_squared_error(x, y, b, m):
    total_error = 0
    n = y.size
    for i in range(n):
        prediction = m*x[i] + b
        total_error += (y[i] - prediction)**2
    return (1/n) * total_error

def step_gradient(x, y, b, m, learning_rate):
    m_grad = 0
    b_grad = 0
    n = y.size

    #Computes the gradients
    for i in range(n):
        # Partial derivative for m
        m_grad += -(2/n) * x[i] * (y[i] - ((m*x[i]) + b))
        # Partial derivative for b
        b_grad += -(2/n) * (y[i] - (m*x[i]) + b)

    # update m and b
    m = m - (learning_rate * m_grad)
    b = b - (learning_rate * b_grad)    
    return b, m

def gradient_descent_runner(x, y, initial_b, initial_m, learning_rate, num_iterations):
    b = initial_b
    m = initial_m
    past_errors = []
    for i in range(num_iterations):
        b, m = step_gradient(x, y, b, m, learning_rate)
        if(i % 100) == 0:
            error = calcurate_mean_squared_error(x, y, b, m)
            past_errors.append(error)
            print('Error after', i, 'iterations:', error)
    return b, m, past_errors

実験結果

学習率 0.0001 だと収束しなかった。

おかしい。もっともっと学習率を小さくしても収束しない。はじめはバグっているのかと思ったけど、そうではなさそうだ。

num_iterations = 1000
learning_late = 0.0001
print("Starting gradient descent at b = {0}, m = {1}, error = {2}".format(
    initial_b, initial_m, 
    calcurate_mean_squared_error(x, y, initial_b, initial_m)))
print("Running...")
[b, m, errors] = gradient_descent_runner(x, y, initial_b, 
                                 initial_m, learning_late, num_iterations)
print("After {0} iterations b = {1}, m = {2}, error = {3}".format(
    num_iterations, b, m, calcurate_mean_squared_error(x, y, b, m)))
Starting gradient descent at b = 0, m = 1.0, error = 38434358058.74041
Running...
Error after 0 iterations: 9.29730669048e+15

/home/tsu-nera/anaconda3/envs/dlnd/lib/python3.6/site-packages/ipykernel_launcher.py:6: RuntimeWarning: overflow encountered in double_scalars

/home/tsu-nera/anaconda3/envs/dlnd/lib/python3.6/site-packages/ipykernel_launcher.py:9: RuntimeWarning: overflow encountered in double_scalars
  if __name__ == '__main__':
/home/tsu-nera/anaconda3/envs/dlnd/lib/python3.6/site-packages/ipykernel_launcher.py:14: RuntimeWarning: invalid value encountered in double_scalars

Error after 100 iterations: inf
Error after 200 iterations: nan

いろいろ学習率をいじって試した結果、0.000000385 というよくわからない数が最も適切だった。なんだこりゃ?!

標準化をためす

coursera の Machine Learning で、フィーチャースケーリング を習ったことを思い出した。

講座の動画を見返したら多変数の場合を扱っていた。

説明変数が1つでも、有効なのかな?とりあえず、標準化を試してみた。

norm_x = (x - x.mean()) / x.std()

今回は、学習率 0.0001 という、馴染みの値で収束した。うまくいったようだ。

コスト関数の値も plot した。イテレーションを繰り返すごとに減っている。

14 Jun 2017, 11:36

三目並べ(tic-tac-toe) にモンテカルロ法を試した

三目並べ(tic-tac-toe) をモンテカルロ法をつかって学習させました。

元ネタは、これ。

この本のコードは Octave でかかれているのだけれども、それを Python にポーティングしてくれた人がいた。

自分はなにをしたかというと、このコードを OpenAI Gym の tic-tac-toe に対応させてみた(tic-tac-toe は非公式)

ただ移しただけだと動かなかった。それから 10 時間くらいでばっくをしていた。頭がおかしくなる。

コード

おまけ: プルリク奮戦記

じつは、OpenAI Gym の tic-tac-toe リポジトリにバグっぽいのをみつけた。

ピンチ!いやチャンス?

自分は他人の Github リポジトリにプルリクをしたことがないのだ。

まずは気さくな感じを醸し出して質問をしてみた。Hello!! :-)

1 分も立たずに返信が帰ってきたのでビビる。はえーよ!

feel free to provide a PR!!

もうこの言葉が理解できずにガクガクした。なにかへんな英語表現を使っちゃったかな??

大丈夫、PR は Pull Reqest のことだ。って、ぅえ〜〜〜〜〜。やったことないよ〜〜〜。

プルリクエストの作法を調べる。

  1. branch 経由
  2. fork repository 経由

検索上位に引っかかるのは、初心者は branch を切る方法が勧められている。

  1. 初心者向け Github への PullRequest 方法 - Qiita
  2. Pull Request の仕方 - Qiita

バカだから何を思ったのか、fork ポタンをポチリ。。。。。fork してしまったぁぁ!!!

とりあえず、バグの修正をして、fork した自分のリポジトリに push

そして、GUI 画面から PULL REQUEST !!!!

ふう、まつこと数分・・・ 10 分でレスポンスが帰ってきた。もう心臓に悪りーよ。

  • コメントの単語が適切でない
  • 冗長な for 文の回し方をしている

その通りです、なにもいうことはありません。 こっちも急いで修正して、再コミット!!

祈った。。。そうして待つこと 15 分、ついに Merge されました〜〜〜〜!!!

うらららららららららら〜〜〜〜〜〜〜!

10 Jun 2017, 07:49

実践的な強化学習のオンライン学習教材、Practical RL をはじめた

実践的な強化学習の教材、Practical RL をやりはじめた。

これはなに

HSE と Yandex SDA というロシアの大学?で教えられている強化学習のコースが、 オンライン学習のために英語とロシア語で公開されている。

教材は、オンラインで強化学習をするためのリソースのいいとこどりをしている。

各週のディレクトリに動画や pdf のリンクがかかれた README がある。

また、”実践” とつくだけに、各週の課題が Jupyter Notebook で与えられ、OpenAI Gym を活用する。

fast.ai の講座 が予想以上によかったので、実践的とかかれると期待してしまう。

強化学習のコースなのだが、最近の動向に合わせ Deep Learning(DQN) の内容も盛り込まれている。

Deep Learning のためのライブラリは、Lasagne というライブラリが推奨されている。 しかし、Tensorflow 版の課題ノートも公開されている。

シラバス

github の README から抜粋。詳しくは、元サイトへ。

前半で、強化学習の話題をカバーしている。中盤で、Deep Learning の話題が出てくる。後半はよくわからない。

week0 Welcome to the MDP
week1 Crossentropy method and monte-carlo algorithms
week2 Temporal Difference
week3 Value-based algorithms
week4 Approximate reinforcement learning
week5 Deep reinforcement learning
week6 Policy gradient methods
week6.5 RNN recap
week7 Partially observable MDPs
week 8 Case studies 1
week 9 Advanced exploration methods
week 10 Trust Region Policy Optimization.
week 11 Model-based RL: Planning

他のコースとの比較

他のコースと比較検討して Practical RL を進めようと思ったので、その理由も書いておく。

Practical RL のデメリットは、課題 の解答が公開されていないところ。

fork している人のリポジトリを覗いて自分の解答と照らし合わせようかと思ったけれども、 参考になりそうなリポジトリがあまり見つからなかった。

ということで、自分は途中で挫折する可能性が高いので、 このコースに挫折したら次にやることも考えておく。

Learning Reinforcement Learning - WildML

強化学習の主要な話題が Jupyter Notebook と共に提供されている。うれしいことに、解答付きだ。

ただいま作成中のようなのと、学ぶ方法が Sutton 本を読むことに偏っていたのでやめた。

しかし、Practical RL に行き詰まったらこっちにシフトしようかと考えている。

UCL Course on RL

ユニバーシティ・カレッジ・ロンドンの強化学習の講義資料

この動画は、Practical RL の中で何度も引用されていてみることが進められている。

なので、Practical ML を進めたらこの講義内容はカバーできるのと、 課題が見つからなかったので止めた。

追記: 2016 年のページ見つけた。課題もしたのほうにある。

CS 294: Deep Reinforcement Learning, Spring 2017

UC Barkeley の Deep Learning と強化学習を学ぶ講義資料。

強化学習に Deep Learning を使う。ライブラリは Tensorflow.

講義動画がしっかりそろっている。

課題は 4 つある。掲示板も Reddit を使っていて課題につまったときは検索できそう。

これを選ばなかった理由は、Practical RL よりも難しそうな印象を受けたから。 Deep Learning も 強化学習もわからないのに、それを合わせた内容をバンバン紹介されても消化できなさそうだ。

また 、Practical RL からもこのコースの動画や課題(hw3)が紹介されていたので、 うまくつまみぐいできるかと思ったから。

UC Barkeley CS294 Deep Reinforcement Learning

2015 年の Barkeley の Deep Reinforcement Learning

2017 年版の元になったコースだ。内容は、短くまとまっている(4つ??)

UC Berkeley CS188 Intro to AI

2014 年の Berkeley の AI コース。

レクチャー動画や課題はしっかりしている。Project もおもしろそうだ。

扱っているものは、基本的なもので Deep うんたらはでてこないので少し古さは感じる。

An introduction series to Reinforcement Learning (RL) with comprehensive step-by-step tutorials.

Git-Base のチュートリアリル。提供元団体不明。個人かな?

このチュートリアルも作成中のようだが、前半はほぼ完成している。

README とコードベースのチューとリアルなので、 それほど英語力や数学力を求められない、今までで一番やさしそうな印象を受ける。

扱っている話題は、Q-Learning, OpenAI Gym, DQN, Deep Convolutional Q-Learning, ROS などなど、おもしろそうなものばかりだ。

Udacity Reinforcement Learning

MOOC の大御所 Udacity が提供しているコース。

短い動画がたくさんある。二人の掛け合いによって動画が進んでいき、 とっつきやすい感じはある。

課題はなく、短いので、理解が足りないところを補足する目的で見てもみてもいいかも。

Reinforcement Learning: An Introduction - Richard S. Sutton and Andrew G. Barto

言わずと知れた、強化学習のバイブル。これを腰を据えて読むのがいいのかも。

第2版には、サンプルコードが提供されているようだ。ただし、解答はなし。

Udemy Artificial Intelligence A - Z

Udemy の AI コースも, 最新の話題を扱っている。セールのときに 1200 円で買った。

Module 1: "Self Driving Car"
Module 2: "Deep Convolutional Q-Learning"
Module 3: "A3C"

なんと、フレームワークは Pytouch を使う。

  • Module1 では、シミュレータ上の車のライントレースを DQN で行う。
  • Module2 では、OpenAI Gy 上で Deep Convolutional Q-Learning を学ぶ。
  • Module3 では、A3C という発展的な話題を扱う。

これで、1200 円だ。安いと思う。

Simple Reinforcement Learning with Tensorflow

TensorFlow による 強化学習の実装チュートリアル。

以下は内容。コードはここ https://github.com/awjuliani/DeepRL-Agents

  • Part 0 — Q-Learning Agents
  • Part 1 — Two-Armed Bandit
  • Part 1.5 — Contextual Bandits
  • Part 2 — Policy-Based Agents
  • Part 3 — Model-Based RL
  • Part 4 — Deep Q-Networks and Beyond
  • Part 5 — Visualizing an Agent ’ s Thoughts and Actions
  • Part 6 — Partial Observability and Deep Recurrent Q-Networks
  • Part 7 — Action-Selection Strategies for Exploration

09 Jun 2017, 23:09

OpenAI Gym FrozenLake-v0 に 遺伝的アルゴリズム(deap)を試す

タイトルのとおり、OpenAI Gym FrozenLake-v0 に遺伝的アルゴリズムを試しました。

遺伝的アルゴリズム

遺伝的アルゴリズムとは

遺伝的アルゴリズム(genetic algorithm, 略して GA)とは、 組み合わせ問題の最適解を求めるためのアルゴリズム。

具体的には、以下の 2 〜 4 を繰り返すアルゴリズム。

1. 初期設定
2. 選択
3. 交叉
4. 突然変異

詳しくは、他のサイトに説明は譲る。この記事がわかりやすかった。

Python で遺伝的アルゴリズムやるなら Deap

Python で遺伝的アルゴリズムやるなら Deap というライブラリがある。

遺伝的アルゴリズムにも、選択、交叉、突然変異にいろいろな酒類がある。

この辺の話は, Wikipedia が詳しい。

それらをうまく抽象化して扱えるのがこのライブラリ。

解説記事はネット上にたくさんあるのだが OneMax 問題を扱っているものが多い。

なので、OpenAI の FrozenLake-v0 を題材に Deap を使ってみた。

FrozenLake-v0

GA の前に乱数を発生させて、そのポリシーにしたがって進んでいく例を書く。

結果は、こちら。https://gym.openai.com/evaluations/eval_iinFj8fUSvOOYHWXwjjAw

Score が 0.56 で、基準の 0.78 をオーバーしていない。

deap を使った GA

結果は、こちら。https://gym.openai.com/evaluations/eval_uU3CIG5yTgOhOXVM8EG3wA

Score が 0.81 と、基準値をなんとかクリアした。

deap をつかわない GA

結果は、こちら。https://gym.openai.com/evaluations/eval_YpHI9YmhQoSGcKMI1dFsw

なんと Score は 0.91 だ。

ということは、自分の deap をつかった実装はどこかバグってるなぁ?!

09 Jun 2017, 07:18

OpenAI Gym の CartPole-v0 を試したメモ

OpenAI Gym を試してみたメモです。

CartPole-v0 というゲームを動かしてみました。

OpenAI Gym

OpenAI Gym とは

OpenAI Gym is a toolkit for developing and comparing reinforcement learning algorithms.

OpenAI Gym は、強化学習アルゴリズムを開発し評価するためのツールキット。

  • gym … python テスト環境ライブラリ.
  • OpenAI Gym service … エージェントのパフォーマンスを評価するサービス。

ちょっとわかりにくいが、自分の解釈では、 いろんなゲームをプレイする環境が提供されていて、 自分の AI エージェントをつくってゲームをプレイして遊べるツール。

どんなゲーム(環境)があるの?

三目並べからシューティングゲーム、囲碁まである。詳しくは、以下。

Open AI Gym ライブラリのインストール

OpenAI Gym を pip でいれる。

pip install gym

以下のジャンルのゲームができるようになる。

  • algorithmic
  • toy_text
  • classic_control

CartPole で遊ぼう

公式のチュートリアルで紹介されている CartPole というゲームを触ってみる。

CartPole 問題

CartPole 問題は、強化学習の古典的問題らしい。

棒(pole)が動く台車(cart)の上に立っている。 棒は倒れるので、台車を右か左に動かして倒れないようにする。 より長く棒を直立させることが目的。

以下は、ルールの Google 日本語翻訳。

ポールは、作動していないジョイントによって、摩擦のないトラックに沿って動くカートに取り付けられる。システムは、カートに+1 または-1 の力を加えることによって制御される。振り子が起立して、それが転倒するのを防ぐことが目標です。ポールが直立したままのタイムステップごとに+1 の報酬が与えられます。エピソードは、ポールが垂直から 15 度を超えると終了するか、またはカートが中心から 2.4 ユニット以上移動すると終了します。
  • 1step の間に直立 h していれ報酬を 1 もらえる
  • 右(+1) or 左(-1)の行動を選択できる
  • 棒が 15 度傾くとゲームオーバー
  • 台車が中心から一定距離(2.4unit???) とゲームオーバー

コードを調べる

公式ドキュメントに乗っているコードを見ていく。

import gym
env = gym.make('CartPole-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break

まずは、gym というライブラリをインポートする。

gym.make(“環境名”) で動かす環境(env)を生成する。ここでは、CartPole-v0 を指定。

import gym
env = gym.make('CartPole-v0')

env の 3 つの主なメソッドは、

  • reset() - 環境(environment)をリセットする。最初の 観測(observation) を返す。
  • render() - 現在の環境の状態をレンダリングする。
  • step(a) - 行動(action)を実行し、以下を返す(new observation, reward, is done, info)
    • new observation - 行動を実行したあとの観測
    • reward - 報酬
    • is done - ゲームが終了したら True, 続いているなら False
    • info - 詳細情報

for 文で 20 エピソード分を実行する。

env.render()で以下のような図を表示する。

env.reset()を実行すると、以下の numpy 配列が帰ってくる。

# [position of cart, velocity of cart, angle of pole, rotation rate of pole]
array([-0.01717682,  0.00789496,  0.03295495, -0.0202679 ])

env.observation_space で、観測状態、env.action_space で、行動がそれぞれ帰ってくる。

Box は、n-次元の Box を、Discrete は固定された範囲の非負の数をそれぞれ表す。

print("observations:", env.observation_space)
print("actions:", env.action_space)
observations: Box(4,)
actions: Discrete(2)

CartPole-v0 では、observation は 4 次元の配列, action は 0 or 1 の数。

以下で、observation_space の上限、下限が分かる。

print(env.observation_space.high)
#> array([ 2.4       ,         inf,  0.20943951,         inf])
print(env.observation_space.low)
#> array([-2.4       ,        -inf, -0.20943951,        -inf])

以下で、action_space の数が分かる。

print(env.action_space.n)
#> 2

env.action_space.sample()で、action をランダムに選択できる。

env.action_space.sample()
#> 0
env.action_space.sample()
#> 1
env.action_space.sample()
#> 1

step()関数に action を渡すことで、action を実行できる。

done が True になるまで繰り返す。reward には、1.0 が入る。

結果を記録、アップロード

以下のように、wrappers.Monitor(env, ‘/tmp/cartpole-experiment-1’)を使うと、 実行結果を記録することができる。

import gym
from gym import wrappers
env = gym.make('CartPole-v0')
env = wrappers.Monitor(env, '/tmp/cartpole-experiment-1')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break

以下のような mp4 の動画と meta 情報の json がディレクトリに作成される。

$ ll /tmp/cartpole-experiment-1
合計 32K
-rw-rw-r-- 1 tsu-nera tsu-nera  817  6 月  9 15:59 openaigym.episode_batch.0.13181.stats.json
-rw-rw-r-- 1 tsu-nera tsu-nera  412  6 月  9 15:59 openaigym.manifest.0.13181.manifest.json
-rw-rw-r-- 1 tsu-nera tsu-nera 2.0K  6 月  9 15:58 openaigym.video.0.13181.video000000.meta.json
-rw-rw-r-- 1 tsu-nera tsu-nera 4.0K  6 月  9 15:58 openaigym.video.0.13181.video000000.mp4
-rw-rw-r-- 1 tsu-nera tsu-nera 2.0K  6 月  9 15:58 openaigym.video.0.13181.video000001.meta.json
-rw-rw-r-- 1 tsu-nera tsu-nera 3.9K  6 月  9 15:58 openaigym.video.0.13181.video000001.mp4
-rw-rw-r-- 1 tsu-nera tsu-nera 2.0K  6 月  9 15:58 openaigym.video.0.13181.video000008.meta.json
-rw-rw-r-- 1 tsu-nera tsu-nera 3.8K  6 月  9 15:58 openaigym.video.0.13181.video000008.mp4

以下のようなスクリプトを実行すると、OpenAI Gym に結果をアップロードできる。

import gym
gym.upload('/tmp/cartpole-experiment-1',api_key='<api key>')

api_key は、OpenAI Gym にログインすると得られる。

$ python carpole_upload.py
[2017-06-09 16:09:39,697] [CartPole-v0] Uploading 20 episodes of training data
[2017-06-09 16:09:48,712] [CartPole-v0] Uploading videos of 3 training episodes (9058 bytes)
[2017-06-09 16:09:49,232] [CartPole-v0] Creating evaluation object from /tmp/cartpole-experiment-1 with learning curve and training video
[2017-06-09 16:09:49,618] 
****************************************************
You successfully uploaded your evaluation on CartPole-v0 to
OpenAI Gym! You can find it at:

    https://gym.openai.com/evaluations/eval_7fz1aflRO6alkzRRfWhQ

****************************************************

gist にコードをあげて、URL を取得する。

評価ページにいき、gist を貼り付ける。以下のリンクが今回の評価ページ。

追記

長い間プログラムを動作させると、manifest.json ファイルが生成されなかった。 そういう場合は、念のため env.close()を終了時に呼び出すことで、manifest.jssn が生成されるようだ。 参考にしたコードはここ.

01 Jun 2017, 04:41

Oracle Certified Java Programmer, Silver SE 8 認定資格に合格

Java SE8 Silver(Java SE 8 Programmer I 試験[1Z0-808]]) に 3 日間 で合格しました。

受験するまで

最近はディープラーニングの勉強をしているのだけれども、会社から脅された。

  • ディープラーニングが業務ににどう役に立つか説明してください。
  • ディープラーニングでどうやって会社に貢献するんですか?
  • Java の資格をさっさととらないとクビにするよ?

(´・ω・`)

ということで、Java SE8 Silver[1Z0-808]を勉強をはじめた。

Oracle はキャンペーンをやっていて、2017/5/31 までに受験すると、 一度落ちても再受験が無料のキャンペーンを実施中であることに、 528 の夕方に気づいた。

受験料がバカに高い(28728 円!)ので、落ちたらお金がもったいないし、 こっちは人生かかっているので、3 日間で死ぬ気で勉強することになった。

結果

82%の正解率で合格。(合格ライン 65%)

勉強内容

前提

Java の業務経験は、3 年前に 1 年程度。それから 2 年のブランク期間あり。

オラクル社主催の試験のランクは、ブロンズ、シルバー、ゴールドとあるけれども、 ブロンズは受けていない。

元々 Java の知識はあったので、問題をひたすら解くという対策方法をとった。

学習時間

528 の夕方 から 531 の夕方までなので、4 日間にわたるのだけれども、実質 72 時間。 そのうち、37 時間を Java に費やした。

  • (0 日目:528: 6 時間)
  • 1 日目 529: 13 時間 (黒本模試 66%, 68%)
  • 2 日目 530: 8 時間 (白本模試 75%)
  • 3 日目 531: 10 時間 (本番 82%)

参考書

売り出されている参考書は、黒本と白本と紫本の3つがある。

まず、一番評判がいい黒本を 2 周した。(1 日目)

まだ時間の余裕と心の不安があったので、白本を購入して一週した(2 日目)

最後の 3 日目は、黒本と白本の間違えたところを復習。

黒本

  • 解説が文章でかかれていて丁寧。
  • 問題の解説の前に概念の説明があるので、問題演習の延長で基礎の復習もできる。
  • 紙質が白本に比べていい。

白本

  • 解説に図を多様している。図解で直感的理解ができる。
  • 問題のすぐ下に解説があるので、解いてすぐに答えを確認できるようにつくられている。
  • 黒本よりもやさしい。
  • 出なさそうな問題もたまにある気がする。
  • アプリ版があるので、スマートフォンで満員電車のなかでも勉強できる!

紫本

  • 問題の前に、説明にベージが多く割かれている。
  • 体系的にまとまっているので基礎から学びたい人におすすめ。

受験する人へのアドバイス

どういう問題が出たかは、問題の情報漏洩になるのでいえないのだが、

黒本をやれ!!(。・ω・)ノ

そう、ひたすら黒本をやれば受かる。

自分のように白本に手を出す時間があるならば、黒本の問題を繰り返し解こう。

なぜなら・・・おっとこれは書けない。

26 May 2017, 16:28

Emacs で conda.el をつかって環境が切り替えられない時の対処方法

Emacs で、anaconda 環境を切り替える便利な eLisp に conda.el というものがある。

しかし、これがどうもうまく動かなかったので調査してみた。

環境

  • fish shell 2.5.0
  • Emacs 25.1.2

事象

conda-env-activate を使うと、切り替わったよというメッセージはでるが、 実際は Anaconda の root を使っている。指定した環境を使ってくれない。

原因

PATH に何が設定されてるか調べてみると。 (getenv "PATH")

"/home/tsu-nera/anaconda3/envs/kaggles/bin:/home/tsu-nera/.rbenv/shims:/home/tsu-nera/anaconda3/bin:/home/tsu-nera/.cask/bin:/home/tsu-nera/bin:/home/tsu-nera/go/bin:/home/tsu-nera/.rbenv/bin:/home/tsu-nera/script/scala:/home/tsu-nera/script/ruby:/home/tsu-nera/script/sh:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin"

つまり、二つのパスが登録されている。

  1. /home/tsu-nera/anaconda3/envs/kaggle/bin
  2. /home/tsu-nera/anaconda3/bin

使いたいのは、1 のほうで2はいらない。

なぜかわからないが、Emacs を起動すると、PATH を自動で読み込んでくれるようなのだ。

こんな機能しらないぞ!exec-path-from-shell をつかって実現する機能ではなかったか? デフォルトで PATH を引き継ぐように仕様変更されたのか??

解決方法

fish shell の環境設定ファイル(自分の場合は env.fish に分けている)、 から、anaconda のパスを削除すると、Emacs で conda-activate をつかった切り替えができる。

しかし、これでは、ふだん conda コマンドが使えない。

そこで、fish shell にこんな関数を定義した。まず Emacs を立ち上げた上で、conda を有効にする。

# anaconda
function conda-activate
    set fish_user_paths $HOME/anaconda3/bin $fish_user_paths
end

一時しのぎだけれども、これで Emacs から conda で環境を切り替えることができるようになった。

21 May 2017, 03:01

ディープラーニング(char-rnn)でバッハの音楽を生成してみた

前回、テキストで音楽を表現する方法 を調べた。今回は実際に char-rnn を利用して音楽を生成してみた。

まずは結果から

バッハのインベンションの No.1 - No.15 の全 15 曲を学習データにして、 char-rnn を利用して学習させた。結果がこちら。

無調音楽に近いような感じ。

実装

以下のサイトの記事を真似しました。

参考にした記事では、karpathy さんの char-rnn をそのままつかっていたけれども、 理解を深めるために Tensorflow で char-rnn を実装した。 といっても、Udacity で学んだことを応用しただけ。

その他、

  • テキスト形式としては、**kern 記譜法を採用。
  • 音楽を扱うライブラリは music21 を利用。

今回の Jupyter Notebook はコチラ。いつものようにコードを抜粋しながら説明。

KernScore からデータ取得

KernScores には、大量のクラシック音楽の **kern 記譜法でかかれた楽譜が置いてある。 まずは、バッハのインベンションの楽譜を取得した。

from urllib.request import urlopen
for i in range(1,15+1):
    filename = "inven{0:02d}.krn".format(i)
    file = urlopen("http://kern.humdrum.org/cgi-bin/ksdata?l=osu/classical/bach/inventions&file=%s&f=kern"%filename)
    with open("kernscore/bach/"+filename,'wb') as output:
        output.write(file.read())

データを char-rnn に食わせるために整形

データを見てみると余分なものがあることに気づく。これはいらない。

  • metadata
  • コメント
  • 小節記号
!!!COM: Bach, Johann Sebastian
!!!OPR: Inventio
!!!OTL: Inventio 1
!!!XEN: Two-part Inventions [for keyboard]
!!!ONM: No. 1
!!!ONB: In C major.
!!!SCT: BWV 772
!!!YEC: Copyright 1994, David Huron
!!!YEM: Rights to all derivative electronic formats reserved.
!! Performance duration: 1:29; performance tempo: 59.3 quarter-notes per minute.
!! (Andras Schiff, piano, "Two-Part Inventions BWV 772a-786; Three-part
!! Inventions BWV 787-801" Decca 411 974-2)
**kern  **kern
*staff2 *staff1
*clefF4 *clefG2
*k[]    *k[]
*C: *C:
*M4/4   *M4/4
*MM59.3 *MM59.3
=1- =1-
2r  16r
.   16c
.   16d
.   16e
.   16f
.   16d
.   16e
.   16c
16r 8g
16C .
16D 8cc
16E .
16F 8bM
16D .
16E 8cc
16C .

...

.   16b
=22 =22
1CC; 1C;    1e; 1g; 1cc;
==|!    ==|!
*-  *-
!!!CDT: 1685/3//-1750/7/28
!!!OCY: Deutschland
!!!AGN: polyphony
!!!AST: baroque
!!!AMT: simple quadruple
!!!SCA: Bach-Werke-Verzeichnis
!!!YOR: Bach Gesellschaft
!!!AIN: cemb; clavi
!!!EEV: 1.0
!!!RDT: 1986 November
!!!YER: 1995 May 22
!!!YEN: Canada
!!!EFL: 1/15
!!!EED: David Huron

これらを除去して、インベンション 15 曲を一つのファイルに出力する。

import glob
REP="@\n"
def trim_metadata(output_path, glob_path):
    comp_txt = open(output_path,"w")
    ll = glob.glob(glob_path)
    for song in ll:
        lines = open(song,"r").readlines()
        out = []
        found_first = False
        for l in lines:
            if l.startswith("="):
                ## new measure, replace the measure with the @ sign, not part of humdrum
                out.append(REP)
                found_first = True
                continue
            if not found_first:
                ## keep going until we find the end of the header and metadata
                continue
            if l.startswith("!"):
                ## ignore comments
                continue
            out.append(l)
        comp_txt.writelines(out)
    comp_txt.close()



output_path = "composer/bach.txt"
glob_path = "kernscore/bach/*.krn"
trim_metadata(output_path, glob_path)

char-rnn で音楽生成

ここからのコードは、Udacity で与えられたコードをほぼそのまま使った。 ハイパーパラメータは、以下のとおりに設定した。これで、学習時間が 30 分くらい。 曲の完成度からみると、これではすくないような気もする。

batch_size = 10
num_steps = 10 
lstm_size = 512
num_layers = 2
learning_rate = 0.001
keep_prob = 0.5

出力データのフォーマットを整える

出力データが 結構ぐちゃぐちゃに吐き出される。

  • 右手左手の 2 行だけでよいのに、3 行目がある。
  • 右手パートしかない
  • 左手パートしかない
  • 終端マークが途中で現れる。

これらを解消するために、**kern 記法に沿ったフォーマットで吐き出されるようにした。

ついでに、メタデータと小節番号の bar も追加。

r = []

r.append("**kern\t**kern\n")
r.append("*staff2\t*staff1\n")
r.append("*clefF4\t*clefG2\n")
r.append("*k[]\t*k[]\n")
r.append("*C:\t*C:\n")
r.append("*M4/4\t*M4/4\n")
r.append("*MM80\t*MM80\n")

bar = 1
for line in samp.splitlines():
    sp = line.split('\t')
    if sp[0] == '@':
        r.append("={bar}\t={bar}\n".format(bar=bar))
        bar += 1
    else:
        ln = len(sp)
        if ln == 1 and sp[0] != "":
            r.append(sp[0])
            r.append('\t')
            r.append('.')
            r.append('\n')
        elif ln == 1 and sp[0] == "":
            r.append(".")
            r.append('\t')
            r.append('.')
            r.append('\n')
        elif sp[0] == "*-" or sp[1] == "*-":
            continue
        else:
            r.append(sp[0])
            r.append('\t')
            r.append(sp[1])
            r.append('\n')

r.append("==|!\t==|!\n")
r.append("*-\t*-\n")

open("results/bach2ai.krn","w").writelines(r)

これで、楽譜が完成!

midi 吐き出し

あとは、これを midi に吐き出して再生するだけだ。

from music21 import *
m1 = converter.parse("results/bach2ai.krn")
m1.write('midi', fp='midi/bach2ai.mid')

Jupyter Notebook 上でも再生できる。

m1.show("midi")

おわりに

今回は、あまり満足のいく作品ができなかった。改善点としては、

  • char ベース見ていくのではなくて、音符単位(8a, 7b など)で音を見る
  • 左手、右手を分けて音を見ていく
  • 学習をもっと実施する、ハイパーパラメータの調整

などが考えられる。とはいえ、音楽をディープラーニングで生成できた。 ディープラーニングを学ぶ動機のひとつが音楽生成だったので、達成できて嬉しい。

音楽に関係する取り組みは、char-rnn ベース以外にもあるみたいだ。 今後は、これらを理解していくことにしよう。

19 May 2017, 07:49

テキストで音楽を表現する方法を調べた

テキストで音楽を表現する方法を調べた。

char-rnn で音楽生成したい

以前の記事で、char-rnn というものを試して、 坊ちゃんのテキストからテキスト生成をすることを試した。

これを音楽に応用してみたい。今回の記事はその準備として情報収集をした。

こういうテキストから LSTM を使って音楽を生成する試みは、いろんな人がやっている。 発端となっているのは、Andrej Karpathy 氏のブログ記事。

Andrej Karpathy さんは、Touch で char-rnn を実装している。

私は最近、TensorFlow や Keras による、char-rnn の実装を勉強した。

Keras が好きなので、勉強のために Keras で実装したいと考えている。

記譜法を調べた

ABC 記譜法

ABC 記法はわりと有名な記法。WikiPedia にも情報がある。

以下の特徴がある。

  • アスキー文字で音楽を表現
  • 関連ソフトウェアが豊富
  • 民族音楽に強い

ABC 記法から、五線譜に変換して再生する OSS.abcjs. これは凄い。

データベース・音源集

LSTM に応用した事例

**kern notation

マイナーな記法。

データベースにクラシック音楽の曲がたくさんあるのが魅力。

ツールとしては、music21 をつかう。これは、DeepJazz でも使われている。

music21 はデータベースが充実しているけれども、データ形式が XML 形式だから char-rnn には使えないかな。

LSTM に応用した事例

自力で midi から text 変換

そういう手法もある。欲しいデータがみつからなかったら、この手も使う。