書評 – TensorFlowで始める株式投資のためのディープラーニング

手習いでPython(Windows10-Anaconda3-Jupyter Notebook) を応用できる分野として数年前からブームとなっているAIによる株価分析に興味を持っており、TensorFlowを始めたい初学者にも再現性のある本書。

TensorFlowで始める株式投資のためのディープラーニング| Amazon.co.jp

実際に全銘柄データをダウンロード、Pythonでマージするところから第1章を始めて、第2章で古典的な線形回帰分析、第3章はディープラーニングの概念、理論の説明、第4章で実際にTensorFlowで分析した結果を線形回帰分析した結果と比べて評価するまでを学習者とデータ加工、表、グラフへの出力をしてゆきます。プログラムコードはURLからもダウンロードできるのでタイプが苦手な人にもGoogle力とデバッグ知識があれば再現可能な内容となっています。AIをはじめ、ディープラーニング、機械学習の概念をつかむのに画像解析だけじゃないところが画期的といえましょう。Python で株式投資の奥深い概念をどこまで応用できるか興味のある人には最適な入門書だと思います。

to_csv のencoding オプション

Python3 でリストをcsv として保存したものをExcel で開くと文字化けする件。read_csv でencoding を指定したのと同じものをto_csv のオプションに指定したら解決しました。

・
・
csv_name = "\price_data.csv"
data.to_csv(OUT_DIR + csv_name, encoding = 'sjis', index = False)

to_csv のencoding のデフォルトは ‘utf-8’ なので指定必須でした。

TensorFlow2.1.0 環境構築(Windows10)

突然ですがAnaconda にディープラーニングのライブラリーTensorFlow 環境を構築したいと思い、Google先生に訊いたところ

初心者がGPU搭載Windows10にPython + Anaconda + TensorFlow + Kerasの環境を構築してみた[2018/4/28]

上記Tips が見つかったので試したことをメモします。

エディション Windows10 Pro
バージョン 1903
マザーボード Asrock Z370 Pro4
CPU    Intel Core i7 8700K
メモリ   16.0GB
GPU    Nvidia Quadro P2000

まずは下記手順にてAnaconda Promptを管理者として実行してAnacondaをアップデート。(参考:Windows環境でのAnacondaのアップデート

Anaconda本体をアップデートする
> conda update -n base conda

Anacondaすべてのパッケージをアップデートする
> conda update --all

AnacondaのPythonをアップデートする
> conda update python

Pythonのバージョン確認
> python --version
Python 3.7.6

Microsoft Visual Studio 2019 Community 無料ダウンロード
https://visualstudio.microsoft.com/ja/downloads/

からC++ のパッケージをインストール

続いてNvidia CUDA toolkit10.1 をダウンロード、インストール
https://developer.nvidia.com/cuda-toolkit-archive

バージョンは最新の10.2 だとdllエラーがでたので、ひとつ下のグレードでよかったみたいです。

https://developer.nvidia.com/rdp/cudnn-download から cuDNN v7.6.5 [November 5th, 2019] for CUDA 10.1をダウンロード、解凍して

bin,include, lib 各フォルダを C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1 に上書きコピー。

Anaconda Navigator の[Environments]から仮想環境を[Create]、tensorflow と入力して [Create]


[Not Installed] からanaconda 関連のパッケージを検索して、[Apply] すると仮想環境にanaconda のインストールが完了します。

Anaconda Prompt (tensorflow) をスタートメニューから管理者として起動してtensorflow-gpu, keras をインストール。

追記)Anaconda Navigator のEnvironments からGUIでtensorflow関連のパッケージをインストールもできますけどバージョン違いでエラーがでるのですべて信頼はできません。

> pip install tensorflow-gpu
> pip install -U tensorflow keras

最初、pip install keras したのですが、AtrributeError が出たので一旦、pip uninstall keras して再度、pip install -U オプションすると上手く行きました。(まぐれ当たりでしょうか?)スタートメニューからJupyter Notebook (tensorflow)を起動してバージョン確認。

pip list | find "tensor"
tensorboard 2.1.0 tensorflow 2.1.0 tensorflow-estimator 2.1.0 tensorflow-gpu 2.1.0 tensorflow-gpu-estimator 2.1.0
import keras print(keras.__version__)
Using TensorFlow backend. 2.3.1

めでたくUsing TensorFlow backend. が表示されました。

