覚え書きブログ

Pythonによる機械学習10(2/4)

<< Pythonによる機械学習10(1/4)

Pythonによる機械学習10(2/4)の目次】

参考書

本ブログの内容の詳細は、「機械学習スタートアップシリーズ ゼロからつくるPython機械学習プログラミング入門」に掲載されています。
機械学習に必要な数学の復習から、機械学習アルゴリズムの導出およびPythonの基本ライブラリのみを用いた実装方法まで学びたい方は、本書籍をご活用ください。
bookclub.kodansha.co.jp

線形回帰のテンプレート

intelligentSystemTrainingフォルダ下の線形回帰のテンプレートregression_template.pyに定義されているlinearRegressionクラスに、演習1で作成したtrain関数を組み込み、学習から評価および結果の可視化までのパスを通していきます。

以下は、linearRegressionクラスには、以下のようなメソッドが定義されています。
1)__init__: 学習データの初期化
2)train:最小二乗法を用いたモデルパラメタself.wの最適化※未実装(演習1)
2)trainMat:最小二乗法を用いたモデルパラメタself.wの最適化(行列演算を用いた高速化)※未実装(演習3)
3)predict: 学習したモデルを用いてyを予測 ※未実装(演習2)
4)loss: 二乗損失の計算※未実装(演習2)

#-------------------
# クラスの定義始まり
#-------------------
# クラスの定義始まり
class linearRegression():
	#------------------------------------
	# 1) 学習データおよびモデルパラメータの初期化
	# x: 学習入力データ(入力ベクトルの次元数×データ数のnumpy.array)
	# y: 学習出力データ(データ数のnumpy.array)
	# kernelType: カーネルの種類(文字列:gaussian)
	# kernelParam: カーネルのハイパーパラメータ(スカラー)
	def __init__(self, x, y, kernelType="linear", kernelParam=1.0):
		# 学習データの設定
		self.x = x
		self.y = y
		self.xDim = x.shape[0]
		self.dNum = x.shape[1]
		
		# カーネルの設定
		self.kernelType = kernelType
		self.kernelParam = kernelParam
	#------------------------------------

	#------------------------------------
	# 2) 最小二乗法を用いてモデルパラメータを最適化
	# (分子・分母の計算にFor文を用いた場合)
	def train(self):
		self.w = np.zeros([self.xDim,1])
	#------------------------------------

	#------------------------------------
	# 2) 最小二乗法を用いてモデルパラメータを最適化
	# (分子・分母の計算に行列演算を用いた場合)
	def trainMat(self):
		self.w = np.zeros([self.xDim,1])
	#------------------------------------
	
	#------------------------------------
	# 3) 予測
	# x: 入力データ(入力次元 x データ数)
	def predict(self,x):		
		y = []
		return y
	#------------------------------------

	#------------------------------------
	# 4) 二乗損失の計算
	# x: 入力データ(入力次元 x データ数)
	# y: 出力データ(データ数)
	def loss(self,x,y):
		loss = 0.0
		return loss
	#------------------------------------
# クラスの定義終わり
#-------------------

以下は、学習から評価および可視化までを実行するメインです。
メインでは、以下のようにフローなっています。
1)regressionData.artificialクラスをインスタンス(myData)化し、学習用・評価用データの生成
2)linearRegressionクラスをインスタンス(classifier)化し、モデルの初期化
3)linearRegression.trainを用いて最小二乗法を用いてパラメータの最適化および処理時間の測定
4)linearRegression.trainMatを用いて最小二乗法の行列演算版を用いてパラメータの最適化および処理時間の測定
5)linearRegression.lossを用いて評価データに対する二乗損失を計算
6)linearRegression.predictを用いて評価データに対する予測値を計算し、regressionData.artificial.plotを用いてプロット

#-------------------
# メインの始まり
if __name__ == "__main__":
	
	# 1) 学習入力次元が2の場合のデーター生成
	myData = rg.artificial(200,100, dataType="1D")
	
	# 2) 線形回帰モデル
	regression = linearRegression(myData.xTrain,myData.yTrain)
	
	# 3) 学習(For文版)
	sTime = time.time()
	regression.train()
	eTime = time.time()
	print("train with for-loop: time={0:.4} sec".format(eTime-sTime))
	
	# 4) 学習(行列版)
	sTime = time.time()
	regression.trainMat()
	eTime = time.time()
	print("train with matrix: time={0:.4} sec".format(eTime-sTime))

	# 5) 学習したモデルを用いて予測
	print("loss={0:.3}".format(regression.loss(myData.xTest,myData.yTest)))

	# 6) 学習・評価データおよび予測結果をプロット
	predict = regression.predict(myData.xTest)
	myData.plot(predict)
	
#メインの終わり
#-------------------

演習2

以下のlinearRegressionクラスのtrain, lossおよびpredictメソッドを実装し完成させましょう。
#------------------------------------
# 2) 最小二乗法を用いてモデルパラメータを最適化
# (分母の計算にFor文を用いた場合)
def train(self):
【演習1の内容をlinearRegressionクラスに合うように変形したコード】
#------------------------------------
#------------------------------------
# 3) 予測
# x: 入力データ(入力次元 x データ数)
def predict(self,x):
【入力xから学習したモデルを用いてyを予測するコード】
return y
#------------------------------------

#------------------------------------
# 4) 二乗損失の計算
# x: 入力データ(入力次元 x データ数)
# y: 出力データ(データ数)
def loss(self,x,y):
【入力xに対する予測と、yの平均二乗誤差を計算しlossに設定するコード】
return loss
#------------------------------------

行列演算による高速化

Pythonのfor文は、C言語などのコンパイル言語と異なり、インタプリタが解釈し実行するため処理に時間がかかります。そのため、出来るだけfor文は使わず実装が最適化されているnumpyの行列演算を用いて方が処理の効率上良いとされています。
線形回帰の最適化におけるモデルパラメータの式に、分子および分母の計算に和があり、特に工夫をしなければfor文を使ってしまうと思います。これを行列演算に置き換えることを考えましょう。
f:id:hirotaka_hachiya:20171212142041p:plain

演習3

モデルパラメータ \textbf{w}の最適化の式の分母の計算を、行列演算に置き換えられることを式の上で確認し、linearRegression.trainMatメソッドを実装し、クラスを完成させましょう。

線形回帰の実行例

linearRegressionクラスのパスが一通り通り実行すると、以下のような出力が得られます。
【入力次元が1次元の場合】

> train with for-loop: time=0.006868 sec
train with matrix: time=0.002006 sec
loss=0.011

f:id:hirotaka_hachiya:20171212142750p:plain

【入力次元が2次元の場合】

> python .\regression.py
train with for-loop: time=0.007021 sec
train with matrix: time=0.002 sec
loss=0.0132

f:id:hirotaka_hachiya:20171212142642p:plain

Pythonによる機械学習10(3/4) >>