頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


matplotlibでグラフを描こうとするとエラー

Pythonで計算した結果をグラフにしようとしたらエラーが出て困った、というお話。

QObject::connect: Cannot connect NavigationToolbar2QT::message(QString) to (null)::_show_message()

ってエラーが出る。なぜだ?matplotlibでグラフって前にもやってるのに、、、?
そのコードを探して持ってきて実行させてもやはり同じエラーが出る。
エラーメッセージで検索するとバージョンが古いんじゃね?という記述を見たので、自分の環境を調べてみた。

import matplotlib

print(matplotlib.__version__) # 1.5.1
1.5.1で古いんかな?pip install matplotlib してみるけど
Requirement already satisfied: matplotlib
てな感じで最新版ダウンロードしてるようにも見えないし、、、

以前やったコードを「そのまま」実行させたらちゃんと動いた!

matplotlibによるグラフ

つまり、、、そういうことか!

PyQtによるメニュー画面

↑今はこんな感じのPyQt5使ったメニュー画面を経由したところでmatplotlibでグラフ表示させようとしてる。
どうやらそれがダメらしい。メニュー画面を経由しなければいけた。

PyQt5 Matplotlib – Python Tutorial
↑こんな感じでPyQtのメインウインドウにグラフを描くのはできるみたいなんだけど、描きたいのはサブウインドウに、なんだよなあ、、、うーん。
何かやり方はあるのかもしれないけど、、、
結局下のようなおきまりのコードを追加して直接このファイルを実行するようにした。

if __name__ == '__main__' :
    showGraph()
↑Pythonを勉強し始めた頃には何の役に立つの?と思っていたけど、大助かりだわ。


SceneKitでシェーダーを適用したのに一部しか反映されない

Blenderで作成したオブジェクトをdaeファイルで出力→SceneKitで使おうとしたけどうまく認識できていない?って妙な不具合に悩んでいた。まあ同じような症状にはまる人もいないと思うけど、とりあえず書いておく。

Blenderでオブジェクト作成

↑Blenderではこんな形状。これで1つのオブジェクト。ボーンが設定されてるんだけど本筋には関係なかった。
これをdaeファイルで出力。

SceneKitでdaeファイルの表示

↑SceneKitで使う。ここまではいいんだけど、このオブジェクトにシェーダーを適用すると、、、

SCNNodeにシェーダー適用

↑片側しか適用されない?なんでや?

Xcodeでdaeファイル確認

↑もしかして二つのSCNNodeオブジェクトになってんの?と思い、Xcode上でオブジェクトの構成を確認しても1つのオブジェクトみたい。
いろいろ試したり、調べてたりしたんだけど、daeファイルの中身を見てたらマテリアルが二重に設定されてることに気付いた。

Blenderでのマテリアル設定

↑Blenderで確認すると確かに設定したつもりはないんだけど二つある。片方を削除してやったら、、、

SCNNodeにシェーダー適用(修正後)

↑いけた!そういうことだったのか。
確かに、コードでも最初のmaterialにだけシェーダを適用するように書いてたわ。
{
    SCNGeometry *geometry = node.geometry;
    SCNMaterial *material = geometry.firstMaterial;

    SCNProgram *program = [SCNProgram program];
    program.vertexFunctionName = @"myVertex";
    program.fragmentFunctionName = @"myFragment";
    material.program = program;
}



機械学習で株価予測やってみたが

今更かよってネタだけどTensorFlow使って株価予測をやってる。
やってみたけどうまくいかないって内容だけど、、、現時点での備忘録。

1)データセット
スクレイピングなどのデータ収集方法は置いといて、、、
学習データには日付、日経平均、JASDAQ指数、ドル、ユーロと予想の対象となる株価(今回はトヨタ 7203)を使ってる。売買の手数料については無視(俺の場合だと信用取引で100万円betしても税込388円だし)。

ユーロが1991年1月から導入されたとかなんとかで、自分が収集した方法ではこのユーロが一番データ数が少ない。1991年1月から2017年6月末までを学習データ、7月から12月末までをテストデータとしてデータセットを作成。
寄りで買うか売り、引けでその反対の売買をする。信用取引で売りからもあり。宵越しの株は持たない。

1つのデータは以下のようなデータを持つ。
横幅はn日分、縦は項目(上記の日付、日経平均など)、奥行きが4つで始値、高値、安値、終値の4つ。悩んだけど、出来高は考慮外。

正解は 終値/始値 の値をベースに9種類とした。ざっくり下のような感じ。5から8はマイナス側。
0 +6%超
1 +4%〜+6%
2 +2%〜+4%
3 0%〜+2%
4 変化なし

確率分布図1
↑理想的には確率分布を求めるイメージ。
あと、学習には使わないけど実際にbetした場合の利率(一番知りたい値だよね)を計算するために 終値/始値 の値も入れてる。


2)NNの構成
上記のようなデータにしたのはCNN(畳み込み)で解いてみようとしたため。MNISTとかだと画像が白黒だったのでチャンネル(画像の奥行き)が1だったが、今回は4。Cifar10はカラー画像なので参考になるかも。
なお、今回のデータを4チャンネルの画像としてデータ化すると1つの値が8ビットしかないので無次元化すると高値も安値も同じ値になるかもしれないので注意(いや、俺が実際画像を作って気付いたんだけどね)。32bitの浮動小数点数で扱ってる。
畳み込みなのでCifar10みたいな畳み込み層2つにLRN層、ドロップアウト、全結合層、出力層ってよくある感じ。