TensorFlow 2.x のバージョンからTensorFlow 1.x のコードを実行したいときは

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

とするとハッピーになれるようでした。(下記サンプルコード転記)

import tensorflow.compat.v1 as tf
import numpy as np

tf.disable_v2_behavior()
# Create 100 phony x, y data points in NumPy, y = x * 0.1 + 0.3
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3

# Try to find values for W and b that compute y_data = W * x_data + b
# (We know that W should be 0.1 and b 0.3, but TensorFlow will
# figure that out for us.)
W = tf.Variable(tf.random.uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# Before starting, initialize the variables.  We will 'run' this first.
init = tf.global_variables_initializer()

# Launch the graph.
sess = tf.Session()
sess.run(init)

# Fit the line.
for step in range(201):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(W), sess.run(b))

# Learns best fit is W: [0.1], b: [0.3]

try-except (Python)

Python で受け取った入力値の型が間違っているときはエラー(この場合はValueError)がでますが、そんな例外を処理する予約語としてtry except 文が用意されています。以下のコードは西暦を干支に変換するコードですが、半角数字が入力されないときのエラーを例外処理しています。
try:
(処理)
except(ValueError):
(例外処理)

eto.py

eto = ["申","酉","戌","亥","子","丑","寅","卯","辰","巳","午","未"]
try:
    x = input("生まれた年を西暦で入力してください。: ")
    y = int(x)
    y = y % 12
    print("あなたの干支は {} です。".format(eto[y]))
except(ValueError):
    print("4桁の半角数字を入力してください。")

あらかじめエラーが予想される処理をtry 文に投げて、except(エラーの種類)文で例外処理をします。エラーの種類は、データ型のエラー(ValueError)のほかに、0で割り算をした時のZeroDivisionError などがあります。

openメソッド(Python)

外部の.txt ファイルを読み込むopen メソッドについて調べたのでメモ。

pythonでlistをファイルに保存し、読み込む方法(numpyも同様!)

Titles.txt

Stand Still - Wave Racer Remix
Slumber Party
Milky Way Stars (feat. TR)
At The End Of The Night

上記のような素のテキストファイルをリストに読み込みたいとして。

open(‘ファイルパス’, ‘モード’, <option>[encoding=’utf-8′])

ファイルパス ‘filepath/filename’ スクリプトからの相対参照
モード r 読み込み用
w 書き込み用
a 追加書き込み
r+ 読み込みと書き込み
w+ 読み込みと書き込み
a+ 読み込みと書き込み
b バイナリモード
option encoding utf-8, cp932(SJIS)など

open_file.py

Titles = []
f = open('Titles.txt', 'r')  
for x in f: 
    Titles.append(x.rstrip("\n")) 
for title in Titles: 
    print(title) 
f.close()

Titles.txt を読み込みモード’r’ でファイルオープンして、リストに一行づつ追加していきます。
for ループを2回廻すのがスマートではないですがリストの内容をプリントアウトしています。

f = open('Titles.txt', 'r') 
・ 
・ 
・ 
f.close()

とするところを、close忘れを防ぐ意味もあってwith ~asと記述するとファイルをオブジェクトf として扱えます。

Titles = []
with open('Titles.txt', 'r') as f:  
    for x in f: 
        Titles.append(x.rstrip("\n")) 
        print(x.rstrip("\n"))

1行づつファイルを読み込む上記コードもreadメソッドを使えばまとめてリストにできますね。改行コードも関係ないのかな。これ、もう分かんねえなぁ。

Titles = []
with open('Titles.txt', 'r') as f:
    Titles.append(f.read())
for x in Titles:
    print(x)

追記)Windows10 のVisual Studio Code のデバッグ機能を使って外部ファイルの読み込みをしていましたが一向に出力してくれないので、CentOS のbash を使ったところ正常に読み込んでくれました。

訂正)まとめてreadメソッドで読み込むコードのforループの参照オブジェクトに誤りがありましたので修正しました。

continue と break (Python)

突然ですが、Python でループの途中に処理を飛ばしたいときやループを中止したいときに用意されている予約語、continue と break を使ったスクリプトの例を作ってみました。

continue はループの途中でif 文で条件分岐を挟むとそれ以降のコードが実行されずに飛ばされます。

break はやはりif 文で条件分岐を挟んでループ処理そのものを中止します。

Titles = [
	"Discopolis 2.0 - Fehrplay Remix",
        "Never Alone - J-Kraken Remix",
        "Golden",
        "Steal Your Heart",
        "I Want You To Know",

]

Artists = [
        "Lifelike, Kris Menace, Fehrplay",
        "Chachi, Natascha Bessez",
        "Thomas Hayes, Kyler England",
        "BRKLYN, Lenachka",
        "ゼッド, セレーナ・ゴメス",
        
]

i = 0
for i, new in enumerate(zip(Titles,Artists)):
    new = Artists[i]
    x = input("{} {} / {} | アーティスト名を修正してください。:".format(i, Titles[i], Artists[i]))
    if x == "":
        continue
    elif x == "q":
        break
    new = x
    Artists[i] = new
    print(i, Titles[i], "/", Artists[i])

ループで読み込まれたアーティスト名をリストの最後まで修正し続けるコードですが[Enter]が押されたときはcontinue でスキップ、[q] を入力したときにbreak でループ処理を終了します。

結果

0 Discopolis 2.0 - Fehrplay Remix / Lifelike, Kris Menace, Fehrplay | アーティスト名を修正してください。:[Enter]
1 Never Alone - J-Kraken Remix / Chachi, Natascha Bessez | アーティスト名を修正してください。:[Enter]
2 Golden / Thomas Hayes, Kyler England | アーティスト名を修正してください。:[Enter]
3 Steal Your Heart / BRKLYN, Lenachka | アーティスト名を修正してください。:[Enter]
4 I Want You To Know / ゼッド, セレーナ・ゴメス | アーティスト名を修正してください。:Zedd, Selena Gomez
4 I Want You To Know / Zedd, Selena Gomez

import (Python)

組み込み関数の入ったモジュールや長いプログラム、データファイルを外部から読み込むときの記法としてimport がPythonで用意されています。

書き方として、import print_module as pm としておけば、main.py で外部関数をpm.Hello として読めるということです。

print_module.py

def Hello(name):
	print("Hello {}!".format(name))

main.py

import print_module as pm
 
pm.Hello("World")

結果

Hello World!

事前に辞書ファイルを外部に用意して必要に応じて呼び出すようにすることも出来ますね。

music_list.py

Titles = [
        "Atmosphere",
        "I Need Your Love",
        "Enigma",
        "Addicted To A Memory",
]
Artists = [
        "Husman",
        "First State",
        "Seth Hills",
        "ゼッド",
]
music = dict(zip(Titles, Artists))

query.py

import music_list as mu

title = input("タイトルを入力してください。:")
if title in mu.music:
        print(mu.music[title])
else:
        print("見当たりません。")

結果

タイトルを入力してください。:Addicted To A Memory
ゼッド

※ 訂正)Hello(name) 関数の) が足りない転記ミスを修正しました。

enumerate関数(Python)

前回のエントリーでは複数のリストを辞書として登録するzip関数の使い方を学びました。今回はfor ループでリストのインデックスを扱う、enumerate関数の使い方をめも。

Titles =[
       "Bittersweet - Radio Edit",
        "Anchor",
        "Get There",
        "Set Me Free",
        "Untouchable",
]
Artists = [
        "Dyro",
        "Tritonal",
        "Paris Blohm",
        "Dyro",
        "Tritonal",
]

例えば、タイトルとアーティストの2つのリストをインデックス変数を含めて処理したいときに、for ループの変数に< , > を付けて併記したいとします。ループで取り出した要素がリストの何番目かをPythonが自動的にインデックス値として用意してくれるのがenumerate関数というわけですね。

for i, (Titles, Artists) in enumerate(zip(Titles, Artists)):
    print(i, Titles,"/", Artists)

前回の応用でenumerate関数の引数に2つのリストをzip関数でまとめて渡せばOK。インデックスと2つのリストの処理をいろいろやってくれるスゴイやつです。良いですね。

0 Bittersweet - Radio Edit / Dyro
1 Anchor / Tritonal
2 Get There / Paris Blohm
3 Set Me Free / Dyro
4 Untouchable / Tritonal

zip関数(Python)

Python で順序と数の一致した2つのリストをキーとバリューとする1対の辞書を作りたいときに便利なzip関数の使い方を検索したのでメモ。

Pythonで辞書の初期値をまとめて登録する方法 | Nana-Korobi

