覚え書きブログ

強くなるロボティック・ゲームプレイヤーの作り方勉強会

私が執筆した「強くなるロボティック・ゲームプレイヤーの作り方」の勉強会が開催されていたらしい。声をかけてくれれば参加したのに。。。

techplay.jp
techplay.jp

Pythonによるデータ解析1(3/3)

hirotaka-hachiya.hatenablog.com

Pythonによるデータ解析1(2/3)の目次】



リスト内包表記のPythonスクリプトの例

pythonには、C言語と類似の記述方法のfor文とif文がありますが、さらに、リストの括弧[]内にfor文やif文を記述するリスト内表記という方法があります。

import numpy as np

values = np.array([10, 3, 1, 5, 8, 6])

#---------------
# 通常のfor文
passed_values = np.array([])
for ind in np.arange(len(values)):
	#通常のif文
	if values[ind] > 5:
		passed_values = np.append(passed_values,values[ind])

# 結果を標準出力
passed_values = passed_values.astype('int') #int型にキャスト
print("5以上の値",passed_values)
#---------------

#---------------
# リスト内包表記のfor文
passed_values = values[[values[ind] > 5 for ind in np.arange(len(values))]]

# 結果を標準出力
print("5以上の値",passed_values)
#---------------

上記のスクリプトをファイルfor_loop.pyに保存し以下のように実行します。

> python loop.py
5以上の値 [10  8  6]
5以上の値 [10  8  6]

ここで、以下のようにlen(x)はxの長さを返し、np.arange(x)はarray([0,1,2,..,x-1])を返えす関数となっています。

(Pdb) len(values)
6
(Pdb) np.arange(len(values))
array([0, 1, 2, 3, 4, 5])

また、通常のfor文とif文は以下の形式で記述します。

for 変数A in データ集合:
    変数Aを用いた処理A
if 条件:
    処理B

一方、リスト内包表記は以下のようなフォーマットとなっていて、for文を一行で記述することができます。

[変数Aを用いた処理A for 変数A in データ集合]

このリスト内包表記により、通常のfor文とif文では4行必要な処理を、1行で記述することができます。

演習3: numpy.whereを用いて、5より大きい値を持つ変数valuesの要素のインデックスを取得するように、リスト内包表記を用いて一行で記述してみましょう。なお、numpy.whereは、以下のように、リスト内の真値の要素のインデックスをnumpy.arrayで返す関数です(詳細については、以下を参照してください:https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.where.html。)

 (Pdb) np.where([True, False, True])
(array([0, 2], dtype=int64),)



オブジェクト指向Pythonスクリプトの例

Pythonでは、関数とクラスの定義を以下のような形式で記述します。

def 関数名(引数1,引数2, ...):
	関数の処理
class クラス名:
    def __init__(self, 引数1, 引数2, ….):
        #コンストラクタの定義

    def メソッド名(self, 引数1, 引数2, ….):
        #メソッドの定義

ここで、self.xxxはインスタンス変数で、コンストラクタとメソッドの最初の引数はselfを記述しなければなりません。

以下は、

# -*- coding: utf-8 -*-
import os
import pandas as pd
import numpy as np

#-------------------
# クラスの定義始まり
class sentenceData:
	dataPath = 'data'  # データのフォルダ名
	
	# コンストラクタ
	def __init__(self,fname):
		# ファイルのパス
		fullpath = os.path.join(self.dataPath,fname) 

		# csv形式のデータ読み込み
		self.data = pd.read_csv(fullpath,'\t')

	# 文字列検索のメソッド
	def search(self, keyword):
		results = self.data['sentence'].str.contains(keyword)
		return self.data['sentence'][results].values
# クラスの定義終わり
#-------------------

#-------------------
# メインの始まり
if __name__ == "__main__":
	# データファイルamazon_cells_labelled.txtを指定して、インスタンス化
	myData = sentenceData("amazon_cells_labelled.txt")

	# 検索
	results = myData.search("very good")
	
	# 検索結果の表示
	for ind in np.arange(len(results)):
		print(ind,":",results[ind])
#メインの終わり
#-------------------

上記のスクリプトをファイルsentenceData.pyに保存します。
また、sentenceData.pyと同じフォルダにdataというフォルダを作成し、Amazonのカスタマーリビューのデータを、ここからダウンロードし、dataフォルダに置きます。このファイルは、以下のように「sentence」列にカスタマーレビューの文章、および「score」列にスコア(0または1)を格納しています。

                                              sentence  score
    So there is no way for me to plug it in here i...      0
                          Good case, Excellent value.      1
                               Great for the jawbone.      1
    Tied to charger for conversations lasting more...      0
                                    The mic is great.      1
    I have to jiggle the plug to get it to line up...      0
    If you have several dozen or several hundred c...      0
          If you are Razr owner...you must have this!      1
                  Needless to say, I wasted my money.      0
                     What a waste of money and time!.      0
                      And the sound quality is great.      1
    He was very impressed when going from the orig...      1
    If the two were seperated by a mere 5+ ft I st...      0
                             Very good quality though      1
    The design is very odd, as the ear "clip" is n...      0
    Highly recommend for any one who has a blue to...      1
                  I advise EVERYONE DO NOT BE FOOLED!      0
                                     So Far So Good!.      1
                                        Works great!.      1
    It clicks into place in a way that makes you w...      0
    I went on Motorola's website and followed all ...      0
    I bought this to use with my Kindle Fire and a...      1
             The commercials are the most misleading.      0
    I have yet to run this new battery below two b...      1
...

そして、以下のようにスクリプトを実行すると、「sentence」列でキーワード「very good」を含む文章が表示されます。