3)損失関数、期待値
損失関数にはソフトマックス関数を使っているので各ラベルの確率を得ることができる。
画像認識なんかでは単に一番確率の高いのを選ぶのが一般的だけど、今回は確率分布を得ているつもりなので、期待値の高い方にbetすることにする。

確率分布図2
↑極端な例だけどこういう場合、確率が一番高いのはマイナス側にあるので売りがよさそうに見えるけど、買いと売りだと買いの方が期待値(面積だよね)が高くなるので買いにbetする。この期待値うんぬんは学習時には関係なくて、テストデータの検証でのみ使う。


4)結果

TensorBoadによる損失関数の値変化
↑学習するやん!と喜んだのだが、、、学習が進むめば進むほど損失関数の値が学習用のデータに対する値と、テスト用のデータに対する値でどんどん乖離していった。
的中率や肝心の利率も同様で、正解率はせいぜい43%程度、半年での利率は0から-3%という結果に(パラメータをいじってもたいしてよくならなかった)。

ちなみに学習データに対してはツイートもしたけど、、、



こういう値がテストデータで出るのを期待してたんだが。
データ数少ないよねえ、、、1991年からで5,400個程度だしなあ。


5)雑感
こういうわけのわからん株価データに対してもちゃんと学習が進むんだなあ、というのには感心した。NNの表現力というか。機械学習やTensorFlowの研究者、開発者にほんとリスペクトである。

それと相場ってのはやっぱり掴み所がないんだねえ。26年間のデータに対し90%正解率あるモデルでも、いざ新しいデータに対しては50%いかないんだもの。


動くようになったらNNの構成やパラーメータをいじったりしないと、と思ってたけどそれ以前に圧倒的にデータ数が足りないみたい。ここをなんとかしないとねえ、、、


TFRecordで多次元配列を扱う

TFRecordでたくさんの浮動小数点数を扱う
numpyで値の型を指定したつもりが
↑このあたりに関連したデータの整形のお話。

TensorFlowで多次元の配列でデータを受け取りたいとする。
まずは保存。上記リンクにあるようにnumpyを使う。3次元の場合はこんな感じでやってみた。値は32bitのfloatで。
{
    CH = 4
    W = 3
    H = 2
    ite = 0
    arr_h = np.zeros([0,W,CH] , dtype=np.float32)
    for h in range(H) :
        arr_w = np.zeros([0,CH] , dtype=np.float32)
        for w in range(W) :
            arr_ch = np.zeros([0] , dtype=np.float32)
            for ch in range(CH) :
                arr_ch = np.append(arr_ch , np.float32(ite)) 
                ite += 1
            arr_w = np.append(arr_w , [arr_ch] , axis=0)
        arr_h = np.append(arr_h , [arr_w] , axis=0)
    print(arr_h)
}
#[[[ 0. 1. 2. 3.]
# [ 4. 5. 6. 7.]
# [ 8. 9. 10. 11.]]
#
# [[ 12. 13. 14. 15.]
# [ 16. 17. 18. 19.]
# [ 20. 21. 22. 23.]]]

↑結果。意図通り2x3x4の3次元配列になってる。append時のキャストが必要なのはリンクの通り。
これをTFRecordに書き込んだとする。
次に、このデータを使う時に読み込む場合。
{
    features = tf.parse_single_example(
                                       serialized_example,
                                       features={
                                       'arr_h': tf.FixedLenFeature([], tf.string),
                                       })
    arr = tf.decode_raw(features['arr_h'], tf.float32)
    arr = tf.reshape(arr, tf.stack([2,3,4]))
}
reshapeが必要。画像サイズがまちまちだと画像ごとにW,H,CHの値を持たせてる場合もあったと思う(確かcifar10とか?)が定数なら持たせなくてもいいか。
TensorFlowのテンソルとして値を表示させてみると、、、

_arr1=[[[[ 0. 1. 2. 3.]
[ 4. 5. 6. 7.]
[ 8. 9. 10. 11.]]

[[ 12. 13. 14. 15.]
[ 16. 17. 18. 19.]
[ 20. 21. 22. 23.]]]]

ふんふん、それらしくなってるな。とまあここまでしか確認はできていなくて、これからこれらを使って実際に学習が進むかってのをやっていくわけだけど。


numpyで値の型を指定したつもりが

TFRecordでたくさんの浮動小数点数を扱う
↑これに関連するnumpyの話。

numpyで配列を作る時に空の配列を用意してそこに値を入れていく、ってのをやろうとしたんだけど、この場合、最初の空の配列をどうするのか?いくつかあるみたいでこれが定番!というのがよくわからなかったんだが、とりあえずzerosを使うことにした。それ自体はいいんだと思うが、、、

↓これを実行すると
{
    a = 1.
    b = 2.
    arr = np.zeros([0] , dtype=np.float32)
    arr = np.append(arr, a)
    arr = np.append(arr, b)

    print(type(a))
    print(arr)
    print(type(arr[0]))
}
<class ‘float’>
[ 1. 2.]
<class 'numpy.float64'> ←な、なんですとー?!

↑こんな結果になる。
zerosのところで型指定して32bitの値が入るんだろうと思いきや、appendで入る値は64bitのままになってる。

これになかなか気付かず、TensorFlowのTFRecordで作成したデータが意図通りに読み込めずにうんうんと悩んでた。

arr = np.append(arr , np.float32(a))
のようにキャストすればいけた、、、けど、じゃあzerosでの指定はなんやねん?!


Python 3.5.2 :: Anaconda 4.1.1 (x86_64)




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad