


"""simple docstring"""


import pickle

import numpy as np
from matplotlib import pyplot as plt
class 						_UpperCamelCase						:
							'''simple docstring'''







							def __init__(  self					,     __a					,     __a					,     __a					,     __a					,     __a					,     __a=0.2					,     __a=0.2			):
										__lowerCAmelCase       					=    bp_numa
										__lowerCAmelCase       					=    bp_numa
										__lowerCAmelCase       					=    bp_numa
										__lowerCAmelCase       					=    conva_get[:2]
										__lowerCAmelCase       					=    conva_get[2]
										__lowerCAmelCase       					=    size_pa
										__lowerCAmelCase       					=    rate_w
										__lowerCAmelCase       					=    rate_t
										__lowerCAmelCase       					=    [
										    np.mat(-1 * np.random.rand(self.conva[0]					,     self.conva[0]			) + 0.5			)
										    for i in range(self.conva[1]			)
										]
										__lowerCAmelCase       					=    np.mat(-1 * np.random.rand(self.num_bpa					,     self.num_bpa			) + 0.5			)
										__lowerCAmelCase       					=    np.mat(-1 * np.random.rand(self.num_bpa					,     self.num_bpa			) + 0.5			)
										__lowerCAmelCase       					=    -2 * np.random.rand(self.conva[1]			) + 1
										__lowerCAmelCase       					=    -2 * np.random.rand(self.num_bpa			) + 1
										__lowerCAmelCase       					=    -2 * np.random.rand(self.num_bpa			) + 1

							def     snake_case       (  self					,     __a			):
										# save model dict with pickle
										__lowerCAmelCase       					=    {
										    "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(snake_case_					,     "wb"			) as f:
													pickle.dump(snake_case_					,     snake_case_			)

										print(f"Model saved： {save_path}"			)

							@classmethod
							def     snake_case       (  cls					,     __a			):
										# read saved model
										with open(snake_case_					,     "rb"			) as f:
													__lowerCAmelCase       					=    pickle.load(snake_case_			)  # noqa: S301

										__lowerCAmelCase       					=    model_dic.get("conv1"			)
										conv_get.append(model_dic.get("step_conv1"			)			)
										__lowerCAmelCase       					=    model_dic.get("size_pooling1"			)
										__lowerCAmelCase       					=    model_dic.get("num_bp1"			)
										__lowerCAmelCase       					=    model_dic.get("num_bp2"			)
										__lowerCAmelCase       					=    model_dic.get("num_bp3"			)
										__lowerCAmelCase       					=    model_dic.get("rate_weight"			)
										__lowerCAmelCase       					=    model_dic.get("rate_thre"			)
										# create model instance
										__lowerCAmelCase       					=    CNN(snake_case_					,     snake_case_					,     snake_case_					,     snake_case_					,     snake_case_					,     snake_case_					,     snake_case_			)
										# modify model parameter
										__lowerCAmelCase       					=    model_dic.get("w_conv1"			)
										__lowerCAmelCase       					=    model_dic.get("wkj"			)
										__lowerCAmelCase       					=    model_dic.get("vji"			)
										__lowerCAmelCase       					=    model_dic.get("thre_conv1"			)
										__lowerCAmelCase       					=    model_dic.get("thre_bp2"			)
										__lowerCAmelCase       					=    model_dic.get("thre_bp3"			)
										return conv_ins

							def     snake_case       (  self					,     __a			):
										return 1 / (1 + np.exp(-1 * x			))

							def     snake_case       (  self					,     __a			):
										return round(snake_case_					,     3			)

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

										# expanding the data slice to One dimenssion
										__lowerCAmelCase       					=    []
										for each_focus in data_focus:
													focusa_list.extend(self.Expand_Mat(snake_case_			)			)
										__lowerCAmelCase       					=    np.asarray(snake_case_			)
										return focus_list, data_featuremap

							def     snake_case       (  self					,     __a					,     __a					,     __a="average_pool"			):
										# pooling process
										__lowerCAmelCase       					=    len(featuremaps[0]			)
										__lowerCAmelCase       					=    int(size_map / size_pooling			)
										__lowerCAmelCase       					=    []
										for i_map in range(len(snake_case_			)			):
													__lowerCAmelCase       					=    featuremaps[i_map]
													__lowerCAmelCase       					=    []
													for i_focus in range(0					,     snake_case_					,     snake_case_			):
																for j_focus in range(0					,     snake_case_					,     snake_case_			):
																			__lowerCAmelCase       					=    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(snake_case_			)			)
																			elif pooling_type == "max_pooling":
																						# max pooling
																						map_pooled.append(np.max(snake_case_			)			)
													__lowerCAmelCase       					=    np.asmatrix(snake_case_			).reshape(snake_case_					,     snake_case_			)
													featuremap_pooled.append(snake_case_			)
										return featuremap_pooled

							def     snake_case       (  self					,     __a			):
										# expanding three dimension data to one dimension list
										__lowerCAmelCase       					=    []
										for i in range(len(snake_case_			)			):
													__lowerCAmelCase       					=    np.shape(data[i]			)
													__lowerCAmelCase       					=    data[i].reshape(1					,     shapes[0] * shapes[1]			)
													__lowerCAmelCase       					=    data_listed.getA().tolist()[0]
													data_expanded.extend(snake_case_			)
										__lowerCAmelCase       					=    np.asarray(snake_case_			)
										return data_expanded

							def     snake_case       (  self					,     __a			):
										# expanding matrix to one dimension list
										__lowerCAmelCase       					=    np.asarray(snake_case_			)
										__lowerCAmelCase       					=    np.shape(snake_case_			)
										__lowerCAmelCase       					=    data_mat.reshape(1					,     shapes[0] * shapes[1]			)
										return data_expanded

							def     snake_case       (  self					,     __a					,     __a					,     __a					,     __a					,     __a			):
										__lowerCAmelCase       					=    []
										__lowerCAmelCase       					=    0
										for i_map in range(snake_case_			):
													__lowerCAmelCase       					=    np.ones((size_map, size_map)			)
													for i in range(0					,     snake_case_					,     snake_case_			):
																for j in range(0					,     snake_case_					,     snake_case_			):
																			__lowerCAmelCase       					=    pd_pool[
																			    i_pool
																			]
																			__lowerCAmelCase       					=    i_pool + 1
													__lowerCAmelCase       					=    np.multiply(
													    snake_case_					,     np.multiply(out_map[i_map]					,     (1 - out_map[i_map])			)			)
													pd_all.append(snake_case_			)
										return pd_all

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

																__lowerCAmelCase       					=    np.dot(snake_case_					,     self.vji.T			) - self.thre_bpa
																__lowerCAmelCase       					=    self.sig(snake_case_			)
																__lowerCAmelCase       					=    np.dot(snake_case_					,     self.wkj.T			) - self.thre_bpa
																__lowerCAmelCase       					=    self.sig(snake_case_			)

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

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

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

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

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

										print("------------------Training Complished---------------------"			)
										print((" - - Training epoch: ", rp, f"     - - Mse: {mse:.6f}")			)
										if draw_e:
													draw_error()
										return mse

							def     snake_case       (  self					,     __a			):
										# model predict
										__lowerCAmelCase       					=    []
										print("-------------------Start Testing-------------------------"			)
										print((" - - Shape: Test_Data  ", np.shape(snake_case_			))			)
										for p in range(len(snake_case_			)			):
													__lowerCAmelCase       					=    np.asmatrix(datas_test[p]			)
													__lowerCAmelCase       					=    self.convolute(
													    snake_case_					,     self.conva					,     self.w_conva					,     self.thre_conva					,     conv_step=self.step_conva					,     )
													__lowerCAmelCase       					=    self.pooling(snake_case_					,     self.size_poolinga			)
													__lowerCAmelCase       					=    self._expand(snake_case_			)

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



							def     snake_case       (  self					,     __a			):
										# return the data of image after convoluting process so we can check it out
										__lowerCAmelCase       					=    np.asmatrix(snake_case_			)
										__lowerCAmelCase       					=    self.convolute(
										    snake_case_					,     self.conva					,     self.w_conva					,     self.thre_conva					,     conv_step=self.step_conva					,     )
										__lowerCAmelCase       					=    self.pooling(snake_case_					,     self.size_poolinga			)

										return data_conveda, data_pooleda


