



import numpy as np
from matplotlib import pyplot as plt



def  _lowerCAmelCase     (_lowerCAmelCase):
					return 1 / (1 + np.exp(-1 * x))


class    _lowercase :
				'''simple docstring'''







				def __init__(			self  ,			snake_case__  ,			snake_case__=None  ,			snake_case__=None  ,			snake_case__=False     ):

									'''simple docstring'''


									UpperCamelCase_			= units
									UpperCamelCase_			= None
									UpperCamelCase_			= None
									UpperCamelCase_			= activation
									if learning_rate is None:
														UpperCamelCase_			= 0.3
									UpperCamelCase_			= learning_rate
									UpperCamelCase_			= is_input_layer

				def    _lowerCamelCase       (			self  ,			snake_case__     ):

									'''simple docstring'''


									UpperCamelCase_			= np.asmatrix(np.random.normal(0  ,			0.5  ,			(self.units, back_units)     )     )
									UpperCamelCase_			= np.asmatrix(np.random.normal(0  ,			0.5  ,			self.units     )     ).T
									if self.activation is None:
														UpperCamelCase_			= sigmoid

				def    _lowerCamelCase       (			self     ):

									'''simple docstring'''


									if self.activation == sigmoid:
														UpperCamelCase_			= np.dot(self.output  ,			(1 - self.output).T     )
														UpperCamelCase_			= np.diag(np.diag(__UpperCAmelCase     )     )
									else:
														UpperCamelCase_			= 1
									return gradient_activation

				def    _lowerCamelCase       (			self  ,			snake_case__     ):

									'''simple docstring'''


									UpperCamelCase_			= xdata
									if self.is_input_layer:
														# input layer
														UpperCamelCase_			= xdata
														UpperCamelCase_			= xdata
														return xdata
									else:
														UpperCamelCase_			= np.dot(self.weight  ,			self.xdata     ) - self.bias
														UpperCamelCase_			= self.activation(self.wx_plus_b     )
														return self.output

				def    _lowerCamelCase       (			self  ,			snake_case__     ):

									'''simple docstring'''


									UpperCamelCase_			= self.cal_gradient()  # i * i 维
									UpperCamelCase_			= np.asmatrix(np.dot(gradient.T  ,			__UpperCAmelCase     )     )

									UpperCamelCase_			= np.asmatrix(self.xdata     )
									UpperCamelCase_			= -1
									UpperCamelCase_			= self.weight

									UpperCamelCase_			= np.dot(gradient.T  ,			self._gradient_weight.T     )
									UpperCamelCase_			= gradient * self._gradient_bias
									UpperCamelCase_			= np.dot(__UpperCAmelCase  ,			self._gradient_x     ).T
									# upgrade: the Negative gradient direction
									UpperCamelCase_			= self.weight - self.learn_rate * self.gradient_weight
									UpperCamelCase_			= self.bias - self.learn_rate * self.gradient_bias.T
									# updates the weights and bias according to learning rate (0.3 if undefined)
									return self.gradient




class    _lowercase :
				'''simple docstring'''







				def __init__(			self     ):

									'''simple docstring'''


									UpperCamelCase_			= []
									UpperCamelCase_			= []
									UpperCamelCase_			= plt.figure()
									UpperCamelCase_			= self.fig_loss.add_subplot(1  ,			1  ,			1     )

				def    _lowerCamelCase       (			self  ,			snake_case__     ):

									'''simple docstring'''


									self.layers.append(__UpperCAmelCase     )

				def    _lowerCamelCase       (			self     ):

									'''simple docstring'''


									for i, layer in enumerate(self.layers[:]     ):
														if i < 1:
																			UpperCamelCase_			= True
														else:
																			layer.initializer(self.layers[i - 1].units     )

				def    _lowerCamelCase       (			self     ):

									'''simple docstring'''


									for i, layer in enumerate(self.layers[:]     ):
														print(F"""------- layer {i} -------"""     )
														print("weight.shape "  ,			np.shape(layer.weight     )     )
														print("bias.shape "  ,			np.shape(layer.bias     )     )

				def    _lowerCamelCase       (			self  ,			snake_case__  ,			snake_case__  ,			snake_case__  ,			snake_case__     ):

									'''simple docstring'''


									UpperCamelCase_			= train_round
									UpperCamelCase_			= accuracy

									self.ax_loss.hlines(self.accuracy  ,			0  ,			self.train_round * 1.1     )

									UpperCamelCase_			= np.shape(__UpperCAmelCase     )
									for _ in range(__UpperCAmelCase     ):
														UpperCamelCase_			= 0
														for row in range(x_shape[0]     ):
																			UpperCamelCase_			= np.asmatrix(xdata[row, :]     ).T
																			UpperCamelCase_			= np.asmatrix(ydata[row, :]     ).T

																			# forward propagation
																			for layer in self.layers:
																								UpperCamelCase_			= layer.forward_propagation(_xdata     )

																			UpperCamelCase_	,     UpperCamelCase_			= self.cal_loss(_ydata  ,			_xdata     )
																			UpperCamelCase_			= all_loss + loss

																			# back propagation: the input_layer does not upgrade
																			for layer in self.layers[:0:-1]:
																								UpperCamelCase_			= layer.back_propagation(__UpperCAmelCase     )

														UpperCamelCase_			= all_loss / x_shape[0]
														self.train_mse.append(__UpperCAmelCase     )

														self.plot_loss()

														if mse < self.accuracy:
																			print("----达到精度----"     )
																			return mse
									return None

				def    _lowerCamelCase       (			self  ,			snake_case__  ,			snake_case__     ):

									'''simple docstring'''


									UpperCamelCase_			= np.sum(np.power((ydata - ydata_)  ,			2     )     )
									UpperCamelCase_			= 2 * (ydata_ - ydata)
									# vector (shape is the same as _ydata.shape)
									return self.loss, self.loss_gradient

				def    _lowerCamelCase       (			self     ):

									'''simple docstring'''


									if self.ax_loss.lines:
														self.ax_loss.lines.remove(self.ax_loss.lines[0]     )
									self.ax_loss.plot(self.train_mse  ,			"r-"     )
									plt.ion()
									plt.xlabel("step"     )
									plt.ylabel("loss"     )
									plt.show()
									plt.pause(0.1     )