> python sentenceData.py
0 : The price was very good and with the free shipping and all it was a good purchase.
1 : I love my 350 headset.. My Jabra350 bluetooth headset is great, the reception is very good and the ear piece is a comfortable fit.
2 : very good product, well made.
3 : The design is very good.4.
4 : A lot of websites have been rating this a very good phone and so do I.

上記のスクリプトでは、以下の変数とメソッドを持つsentenceDataというクラスを定義しています。

  • インスタンス変数self.datapath:データが置いてあるフォルダ名
  • インスタンス変数self.data:読み込んだデータを格納するpandas.dataframe
  • メソッドsearch(keyword):keywordで読み込んだデータの「sentence」列で、keywordの文字列を含んでいる文章を返す

また、pandas.Series.str.containsと、pandas.dataframe.valuesについては以下を参照してください。
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.contains.html
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.values.html

宿題: scoreの値が「1」のsentenceを、各要素として格納するnumpy.arrayを返すメソッドを、クラスsentenceDataに追加してみましょう。

Pythonによるデータ解析1(2/3)

hirotaka-hachiya.hatenablog.com

Pythonによるデータ解析1(2/3)の目次】



numpyの数値演算のスクリプトの例

以下は、数値計算用のライブライrnumpyを用いた行列とベクトルの演算( f(\textbf{x}) = \textbf{W}^\top\textbf{x}+\textbf{b})の簡単なスクリプトです。

# -*- coding: utf-8 -*-

# 数値計算用のライブラリnumpyをnpとしてインポート
import numpy as np

# 3x3のnumpy配列(行列)
W = np.array([ [1,0,0], [0,1/2,0], [0,0,1/3] ])

# 3x1のnumpy配列(ベクトル)
x = np.array([ [1], [2], [3] ])
b = np.array([ [1], [2], [3] ])

# 行列Wとベクトルxの掛け算とbとの足し算
f_x = np.matmul(W.T,x) 
f_x = f_x + b

# 標準出力
print(f_x)

上記のスクリプトをファイルnumpy_matmul.pyに保存し以下のように実行します。

> python numpy_matmul.py
[[ 2.]
 [ 3.]
 [ 4.]]

ここで、num.py.arrayは多次元配列を返す関数で、np.array([ [行1], [行2],...])のように、
以下のようにWは3x3の行列、xとbは3次元列ベクトルとして定義されています。

>>> W
array([[ 1.        ,  0.        ,  0.        ],
       [ 0.        ,  0.5       ,  0.        ],
       [ 0.        ,  0.        ,  0.33333333]])
>>> x
array([[1],
       [2],
       [3]])
>>> b
array([[1],
       [2],
       [3]])

そして、numpy.ndarray.Tは行列の転置、numpy.matmulは行列・ベクトルの掛け算を返す関数です。詳細は、以下を参照してください。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.T.html
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.matmul.html



pdbを用いたデバッグ

以下のように、pdbモジュールをインポートし、スクリプトの任意の行に「pdb.set_trace()」を設置すると、その処理を止めて、途中経過を確認することができます。

# -*- coding: utf-8 -*-

# 数値計算用のライブラリnumpyをnpとしてインポート
import numpy as np

# デバッガをインポート
import pdb

# 3x3のnumpy配列(行列)
W = np.array([ [1,0,0], [0,1/2,0], [0,0,1/3] ])

# 3x1のnumpy配列(ベクトル)
x = np.array([ [1], [2], [3] ])
b = np.array([ [1], [2], [3] ])

# 行列Wとベクトルxの掛け算とbとの足し算
f_x = np.matmul(W.T,x) 
pdb.set_trace()
f_x = f_x + b

# 標準出力
print(f_x)

先ほどと同様にスクリプトを実行します。

> python numpy_matmul.py
> /home/staff/hhachiya/Works/numpy_matmul.py(19)<module>()
-> f_x = f_x + b
(Pdb) 

pdb.set_trace()をで処理が「l」を入力し、Enterを押すと、現在実行中のコードを表示できます。

(Pdb) l
 14     b = np.array([ [1], [2] ,[3] ])
 15
 16     # 行列Wとベクトルxの掛け算とbとの足し算
 17     f_x = np.matmul(W.T,x)
 18     pdb.set_trace()
 19  -> f_x = f_x + b
 20
 21     # 標準出力
 22     print(f_x)
[EOF]
(Pdb) 

次に、変数名「f_x」を入力し、Enterを押すことにより、処理途中の変数f_xの値を表示できます。

(Pdb) f_x
array([[ 1.],
       [ 1.],
       [ 1.]])
(Pdb)

現在の行を実行するために「n」を入力し、Enterを押します。そして、「f_x」を入力し、Enterを押すと更新された変数f_xの値を表示できます。

(Pdb) n
> /home/staff/hhachiya/Works/numpy_matmul.py(22)<module>()
-> print(f_x)
(Pdb) f_x
array([[ 2.],
       [ 3.],
       [ 4.]])
(Pdb)

最後に「c」を入力し、Enterを押すと終了(実際には次のpdb.set_trace()まで実行)します。
このように、任意の行で処理を止めて、処理途中の変数の値を確認したり、新たな処理を試したりすることが出来るので、効率よく実装ができます。

演習2: 指数関数numpy.expと、和を求める関数npumpy.sumを使って、ソフトマックス g(x_i) = \frac{\exp(\exp(\textbf{W}^\top \textbf{x}_i+\textbf{b}))}{\sum{j=0}\exp(\textbf{W}^\top \textbf{x}_j+\textbf{b}))}を実装してみましょう。numpy.expとnumpy.sumの詳細については以下参照してください。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.exp.html
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.sum.html

hirotaka-hachiya.hatenablog.com