Pycharm デバッグできなくなる

私はPythonの開発をPycharmというIDEで行っていますが、まだあんまり全貌がつかめていません。Pycharmは2017.3 Communitu Editionです。

特に、実行環境を適当にやっていると、おかしくなります。(適当だから仕方ないね…。)

今日はデバッグできなくなるという事態に遭遇しました。

そんな時は、ここを確認してみてください。

File→Settingus→Project Interpreter

でPythonの実行環境が選べますが、ほかのプロジェクトの実行環境を選んでないでしょうか?

そうすると、実行はできるけれどもデバッグできないようです。

では、今やっているプロジェクトの実行環境を作る方法です。

①File→Settingus→Project Interpreter って選択した後、下記の画面の赤丸の部分をクリックします。

②Add Localを選択します。

③New environmentを選択します。

Base InterpreterでPythonの実行環境を選んでください。

すると、上のLocationのところに、今選択しているプロジェクトの名前+venv という形でパスが自動的に入ると思います。

④OKをクリック

 

Python ArgumentParserでコマンドラインから実行時に強制的に引数を渡させる

きっと書いておかないと忘れるので書いておきます。

ArgumentParserという便利なライブラリがあります。

公式サイトはこちら。

平たく言うと、コマンドラインから

python main.py

って走らせるときに、引数がないと動作しないようにする、とか、ヘルプを表示させたりとか、コマンドラインの引数に応じて、実行することを変えたりすることができるのです。

超シンプルな使い方は下記のようにします。

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')

parser.add_argument('integers', metavar='N', type=int)

args = parser.parse_args()
print(args.integers)

コマンドラインから引数なしで実行すると、次のように表示されます。

 

G:\test>python argparse_sample.py
usage: argparse_sample.py [-h] N
argparse_sample.py: error: the following arguments are required: N

引数を渡すと、次のように引数が表示されます。

G:\test>python argparse_sample.py 5
5

Open AI Gym 初めの一歩

強化学習というのは、機械学習の一つの分野ですが、学習がうまくいっているのかどうか調べるのは難しい課題なんですよね。

そこで、Open AIのGymというツールがあります。

https://gym.openai.com/

なんか、ちょいちょい見る、トンカチみたいなのがゆらゆら揺れてる動画…。これだったんだw

やり方は、次のサイトにある通りですが

https://gym.openai.com/docs/

英語を読むのも「ええい!面倒!!」ということもあると思いますので、超簡単に記載しておきます。

pip install gym

でインスコします。

import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample()) # take a random action

これで走らせてみると、トンカチが一回転して、画面の外に消えちゃいますねw

他に、山を登る車、

'MountainCar-v0'

ってのもあります。さっきのgym.makeの中身を変えるだけです。

