
"""simple docstring"""






import pickle

import numpy as np
from matplotlib import pyplot as plt

class 					__a     :



							'''simple docstring'''







							def __init__(     self  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase=0.2  ,    _lowerCamelCase=0.2       )			->							List[Any]:




										'''simple docstring'''
										__lowercase       =       bp_numa
										__lowercase       =       bp_numa
										__lowercase       =       bp_numa
										__lowercase       =       conva_get[:2]
										__lowercase       =       conva_get[2]
										__lowercase       =       size_pa
										__lowercase       =       rate_w
										__lowercase       =       rate_t
										__lowercase       =       [
										    np.mat(-1 * np.random.rand(self.conva[0]  ,    self.conva[0]       ) + 0.5       )
										    for i in range(self.conva[1]       )
										]
										__lowercase       =       np.mat(-1 * np.random.rand(self.num_bpa  ,    self.num_bpa       ) + 0.5       )
										__lowercase       =       np.mat(-1 * np.random.rand(self.num_bpa  ,    self.num_bpa       ) + 0.5       )
										__lowercase       =       -2 * np.random.rand(self.conva[1]       ) + 1
										__lowercase       =       -2 * np.random.rand(self.num_bpa       ) + 1
										__lowercase       =       -2 * np.random.rand(self.num_bpa       ) + 1
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Union[str, Any]:




										'''simple docstring'''
										# save model dict with pickle
										__lowercase       =       {
										    "num_bp1": self.num_bpa,
										    "num_bp2": self.num_bpa,
										    "num_bp3": self.num_bpa,
										    "conv1": self.conva,
										    "step_conv1": self.step_conva,
										    "size_pooling1": self.size_poolinga,
										    "rate_weight": self.rate_weight,
										    "rate_thre": self.rate_thre,
										    "w_conv1": self.w_conva,
										    "wkj": self.wkj,
										    "vji": self.vji,
										    "thre_conv1": self.thre_conva,
										    "thre_bp2": self.thre_bpa,
										    "thre_bp3": self.thre_bpa,
										}
										with open(_lowerCamelCase  ,    "wb"       ) as f:
													pickle.dump(_lowerCamelCase  ,    _lowerCamelCase       )

										print(f'''Model saved： {save_path}'''       )
							@classmethod
							def   SCREAMING_SNAKE_CASE						(     cls  ,    _lowerCamelCase       )			->							Any:




										'''simple docstring'''
										# read saved model
										with open(_lowerCamelCase  ,    "rb"       ) as f:
													__lowercase       =       pickle.load(_lowerCamelCase       )  # noqa: S301

										__lowercase       =       model_dic.get("conv1"       )
										conv_get.append(model_dic.get("step_conv1"       )       )
										__lowercase       =       model_dic.get("size_pooling1"       )
										__lowercase       =       model_dic.get("num_bp1"       )
										__lowercase       =       model_dic.get("num_bp2"       )
										__lowercase       =       model_dic.get("num_bp3"       )
										__lowercase       =       model_dic.get("rate_weight"       )
										__lowercase       =       model_dic.get("rate_thre"       )
										# create model instance
										__lowercase       =       CNN(_lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase       )
										# modify model parameter
										__lowercase       =       model_dic.get("w_conv1"       )
										__lowercase       =       model_dic.get("wkj"       )
										__lowercase       =       model_dic.get("vji"       )
										__lowercase       =       model_dic.get("thre_conv1"       )
										__lowercase       =       model_dic.get("thre_bp2"       )
										__lowercase       =       model_dic.get("thre_bp3"       )
										return conv_ins
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Dict:




										'''simple docstring'''
										return 1 / (1 + np.exp(-1 * x       ))
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Dict:




										'''simple docstring'''
										return round(_lowerCamelCase  ,    3       )
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase       )			->							Tuple:




										'''simple docstring'''
										# convolution process
										__lowercase       =       convs[0]
										__lowercase       =       convs[1]
										__lowercase       =       np.shape(_lowerCamelCase       )[0]
										# get the data slice of original image data, data_focus
										__lowercase       =       []
										for i_focus in range(0  ,    size_data - size_conv + 1  ,    _lowerCamelCase       ):
													for j_focus in range(0  ,    size_data - size_conv + 1  ,    _lowerCamelCase       ):
																__lowercase       =       data[
																    i_focus : i_focus + size_conv, j_focus : j_focus + size_conv
																]
																data_focus.append(_lowerCamelCase       )
        # calculate the feature map of every single kernel, and saved as list of matrix
										__lowercase       =       []
										__lowercase       =       int((size_data - size_conv) / conv_step + 1       )
										for i_map in range(_lowerCamelCase       ):
													__lowercase       =       []
													for i_focus in range(len(_lowerCamelCase       )       ):
																__lowercase       =       (
																    np.sum(np.multiply(data_focus[i_focus]  ,    w_convs[i_map]       )       )
																    - thre_convs[i_map]
																)
																featuremap.append(self.sig(_lowerCamelCase       )       )
													__lowercase       =       np.asmatrix(_lowerCamelCase       ).reshape(
													    _lowerCamelCase  ,    _lowerCamelCase       )
													data_featuremap.append(_lowerCamelCase       )

										# expanding the data slice to One dimenssion
										__lowercase       =       []
										for each_focus in data_focus:
													focusa_list.extend(self.Expand_Mat(_lowerCamelCase       )       )
										__lowercase       =       np.asarray(_lowerCamelCase       )
										return focus_list, data_featuremap
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase="average_pool"       )			->							Union[str, Any]:




										'''simple docstring'''
										# pooling process
										__lowercase       =       len(featuremaps[0]       )
										__lowercase       =       int(size_map / size_pooling       )
										__lowercase       =       []
										for i_map in range(len(_lowerCamelCase       )       ):
													__lowercase       =       featuremaps[i_map]
													__lowercase       =       []
													for i_focus in range(0  ,    _lowerCamelCase  ,    _lowerCamelCase       ):
																for j_focus in range(0  ,    _lowerCamelCase  ,    _lowerCamelCase       ):
																			__lowercase       =       feature_map[
																			    i_focus : i_focus + size_pooling,
																			    j_focus : j_focus + size_pooling,
																			]
																			if pooling_type == "average_pool":
																						# average pooling
																						map_pooled.append(np.average(_lowerCamelCase       )       )
																			elif pooling_type == "max_pooling":
																						# max pooling
																						map_pooled.append(np.max(_lowerCamelCase       )       )
													__lowercase       =       np.asmatrix(_lowerCamelCase       ).reshape(_lowerCamelCase  ,    _lowerCamelCase       )
													featuremap_pooled.append(_lowerCamelCase       )
										return featuremap_pooled
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							str:




										'''simple docstring'''
										# expanding three dimension data to one dimension list
										__lowercase       =       []
										for i in range(len(_lowerCamelCase       )       ):
													__lowercase       =       np.shape(data[i]       )
													__lowercase       =       data[i].reshape(1  ,    shapes[0] * shapes[1]       )
													__lowercase       =       data_listed.getA().tolist()[0]
													data_expanded.extend(_lowerCamelCase       )
										__lowercase       =       np.asarray(_lowerCamelCase       )
										return data_expanded
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Optional[Any]:




										'''simple docstring'''
										# expanding matrix to one dimension list
										__lowercase       =       np.asarray(_lowerCamelCase       )
										__lowercase       =       np.shape(_lowerCamelCase       )
										__lowercase       =       data_mat.reshape(1  ,    shapes[0] * shapes[1]       )
										return data_expanded
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase       )			->							str:




										'''simple docstring'''
										__lowercase       =       []
										__lowercase       =       0
										for i_map in range(_lowerCamelCase       ):
													__lowercase       =       np.ones((size_map, size_map)       )
													for i in range(0  ,    _lowerCamelCase  ,    _lowerCamelCase       ):
																for j in range(0  ,    _lowerCamelCase  ,    _lowerCamelCase       ):
																			__lowercase       =       pd_pool[
																			    i_pool
																			]
																			__lowercase       =       i_pool + 1
													__lowercase       =       np.multiply(
													    _lowerCamelCase  ,    np.multiply(out_map[i_map]  ,    (1 - out_map[i_map])       )       )
													pd_all.append(_lowerCamelCase       )
										return pd_all
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase  ,    _lowerCamelCase=bool       )			->							Union[str, Any]:




										'''simple docstring'''
										# model traning
										print("----------------------Start Training-------------------------"       )
										print((" - - Shape: Train_Data  ", np.shape(_lowerCamelCase       ))       )
										print((" - - Shape: Teach_Data  ", np.shape(_lowerCamelCase       ))       )
										__lowercase       =       0
										__lowercase       =       []
										__lowercase       =       10_000
										while rp < n_repeat and mse >= error_accuracy:
													__lowercase       =       0
													print(f'''-------------Learning Time {rp}--------------'''       )
													for p in range(len(_lowerCamelCase       )       ):
																# print('------------Learning Image: %d--------------'%p)
																__lowercase       =       np.asmatrix(datas_train[p]       )
																__lowercase       =       np.asarray(datas_teach[p]       )
																__lowercase   ,					__lowercase       =       self.convolute(
																    _lowerCamelCase  ,    self.conva  ,    self.w_conva  ,    self.thre_conva  ,    conv_step=self.step_conva  ,    )
																__lowercase       =       self.pooling(_lowerCamelCase  ,    self.size_poolinga       )
																__lowercase       =       np.shape(_lowerCamelCase       )
																__lowercase       =       self._expand(_lowerCamelCase       )
																__lowercase       =       data_bp_input

																__lowercase       =       np.dot(_lowerCamelCase  ,    self.vji.T       ) - self.thre_bpa
																__lowercase       =       self.sig(_lowerCamelCase       )
																__lowercase       =       np.dot(_lowerCamelCase  ,    self.wkj.T       ) - self.thre_bpa
																__lowercase       =       self.sig(_lowerCamelCase       )

																# --------------Model Leaning ------------------------
																# calculate error and gradient---------------
																__lowercase       =       np.multiply(
																    (data_teach - bp_outa)  ,    np.multiply(_lowerCamelCase  ,    (1 - bp_outa)       )       )
																__lowercase       =       np.multiply(
																    np.dot(_lowerCamelCase  ,    self.wkj       )  ,    np.multiply(_lowerCamelCase  ,    (1 - bp_outa)       )       )
																__lowercase       =       np.dot(_lowerCamelCase  ,    self.vji       )

																__lowercase       =       pd_i_all / (self.size_poolinga * self.size_poolinga)
																__lowercase       =       pd_conva_pooled.T.getA().tolist()
																__lowercase       =       self._calculate_gradient_from_pool(
																    _lowerCamelCase  ,    _lowerCamelCase  ,    shape_featuremapa[0]  ,    shape_featuremapa[1]  ,    self.size_poolinga  ,    )
																# weight and threshold learning process---------
																# convolution layer
																for k_conv in range(self.conva[1]       ):
																			__lowercase       =       self._expand_mat(pd_conva_all[k_conv]       )
																			__lowercase       =       self.rate_weight * np.dot(_lowerCamelCase  ,    _lowerCamelCase       )

																			__lowercase       =       self.w_conva[k_conv] + delta_w.reshape(
																			    (self.conva[0], self.conva[0])       )

																			__lowercase       =       (
																			    self.thre_conva[k_conv]
																			    - np.sum(pd_conva_all[k_conv]       ) * self.rate_thre
																			)
																# all connected layer
																__lowercase       =       self.wkj + pd_k_all.T * bp_outa * self.rate_weight
																__lowercase       =       self.vji + pd_j_all.T * bp_outa * self.rate_weight
																__lowercase       =       self.thre_bpa - pd_k_all * self.rate_thre
																__lowercase       =       self.thre_bpa - pd_j_all * self.rate_thre
																# calculate the sum error of all single image
																__lowercase       =       np.sum(abs(data_teach - bp_outa       )       )
																error_count += errors
																# print('   ----Teach      ',data_teach)
																# print('   ----BP_output  ',bp_out3)
													__lowercase       =       rp + 1
													__lowercase       =       error_count / patterns
													all_mse.append(_lowerCamelCase       )

										def draw_error():
													__lowercase       =       [error_accuracy for i in range(int(n_repeat * 1.2       )       )]
													plt.plot(_lowerCamelCase  ,    "+-"       )
													plt.plot(_lowerCamelCase  ,    "r--"       )
													plt.xlabel("Learning Times"       )
													plt.ylabel("All_mse"       )
													plt.grid(_lowerCamelCase  ,    alpha=0.5       )
													plt.show()

										print("------------------Training Complished---------------------"       )
										print((" - - Training epoch: ", rp, f'''     - - Mse: {mse:.6f}''')       )
										if draw_e:
													draw_error()
										return mse
							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Tuple:




										'''simple docstring'''
										# model predict
										__lowercase       =       []
										print("-------------------Start Testing-------------------------"       )
										print((" - - Shape: Test_Data  ", np.shape(_lowerCamelCase       ))       )
										for p in range(len(_lowerCamelCase       )       ):
													__lowercase       =       np.asmatrix(datas_test[p]       )
													__lowercase   ,					__lowercase       =       self.convolute(
													    _lowerCamelCase  ,    self.conva  ,    self.w_conva  ,    self.thre_conva  ,    conv_step=self.step_conva  ,    )
													__lowercase       =       self.pooling(_lowerCamelCase  ,    self.size_poolinga       )
													__lowercase       =       self._expand(_lowerCamelCase       )

													__lowercase       =       data_bp_input
													__lowercase       =       bp_outa * self.vji.T - self.thre_bpa
													__lowercase       =       self.sig(_lowerCamelCase       )
													__lowercase       =       bp_outa * self.wkj.T - self.thre_bpa
													__lowercase       =       self.sig(_lowerCamelCase       )
													produce_out.extend(bp_outa.getA().tolist()       )
										__lowercase       =       [list(map(self.do_round  ,    _lowerCamelCase       )       ) for each in produce_out]
										return np.asarray(_lowerCamelCase       )





							def   SCREAMING_SNAKE_CASE						(     self  ,    _lowerCamelCase       )			->							Dict:




										'''simple docstring'''
										# return the data of image after convoluting process so we can check it out
										__lowercase       =       np.asmatrix(_lowerCamelCase       )
										__lowercase   ,					__lowercase       =       self.convolute(
										    _lowerCamelCase  ,    self.conva  ,    self.w_conva  ,    self.thre_conva  ,    conv_step=self.step_conva  ,    )
										__lowercase       =       self.pooling(_lowerCamelCase  ,    self.size_poolinga       )

										return data_conveda, data_pooleda


if __name__ == "__main__":
					pass







"""simple docstring"""






def      lowerCAmelCase__			(		__magic_name__ = 1_0      )						->str:
			if not isinstance(__magic_name__			,   __magic_name__      ) or n < 0:
						raise ValueError("Invalid input"      )
			__lowercase       =       1_0**n
			__lowercase       =       2_8_4_3_3 * (pow(2			,   7_8_3_0_4_5_7			,   __magic_name__      )) + 1
			return str(number % modulus      )


if __name__ == "__main__":
					from doctest import testmod

					testmod()
					print(F"{solution(10) = }")





