覚え書きブログ

Pythonによる機械学習3(ニューラルネット 2/3)

<< Pythonによるデータ解析3(ニューラルネット 1/3)

Pythonによる機械学習3(ニューラルネット 2/3)の目次】

難しいデータに対するロジスティック回帰

前回作成したロジスティック回帰を、多峰性のある難しいデータに対してかけてみましょう。logisticRegression_template.pyのメインの人工データ生成の行を以下のように変更します。
【変更前】

# 人工データの生成(簡単な場合)
myData = Data.artificial(300,150,mean1=[1,2],mean2=[-2,-1],mean3=[2,-2],cov=[[1,-0.8],[-0.8,1]])

【変更後】

# 人工データの生成(難しい場合)
myData = Data.artificial(300,150,mean1=[1,2],mean2=[-2,-1],mean3=[4,-2],mean3multi=[-2,4],cov=[[1,0],[0,1]])

そして、以下のようにlogisticRegression_template.pyを実行します。

> python logisticRegression_template.py
Training ite:1 loss:1.0947344475953216
Training ite:2 loss:1.7507642964335643
Training ite:3 loss:1.6984184356189571
Training ite:4 loss:2.1723024152378305
Training ite:5 loss:2.887151921428792
...
Training ite:998 loss:0.4791384797073837
Training ite:999 loss:0.47913847818312594
Training ite:1000 loss:0.4791384766741184
Test loss: 0.495379606706

学習したロジスティックモデルによる各カテゴリの事後確率は以下のようになっており、カテゴリ1と3を分類することができていないことがわかります。
f:id:hirotaka_hachiya:20171125092223p:plain
f:id:hirotaka_hachiya:20171125092238p:plain
f:id:hirotaka_hachiya:20171125092253p:plain

また、交差エントロピー損失も十分に下がっていない(0.47くらいで止まっている)ことがわかります。
f:id:hirotaka_hachiya:20171125092151p:plain

これは、ロジスティックモデルでは、各カテゴリに1つの直線 \textbf{w}_{cl}^\top + b_c \textbf{x}が3次元の場合は平面、4次元以上の場合は超平面)が割り当てられていますが、カテゴリ1と3の間はどのように直線を引いても、原理的を分類をすることができないためです。文章、画像およびセンサーなどの実際のデータは、このように線形では分類できない複雑な構造を持っている場合が多いと考えられます。

ニューラルネットワークのテンプレート

複雑な構造を持つデータに対応するために、ロジスティック回帰を3階層のニューラルネットワークに拡張していきます。ロジスティック回帰と同様に、 intelligentSystemTrainingフォルダにあるニューラルネットワークのテンプレートneuralNetwork_template.pyを用います。

neuralNetworkクラスには、以下のようなメソッドが定義されています。
1)__init__: 学習データおよびモデルパラメータ \textbf{W}^1 \textbf{W}^2初期化
3)update:最急降下法によるモデルパラメータの更新※未実装
5)predict: 事後確率の計算。
6)sigmoid: シグモイド関数※未実装
7)hidden: 中間層の計算

class neuralNetwork:
	#------------------------------------
	# 1) 学習データおよびモデルパラメータの初期化
	# x: 学習入力データ(入力ベクトルの次元数×データ数のnumpy.array)
	# t: one-hot学習カテゴリデータ(カテゴリ数×データ数のnumpy.array)
	# hDim: 中間層のノード数hDim(スカラー)
	# batchSize: 学習データのバッチサイズ(スカラー、0の場合は学習データサイズにセット)
	def __init__(self, x, t, hDim=20, batchSize=0):
		# デフォルトの初期化
		self.init(x,t)

		# モデルパラメータをランダムに初期化
		xDim = x.shape[0]	# 入力データの次元
		hDim = hDim			# 隠れ層のノード数
		tDim = t.shape[0]	# カテゴリ数
		
		self.W1 = np.random.normal(0.0, pow(hDim, -0.5), (xDim + 1, hDim))
		self.W2 = np.random.normal(0.0, pow(tDim, -0.5), (hDim + 1, tDim))

	#------------------------------------

	#------------------------------------
	# 3) 最急降下法によるパラメータの更新
	# alpha: 学習率(スカラー)
	# printLoss: 評価値の表示指示(真偽値)
	def update(self, alpha=0.1,printEval=True):

		# 次のバッチ
		x, t = self.nextBatch(self.batchSize)
		
		# データ数
		dNum = x.shape[1]
		
		# 中間層の計算
		h = self.hidden(x)
		
		# 事後確率の予測と真値の差分
		predict = self.predict(x,h)
		predict_error =  predict - t
		
		# self.W1とW2の更新
		#【self.W1の更新】
		#【self.W2の更新】

		# 交差エントロピーとAccuracyを標準出力
		if printEval:
			# 交差エントロピーの記録
			self.losses = np.append(self.losses, self.loss(self.x[:,self.validInd],self.t[:,self.validInd]))

			# 正解率エントロピーの記録
			self.accuracies = np.append(self.accuracies, self.accuracy(self.x[:,self.validInd],self.t[:,self.validInd]))
		
			print("loss:{0:02.3f}, accuracy:{1:02.3f}".format(self.losses[-1],self.accuracies[-1]))
	#------------------------------------
	
	#------------------------------------
	# 5) 事後確率の計算
	# x: 入力データ(入力ベクトルの次元数×データ数のnumpy.array)
	# h: 中間層のデータh(中間層のノード数×データ数のnumpy.array)
	def predict(self, x, h = []):
		if not len(h):
			h = self.hidden(x)
		return self.softmax(np.matmul(self.W2[:-1].T, h) + self.W2[-1][np.newaxis].T)
	#------------------------------------
	
	#------------------------------------
	# 6) シグモイドの計算
	# x: 入力データ(入力ベクトルの次元数×データ数のnumpy.array)
	def sigmoid(self,x):
		sigmoid = x		#【シグモイド関数の計算】
		return sigmoid
	#------------------------------------

	#------------------------------------
	# 7) 中間層
	# x: 入力データ(入力ベクトルの次元数×データ数のnumpy.array)
	def hidden(self, x):
		h = self.sigmoid(np.matmul(self.W1[:-1].T, x) + self.W1[-1][np.newaxis].T)
		return h
	#------------------------------------

ここで、ニューラルネットワークのモデルパラメータは、以下のような行列構造で表現ていることを確認しましょう。
f:id:hirotaka_hachiya:20181129134550p:plain

メインおよび実行方法は、LogisticRegression_template.pyと基本的には同じです。

演習2

以下の【シグモイド関数の計算】を実装し、sigmoidメソッドを完成させましょう。

#------------------------------------
# 6) シグモイドの計算
# x: 入力データ(入力ベクトルの次元数×データ数のnumpy.array)
def sigmoid(self,x):
	return 【シグモイド関数の計算】
#------------------------------------

Pythonによる機械学習3(ニューラルネット 3/3)>>