import gym
env = gym.make('MountainCar-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample()) # take a random action

これも実行してみると、右往左往してまったく山を登りそうにない車が表示されます。
やはり、ランダムに何かを行ってみても何も結果は得られない… という人生の教訓を得た気になりますね!!

ちょっと進めて下記のようにします。

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

実行すると、ポールが倒れたり、画面の外に行ったりしません。

一瞬おお!と思いますが、落ち着こう。

 

observationというのをprintするようにしたので、次のようにprintされますが

[-0.06550298 -0.62622142 0.12089567 0.99951833]
[-0.07802741 -0.82273366 0.14088604 1.32759199]
[-0.09448208 -0.62964272 0.16743788 1.08210892]
[-0.10707494 -0.4370784 0.18908006 0.846299 ]
[-0.1158165 -0.24496922 0.20600604 0.6185299 ]
….
Episode finished after 16 timesteps

そもそも、この4つの数字なんだ!って話ですよね。

この答え、CartPoleのソースコード見ると書いてありました。(他のところにもかいてほしぃ…)
https://github.com/openai/gym/blob/master/gym/envs/classic_control/cartpole.py

Observation:
Type: Box(4)
Num Observation Min Max
0 Cart Position -4.8 4.8
1 Cart Velocity -Inf Inf
2 Pole Angle -24° 24°
3 Pole Velocity At Tip -Inf Inf

そして、そもそも終了条件ってなんなん??

って思うと、これもソースコード見ると書いてありました。

Episode Termination:
Pole Angle is more than ±12°
Cart Position is more than ±2.4 (center of the cart reaches the edge of the display)
Episode length is greater than 200
Solved Requirements
Considered solved when the average reward is greater than or equal to 195.0 over 100 consecutive trials.

1.ポールの角度(さっきのObservationの3つ目ですね)が±12を超える
2.カートのポジション(さっきのObservationの1つ目ですね)が±2.4を超える
3.エピソードの長さが200以上
4.解決されたと思われる 平均的な報酬が100回の連続したトライアルの中で195を超える

報酬は、1回進めて、倒れなかったら1もらえるので、200回エピソードを繰り返して、195回目まで倒れなければ、そのモデルが優秀ということで、もうOKってことなんですかね。

Actionは左に行くか、右に行くかだけですが、これにVelocityなどが加わって、どのぐらいのポジションを進むかが決定されるようです。

倒れなくなったように見えますが、そうではなく、倒れようとしたところで(doneがTrueになる)env.resetされるので、倒れなくなったように見えるだけです。

 

 

GiHub(Sourcetree)のコミットの取り消し

今回原因不明のバグに遭遇してしてしまい(解決したが)、コミット前の状態に戻そうとしたら思いの外手こずったので、忘れん坊の自分のためにメモを残しておきます。

プッシュ前とプッシュ後で変わってくるので要注意!!

 

・プッシュ前のコミット

プッシュ前のコミットであれば、自分が戻したい位置のコミットにカーソルを合わせ右クリックする。次に、「現在のブランチをこのコミットまでリセット」をクリックする。

・プッシュ後のコミット

プッシュ後となると少し話が変わってくる。自分の消したいと考えるコミット内容にカーソルを合わせ右クリックする。次に、「このコミットを打ち消し…」をクリックする。

Python -(マイナス)記号をつける場所を注意しましょう

Pythonに限ったことではないと思うんですが。とりあえず、私は機械学習のことをやるまでは、あまり数学的なことにプログラミングで取り組んでいなかったので、今回思わぬところにはまってしまったので書いておきます。

下記のような式があります。

[(x[0],x[2],r*((-1)**(x[1]!=hoge))) for x in trainExamples]

これは、次のように分解できるかと思います。

trainExamples =[
                 [3,1,2],
                 [4,-1,1]
                 ]
hoge = 1
r = -1

for x in trainExamples:
    a = x[0]
    b = x[2]
    c = r* ((-1) ** x[1] != hoge)

    print(a, b, c)

次の

c = r* ((-1) ** x[1] != hoge)

部分なんですけど、

x[1] != hoge

はTrue かFalseなので、1か0ということだと思います。

つまりは -1**True か -1**Falseってことですね。

 

しかし、

-1**True

ってやっても

-1**False

ってやっても、答えは -1 なんです。ん?そもそも判定の意味ないぞー?

って思ってたら、元のコードをよく見ると

(-1)**True

(-1)**False

ってやらなきゃいけなかったんですね( ゚Д゚)

 

(-1)**True は -1

(-1)**False は 1

です。

 

-1**True、-1**False とか、1に1乗するか、1を0乗するかした後、マイナス1をかけているので、どちらも-1になるわけです。

カッコの場所でエライ違いだった。

はぁー、むずかし。

 

ちなみに、0乗とか?-1乗とか?についてさっぱり忘れてしまったので、次のサイトさんを参考にさせて頂きました。m(_ _)m

べき乗とは何か。ゼロ乗・マイナス乗・分数乗・無理数乗ってどういう意味?

https://atarimae.biz/archives/20521