zip_function.py

Titles = [
        "Kuaga(Lost Time)(Radio Edit)",
        "Hands",
        "Dreams Lost Kings Remix",
        "We The Fire",
        "NANIMONO(feat.米津玄師)",
        "DREAM ILLUMINATION",
]
Artists = [
        "Pierce Fultion",
        "Gareth Emery",
        "Life of Dillon",
        "赤西仁",
        "中田ヤスタカ",
        "CTS",
]

music = dict(zip(Titles, Artists))
for title in music.items():
    print(title)

新しい空の辞書music をdict で定義するときに引数に2つのリストをzip関数にまとめて渡すとキーとバリューをまとめて登録できるという優れもの。良いですね。

('Kuaga(Lost Time)(Radio Edit)', 'Pierce Fultion')
('Hands', 'Gareth Emery')
('Dreams Lost Kings Remix', 'Life of Dillon')
('We The Fire', '赤西仁')
('NANIMONO(feat.米津玄師)', '中田ヤスタカ')
('DREAM ILLUMINATION', 'CTS')

 

突然ですが、Python 入門

Python には、インタプリタ(対話形式)とスクリプトの2つの方法があります。

python とだけコマンドを打つと対話型のプロンプトで実行可能になります。

$ python
>>>

プロンプトを抜けるには[Ctrl]+[D]です。
一方、テキストファイルに拡張子.py としてプログラムしたスクリプトを実行するにはpython test.py です。

$ vi test.py    # スクリプトを編集
↓ を保存。
print("Hello World!")

$ python test.py    # スクリプトを実行
Hello World!

python 入門

>>> 1+2  # 算術計算
3
>>> 6/5  # 割り算の結果はfloat型に
1.2
>>> 3*4
12
>>> type(1.4)  # データ型の問い合わせ
<class 'float'>
>>> type("hello")
<class 'str'>
>>> x=20  # 変数
>>> print(x)
20
>>> y=15  # 変数同士の演算
>>> print(x+y)
35
>>> a=[1,2,3,4,5]  # リスト
>>> print(a)
[1, 2, 3, 4, 5]
>>> len(a)  # リストの長さを取得
5
>>> a[1]  # リストの要素にアクセス
2
>>> a[4]=99  # リストに値を代入
>>> print(a)
[1, 2, 3, 4, 99]
>>> a[0:2]  # インデックスの0番から2番まで取得
[1, 2]
>>> a[1:]  # インデックスの1番から最後まで取得
[2, 3, 4, 99]
>>> a[:3]  # インデックスの最初から3番まで取得
[1, 2, 3]
>>> a[:-1]  # インデックスの最初から最後のひとつ前まで取得
[1, 2, 3, 4]
>>> a[:-2]  # インデックスの最初から最後の2つ前まで取得
[1, 2, 3]
>>> me={"height":180}  # ディクショナリを作成
>>> me["height"]  # 要素にアクセス
180
>>> me["weight"]=80  # 新しい要素を追加
>>> print(me)
{'height': 180, 'weight': 80}

ブーリアン とif for

&>>> hungry=True    # お腹すいてる?
>>> sleepy=False    # 眠い?
>>> type(hungry)    # 型取得
<class 'bool'>
>>> not hungry    # ブーリアン演算
False
>>> hungry and sleepy    # 空腹 かつ 眠い
False
>>> hungry or sleepy    # 空腹 または 眠い
True

>>> hungry=True    # if 文
>>> if hungry:
...     print("I'm hungry")    # if の中身は行頭空白4つ分インデントを空ける
......
I'm hungry
>>> hungry=False
>>> if hungry:
...     print("I'm hungry")
... else:             # else の中身も行頭空白4つ分のインデントを空ける
...     print("I'm not hungry")
...     print("I'm sleepy")
...
I'm not hungry
I'm sleepy

>>> for i in [1,2,3]:    # for 文(繰り返し)i を print
...     print(i)
...
1
2
3
>>> for i in range(1,11):    # range で指定
...     print(i)
...
1
2
3
4
5
6
7
8
9
10

>>> def hello():    # 関数を定義
...     print("Hello World!")
...
>>> hello()
Hello World!

>>> def Hello(object):    # 引数付きの関数を定義
...     print("Hello "+object+"!")
...
>>> Hello("cat")
Hello cat!
>>>