



"""simple docstring"""




import pickle

import numpy as np
from matplotlib import pyplot as plt






class       UpperCAmelCase_    :



      def __init__(	self	:      Optional[Any]	,      A	:      Union[str, Any]	,      A	:      Union[str, Any]	,      A	:      Dict	,      A	:      List[str]	,      A	:      Any	,      A	:      int=0.2	,      A	:      Optional[Any]=0.2		):
           _UpperCAmelCase     :      Any														=       bp_numa
           _UpperCAmelCase     :      List[str]														=       bp_numa
           _UpperCAmelCase     :      Tuple														=       bp_numa
           _UpperCAmelCase     :      Tuple														=       conva_get[:2]
           _UpperCAmelCase     :      str														=       conva_get[2]
           _UpperCAmelCase     :      List[str]														=       size_pa
           _UpperCAmelCase     :      str														=       rate_w
           _UpperCAmelCase     :      Optional[int]														=       rate_t
           _UpperCAmelCase     :      Union[str, Any]														=       [
               np.mat(-1 * np.random.rand(self.conva[0]	,      self.conva[0]		) + 0.5		)
               for i in range(self.conva[1]		)
           ]
           _UpperCAmelCase     :      Optional[Any]														=       np.mat(-1 * np.random.rand(self.num_bpa	,      self.num_bpa		) + 0.5		)
           _UpperCAmelCase     :      List[Any]														=       np.mat(-1 * np.random.rand(self.num_bpa	,      self.num_bpa		) + 0.5		)
           _UpperCAmelCase     :      str														=       -2 * np.random.rand(self.conva[1]		) + 1
           _UpperCAmelCase     :      Dict														=       -2 * np.random.rand(self.num_bpa		) + 1
           _UpperCAmelCase     :      List[Any]														=       -2 * np.random.rand(self.num_bpa		) + 1



      def 		snake_case_   (	self	:      Optional[Any]	,      A	:      int		):
           # save model dict with pickle
           _UpperCAmelCase     :      List[str]														=       {
               "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(A	,      "wb"		) as f:
                pickle.dump(A	,      A		)

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



      @classmethod
      def 		snake_case_   (	cls	:      List[str]	,      A	:      Tuple		):
           # read saved model
           with open(A	,      "rb"		) as f:
                _UpperCAmelCase     :      Optional[int]														=       pickle.load(A		)  # noqa: S301

           _UpperCAmelCase     :      Optional[Any]														=       model_dic.get("conv1"		)
           conv_get.append(model_dic.get("step_conv1"		)		)
           _UpperCAmelCase     :      Tuple														=       model_dic.get("size_pooling1"		)
           _UpperCAmelCase     :      Optional[Any]														=       model_dic.get("num_bp1"		)
           _UpperCAmelCase     :      str														=       model_dic.get("num_bp2"		)
           _UpperCAmelCase     :      Optional[int]														=       model_dic.get("num_bp3"		)
           _UpperCAmelCase     :      Union[str, Any]														=       model_dic.get("rate_weight"		)
           _UpperCAmelCase     :      List[str]														=       model_dic.get("rate_thre"		)
           # create model instance
           _UpperCAmelCase     :      Optional[int]														=       CNN(A	,      A	,      A	,      A	,      A	,      A	,      A		)
           # modify model parameter
           _UpperCAmelCase     :      str														=       model_dic.get("w_conv1"		)
           _UpperCAmelCase     :      Optional[Any]														=       model_dic.get("wkj"		)
           _UpperCAmelCase     :      Tuple														=       model_dic.get("vji"		)
           _UpperCAmelCase     :      str														=       model_dic.get("thre_conv1"		)
           _UpperCAmelCase     :      Union[str, Any]														=       model_dic.get("thre_bp2"		)
           _UpperCAmelCase     :      Union[str, Any]														=       model_dic.get("thre_bp3"		)
           return conv_ins



      def 		snake_case_   (	self	:      List[str]	,      A	:      Optional[int]		):
           return 1 / (1 + np.exp(-1 * x		))



      def 		snake_case_   (	self	:      str	,      A	:      Tuple		):
           return round(A	,      3		)



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

           # expanding the data slice to One dimenssion
           _UpperCAmelCase     :      Optional[int]														=       []
           for each_focus in data_focus:
                focusa_list.extend(self.Expand_Mat(A		)		)
           _UpperCAmelCase     :      Union[str, Any]														=       np.asarray(A		)
           return focus_list, data_featuremap



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



      def 		snake_case_   (	self	:      Dict	,      A	:      str		):
           # expanding three dimension data to one dimension list
           _UpperCAmelCase     :      Optional[int]														=       []
           for i in range(len(A		)		):
                _UpperCAmelCase     :      str														=       np.shape(data[i]		)
                _UpperCAmelCase     :      List[Any]														=       data[i].reshape(1	,      shapes[0] * shapes[1]		)
                _UpperCAmelCase     :      List[str]														=       data_listed.getA().tolist()[0]
                data_expanded.extend(A		)
           _UpperCAmelCase     :      List[Any]														=       np.asarray(A		)
           return data_expanded



      def 		snake_case_   (	self	:      Union[str, Any]	,      A	:      int		):
           # expanding matrix to one dimension list
           _UpperCAmelCase     :      List[Any]														=       np.asarray(A		)
           _UpperCAmelCase     :      Dict														=       np.shape(A		)
           _UpperCAmelCase     :      List[str]														=       data_mat.reshape(1	,      shapes[0] * shapes[1]		)
           return data_expanded



      def 		snake_case_   (	self	:      Optional[Any]	,      A	:      Any	,      A	:      Union[str, Any]	,      A	:      Optional[Any]	,      A	:      List[Any]	,      A	:      Any		):
           _UpperCAmelCase     :      int														=       []
           _UpperCAmelCase     :      Dict														=       0
           for i_map in range(A		):
                _UpperCAmelCase     :      Dict														=       np.ones((size_map, size_map)		)
                for i in range(0	,      A	,      A		):
                     for j in range(0	,      A	,      A		):
                          _UpperCAmelCase     :      List[str]														=       pd_pool[
                              i_pool
                          ]
                          _UpperCAmelCase     :      Tuple														=       i_pool + 1
                _UpperCAmelCase     :      Tuple														=       np.multiply(
                    A	,      np.multiply(out_map[i_map]	,      (1 - out_map[i_map])		)		)
                pd_all.append(A		)
           return pd_all



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

                     _UpperCAmelCase     :      Tuple														=       np.dot(A	,      self.vji.T		) - self.thre_bpa
                     _UpperCAmelCase     :      Dict														=       self.sig(A		)
                     _UpperCAmelCase     :      List[Any]														=       np.dot(A	,      self.wkj.T		) - self.thre_bpa
                     _UpperCAmelCase     :      int														=       self.sig(A		)

                     # --------------Model Leaning ------------------------
                     # calculate error and gradient---------------
                     _UpperCAmelCase     :      Any														=       np.multiply(
                         (data_teach - bp_outa)	,      np.multiply(A	,      (1 - bp_outa)		)		)
                     _UpperCAmelCase     :      Optional[int]														=       np.multiply(
                         np.dot(A	,      self.wkj		)	,      np.multiply(A	,      (1 - bp_outa)		)		)
                     _UpperCAmelCase     :      Optional[int]														=       np.dot(A	,      self.vji		)

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

                          _UpperCAmelCase     :      Optional[Any]														=       self.w_conva[k_conv] + delta_w.reshape(
                              (self.conva[0], self.conva[0])		)

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

           def draw_error():
                _UpperCAmelCase     :      int														=       [error_accuracy for i in range(int(n_repeat * 1.2		)		)]
                plt.plot(A	,      "+-"		)
                plt.plot(A	,      "r--"		)
                plt.xlabel("Learning Times"		)
                plt.ylabel("All_mse"		)
                plt.grid(A	,      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	:      Any	,      A	:      Optional[int]		):
           # model predict
           _UpperCAmelCase     :      Union[str, Any]														=       []
           print("-------------------Start Testing-------------------------"		)
           print((" - - Shape: Test_Data  ", np.shape(A		))		)
           for p in range(len(A		)		):
                _UpperCAmelCase     :      Any														=       np.asmatrix(datas_test[p]		)
                _UpperCAmelCase							,			_UpperCAmelCase     :      Tuple														=       self.convolute(
                    A	,      self.conva	,      self.w_conva	,      self.thre_conva	,      conv_step=self.step_conva	,      )
                _UpperCAmelCase     :      List[str]														=       self.pooling(A	,      self.size_poolinga		)
                _UpperCAmelCase     :      str														=       self._expand(A		)

                _UpperCAmelCase     :      List[Any]														=       data_bp_input
                _UpperCAmelCase     :      int														=       bp_outa * self.vji.T - self.thre_bpa
                _UpperCAmelCase     :      Tuple														=       self.sig(A		)
                _UpperCAmelCase     :      int														=       bp_outa * self.wkj.T - self.thre_bpa
                _UpperCAmelCase     :      Optional[Any]														=       self.sig(A		)
                produce_out.extend(bp_outa.getA().tolist()		)
           _UpperCAmelCase     :      Union[str, Any]														=       [list(map(self.do_round	,      A		)		) for each in produce_out]
           return np.asarray(A		)



      def 		snake_case_   (	self	:      Union[str, Any]	,      A	:      List[str]		):
           # return the data of image after convoluting process so we can check it out
           _UpperCAmelCase     :      Optional[Any]														=       np.asmatrix(A		)
           _UpperCAmelCase							,			_UpperCAmelCase     :      Dict														=       self.convolute(
               A	,      self.conva	,      self.w_conva	,      self.thre_conva	,      conv_step=self.step_conva	,      )
           _UpperCAmelCase     :      str														=       self.pooling(A	,      self.size_poolinga		)

           return data_conveda, data_pooleda


if __name__ == "__main__":
 pass





"""simple docstring"""




from manim import *






class       UpperCAmelCase_    (							_UpperCamelCase		):



      def 		snake_case_   (	self	:      Tuple		):
           _UpperCAmelCase     :      str														=       Rectangle(height=0.5	,      width=0.5		)
           _UpperCAmelCase     :      List[Any]														=       Rectangle(height=0.25	,      width=0.25		)
           _UpperCAmelCase     :      Tuple														=       Rectangle(height=0.46	,      width=0.46		).set_stroke(width=0		)

           _UpperCAmelCase     :      List[Any]														=       [mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      List[str]														=       [mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      int														=       VGroup(*A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      Dict														=       VGroup(*A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      int														=       VGroup(A	,      A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      str														=       Text("CPU"	,      font_size=2_4		)
           _UpperCAmelCase     :      Union[str, Any]														=       Group(A	,      A		).arrange(A	,      buff=0.5	,      aligned_edge=A		)
           cpu.move_to([-2.5, -0.5, 0]		)
           self.add(A		)

           _UpperCAmelCase     :      Union[str, Any]														=       [mem.copy() for i in range(4		)]
           _UpperCAmelCase     :      Optional[int]														=       VGroup(*A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      Any														=       Text("GPU"	,      font_size=2_4		)
           _UpperCAmelCase     :      Dict														=       Group(A	,      A		).arrange(A	,      buff=0.5	,      aligned_edge=A		)
           gpu.move_to([-1, -1, 0]		)
           self.add(A		)

           _UpperCAmelCase     :      Tuple														=       [mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      str														=       VGroup(*A		).arrange(A	,      buff=0		)

           _UpperCAmelCase     :      Any														=       Text("Model"	,      font_size=2_4		)
           _UpperCAmelCase     :      Any														=       Group(A	,      A		).arrange(A	,      buff=0.5	,      aligned_edge=A		)
           model.move_to([3, -1.0, 0]		)
           self.add(A		)

           _UpperCAmelCase     :      List[str]														=       []
           _UpperCAmelCase     :      Optional[int]														=       []
           _UpperCAmelCase     :      str														=       []

           for i, rect in enumerate(A		):
                rect.set_stroke(A		)

                _UpperCAmelCase     :      Dict														=       Rectangle(height=0.46 / 4	,      width=0.46 / 3		).set_stroke(width=0.0		).set_fill(A	,      opacity=0.7		)

                if i == 0:
                     cpu_target.next_to(cpu_left_col_base[0].get_corner(DOWN + LEFT		)	,      buff=0.02	,      direction=A		)
                     cpu_target.set_x(cpu_target.get_x() + 0.1		)
                elif i == 3:
                     cpu_target.next_to(model_cpu_arr[0]	,      direction=A	,      buff=0.0		)
                else:
                     cpu_target.next_to(model_cpu_arr[i - 1]	,      direction=A	,      buff=0.0		)
                self.add(A		)
                model_cpu_arr.append(A		)

           self.add(*A	,      *A	,      *A		)

           _UpperCAmelCase     :      Dict														=       [mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      List[str]														=       VGroup(*A		).arrange(A	,      buff=0		)

           _UpperCAmelCase     :      List[str]														=       Text("Loaded Checkpoint"	,      font_size=2_4		)
           _UpperCAmelCase     :      Optional[int]														=       Group(A	,      A		).arrange(A	,      buff=0.5	,      aligned_edge=A		)
           checkpoint.move_to([3, 0.5, 0]		)

           self.add(A		)

           _UpperCAmelCase     :      Union[str, Any]														=       []
           _UpperCAmelCase     :      Union[str, Any]														=       []

           for i, rect in enumerate(A		):
                _UpperCAmelCase     :      str														=       fill.copy().set_fill(A	,      opacity=0.7		)
                target.move_to(A		)
                ckpt_arr.append(A		)

                _UpperCAmelCase     :      Dict														=       target.copy()
                if i < 5:
                     cpu_target.move_to(cpu_left_col_base[i + 1]		)
                else:
                     cpu_target.move_to(cpu_right_col_base[i - 5]		)
                ckpt_cpu_arr.append(A		)
           self.add(*A	,      *A		)

           _UpperCAmelCase     :      List[str]														=       Square(side_length=2.2		)
           key.move_to([-5, 2, 0]		)

           _UpperCAmelCase     :      List[Any]														=       MarkupText(
               f'<b>Key:</b>\n\n<span fgcolor=\'{YELLOW}\'>●</span> Empty Model'	,      font_size=1_8	,      )

           key_text.move_to([-5, 2.4, 0]		)

           self.add(A	,      A		)

           _UpperCAmelCase     :      Tuple														=       MarkupText(
               f'<span fgcolor=\'{BLUE}\'>●</span> Checkpoint'	,      font_size=1_8	,      )

           blue_text.next_to(A	,      DOWN * 2.4	,      aligned_edge=key_text.get_left()		)
           self.add(A		)

           _UpperCAmelCase     :      Any														=       MarkupText(
               f'Based on the passed in configuration, weights are stored in\na variety of np.memmaps on disk or to a particular device.'	,      font_size=2_4	,      )
           step_a.move_to([2, 2, 0]		)

           _UpperCAmelCase     :      int														=       [meta_mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      Optional[int]														=       [meta_mem.copy() for i in range(6		)]
           _UpperCAmelCase     :      List[str]														=       VGroup(*A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      Optional[int]														=       VGroup(*A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      List[Any]														=       VGroup(A	,      A		).arrange(A	,      buff=0		)
           _UpperCAmelCase     :      Union[str, Any]														=       Text("Disk"	,      font_size=2_4		)
           _UpperCAmelCase     :      int														=       Group(A	,      A		).arrange(A	,      buff=0.5	,      aligned_edge=A		)
           disk.move_to([-4.0, -1.25, 0]		)
           self.play(Write(A	,      run_time=3		)	,      Write(A	,      run_time=1		)	,      Create(A	,      run_time=1		)		)

           _UpperCAmelCase     :      List[Any]														=       []
           for i, rect in enumerate(A		):
                _UpperCAmelCase     :      Any														=       rect.copy()
                target.generate_target()
                target.target.move_to(disk_left_col_base[i]		).scale(0.5		)
                animations.append(MoveToTarget(A	,      run_time=1.5		)		)
           self.play(*A		)

           self.play(FadeOut(A		)		)

           _UpperCAmelCase     :      int														=       MarkupText(f'Then, the checkpoint is removed from memory\nthrough garbage collection.'	,      font_size=2_4		)
           step_a.move_to([2, 2, 0]		)

           self.play(Write(A	,      run_time=3		)		)

           self.play(
               FadeOut(A	,      A	,      *A	,      *A		)	,      )

           self.wait()