def  _lowerCAmelCase     ():
					UpperCamelCase_			= np.random.randn(10 ,						10)
					UpperCamelCase_			= np.asarray(
					    [
					        [0.8, 0.4],
					        [0.4, 0.3],
					        [0.34, 0.45],
					        [0.67, 0.32],
					        [0.88, 0.67],
					        [0.78, 0.77],
					        [0.55, 0.66],
					        [0.55, 0.43],
					        [0.54, 0.1],
					        [0.1, 0.5],
					    ])
					UpperCamelCase_			= BPNN()
					for i in (10, 20, 30, 2):
										model.add_layer(DenseLayer(__snake_case))
					model.build()
					model.summary()
					model.train(xdata=__snake_case ,						ydata=__snake_case ,						train_round=1_00 ,						accuracy=0.01)


if __name__ == "__main__":
	example()






import numpy as np




def  a_		(							__snake_case     ,		__snake_case					)	->			List[str]:

			'''simple docstring'''


			UpperCamelCase_     				= np.array(__snake_case					)
			UpperCamelCase_     				= np.array(__snake_case					)

			UpperCamelCase_     				= abs(predict - actual					)
			UpperCamelCase_     				= difference.mean()

			return score




def  a_		(							__snake_case     ,		__snake_case					)	->			Optional[Any]:

			'''simple docstring'''


			UpperCamelCase_     				= np.array(__snake_case					)
			UpperCamelCase_     				= np.array(__snake_case					)

			UpperCamelCase_     				= predict - actual
			UpperCamelCase_     				= np.square(__snake_case					)

			UpperCamelCase_     				= square_diff.mean()
			return score




def  a_		(							__snake_case     ,		__snake_case					)	->			Optional[Any]:

			'''simple docstring'''


			UpperCamelCase_     				= np.array(__snake_case					)
			UpperCamelCase_     				= np.array(__snake_case					)

			UpperCamelCase_     				= predict - actual
			UpperCamelCase_     				= np.square(__snake_case					)
			UpperCamelCase_     				= square_diff.mean()
			UpperCamelCase_     				= np.sqrt(__snake_case					)
			return score




def  a_		(							__snake_case     ,		__snake_case					)	->			Optional[int]:

			'''simple docstring'''


			UpperCamelCase_     				= np.array(__snake_case					)
			UpperCamelCase_     				= np.array(__snake_case					)

			UpperCamelCase_     				= np.log(predict + 1					)
			UpperCamelCase_     				= np.log(actual + 1					)

			UpperCamelCase_     				= log_predict - log_actual
			UpperCamelCase_     				= np.square(__snake_case					)
			UpperCamelCase_     				= square_diff.mean()

			UpperCamelCase_     				= np.sqrt(__snake_case					)

			return score




def  a_		(							__snake_case     ,		__snake_case					)	->			int:

			'''simple docstring'''


			UpperCamelCase_     				= np.array(__snake_case					)
			UpperCamelCase_     				= np.array(__snake_case					)

			UpperCamelCase_     				= predict - actual
			UpperCamelCase_     				= np.sum(__snake_case					) / len(__snake_case					)
			UpperCamelCase_     				= np.sum(__snake_case					) / len(__snake_case					)
			# print(numerator, denumerator)
			UpperCamelCase_     				= float(__snake_case					) / denumerator * 1_0_0

			return score





def  a_		(							__snake_case     ,		__snake_case					)	->			Optional[Any]:

			'''simple docstring'''


			return np.mean(np.array(__snake_case					) == np.array(__snake_case					)					)