if __name__ == "__main__":
	pass




"""simple docstring"""


A  :     List[Any]    					=    [4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]
A  :     Optional[int]    					=    [3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]
A  :     Optional[int]    					=    {
    0: "Sunday",
    1: "Monday",
    2: "Tuesday",
    3: "Wednesday",
    4: "Thursday",
    5: "Friday",
    6: "Saturday",
}


def _lowerCamelCase			(	_UpperCamelCase					,				_UpperCamelCase					,				_UpperCamelCase   ):

			'''simple docstring'''




			assert len(str(_UpperCamelCase   )   ) > 2, "year should be in YYYY format"
			assert 1 <= month <= 12, "month should be between 1 to 12"
			assert 1 <= day <= 31, "day should be between 1 to 31"

			# Doomsday algorithm:
			__lowerCAmelCase       					=    year // 100
			__lowerCAmelCase       					=    (5 * (century % 4) + 2) % 7
			__lowerCAmelCase       					=    year % 100
			__lowerCAmelCase       					=    centurian % 12
			__lowerCAmelCase       					=    (
			    (centurian // 12) + centurian_m + (centurian_m // 4) + century_anchor
			) % 7
			__lowerCAmelCase       					=    (
			    DOOMSDAY_NOT_LEAP[month - 1]
			    if (year % 4 != 0) or (centurian == 0 and (year % 400) == 0)
			    else DOOMSDAY_LEAP[month - 1]
			)
			__lowerCAmelCase       					=    (dooms_day + day - day_anchor) % 7
			return WEEK_DAY_NAMES[week_day]


if __name__ == "__main__":
	import doctest

	doctest.testmod()




