{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"! pip install -U 'tensorflow[and-cuda]'","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:20:42.609061Z","iopub.execute_input":"2025-12-25T13:20:42.609498Z","iopub.status.idle":"2025-12-25T13:22:35.841474Z","shell.execute_reply.started":"2025-12-25T13:20:42.609464Z","shell.execute_reply":"2025-12-25T13:22:35.840367Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"! pip install git+https://github.com/darecophoenixx/wordroid.sblo.jp","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:22:35.843732Z","iopub.execute_input":"2025-12-25T13:22:35.844049Z","iopub.status.idle":"2025-12-25T13:22:59.096125Z","shell.execute_reply.started":"2025-12-25T13:22:35.844019Z","shell.execute_reply":"2025-12-25T13:22:59.095087Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras_ex.gkernel import GaussianKernel, GaussianKernel2, GaussianKernel3","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:22:59.097494Z","iopub.execute_input":"2025-12-25T13:22:59.097897Z","iopub.status.idle":"2025-12-25T13:23:08.395245Z","shell.execute_reply.started":"2025-12-25T13:22:59.097856Z","shell.execute_reply":"2025-12-25T13:23:08.394504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%matplotlib inline\nfrom IPython.display import SVG\nfrom tensorflow.keras.utils import plot_model, to_categorical, Sequence","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:08.397410Z","iopub.execute_input":"2025-12-25T13:23:08.397985Z","iopub.status.idle":"2025-12-25T13:23:08.404752Z","shell.execute_reply.started":"2025-12-25T13:23:08.397959Z","shell.execute_reply":"2025-12-25T13:23:08.403813Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ! pip install libarchive-c","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:08.405810Z","iopub.execute_input":"2025-12-25T13:23:08.406210Z","iopub.status.idle":"2025-12-25T13:23:08.428116Z","shell.execute_reply.started":"2025-12-25T13:23:08.406176Z","shell.execute_reply":"2025-12-25T13:23:08.426989Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"! pip install py7zr","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:08.429243Z","iopub.execute_input":"2025-12-25T13:23:08.429985Z","iopub.status.idle":"2025-12-25T13:23:27.035130Z","shell.execute_reply.started":"2025-12-25T13:23:08.429959Z","shell.execute_reply":"2025-12-25T13:23:27.034230Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import py7zr\nfrom PIL import Image\nimport io","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:27.036314Z","iopub.execute_input":"2025-12-25T13:23:27.036596Z","iopub.status.idle":"2025-12-25T13:23:27.109058Z","shell.execute_reply.started":"2025-12-25T13:23:27.036560Z","shell.execute_reply":"2025-12-25T13:23:27.108326Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os.path\nimport sys\nimport re\nimport itertools\nimport csv\nimport datetime\nimport pickle\nfrom collections import defaultdict, Counter\nimport random\nimport gc\nimport zipfile\nimport warnings\n\nimport matplotlib.pyplot as plt\nfrom matplotlib.ticker import NullFormatter\nimport seaborn as sns\nimport pandas as pd\nimport numpy as np\nimport scipy\nimport gensim\nfrom scipy.sparse import linalg\nfrom sklearn.metrics import f1_score, classification_report, confusion_matrix\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import pairwise\nfrom sklearn.metrics import f1_score, classification_report, confusion_matrix\nfrom sklearn import decomposition\nfrom sklearn import mixture\nfrom sklearn import preprocessing\nfrom sklearn import cluster\nfrom sklearn import manifold\nimport networkx as nx\n\nimport tensorflow as tf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:27.109956Z","iopub.execute_input":"2025-12-25T13:23:27.110258Z","iopub.status.idle":"2025-12-25T13:23:49.509288Z","shell.execute_reply.started":"2025-12-25T13:23:27.110230Z","shell.execute_reply":"2025-12-25T13:23:49.508370Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"! pip install japanize-matplotlib\n! pip install pyvis","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:23:49.510353Z","iopub.execute_input":"2025-12-25T13:23:49.511152Z","iopub.status.idle":"2025-12-25T13:24:00.813822Z","shell.execute_reply.started":"2025-12-25T13:23:49.511114Z","shell.execute_reply":"2025-12-25T13:24:00.812537Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pyvis.network import Network\nimport japanize_matplotlib\nplt.rcParams['font.family']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:00.819365Z","iopub.execute_input":"2025-12-25T13:24:00.820335Z","iopub.status.idle":"2025-12-25T13:24:00.944784Z","shell.execute_reply.started":"2025-12-25T13:24:00.820264Z","shell.execute_reply":"2025-12-25T13:24:00.943809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def hexbin(x, y, color, **kwargs):\n    cmap = sns.light_palette(color, as_cmap=True)\n    plt.hexbin(x, y, cmap=cmap, **kwargs)\ndef scatter(x, y, color, **kwargs):\n    plt.scatter(x, y, marker='.')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:00.945760Z","iopub.execute_input":"2025-12-25T13:24:00.946547Z","iopub.status.idle":"2025-12-25T13:24:00.951833Z","shell.execute_reply.started":"2025-12-25T13:24:00.946518Z","shell.execute_reply":"2025-12-25T13:24:00.950899Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tgt_dir = ''\ndir_name = 'img'\n\nimg_cnt = 0\ndef save_img():\n    global img_cnt\n    img_cnt += 1\n    img_name = 'img_{0:03}.png'.format(img_cnt)\n    img_name = os.path.join(tgt_dir, dir_name, img_name)\n    print(img_name)\n    plt.savefig(img_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:00.952683Z","iopub.execute_input":"2025-12-25T13:24:00.953050Z","iopub.status.idle":"2025-12-25T13:24:00.969636Z","shell.execute_reply.started":"2025-12-25T13:24:00.953020Z","shell.execute_reply":"2025-12-25T13:24:00.968779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"! mkdir img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:00.970509Z","iopub.execute_input":"2025-12-25T13:24:00.970914Z","iopub.status.idle":"2025-12-25T13:24:01.128649Z","shell.execute_reply.started":"2025-12-25T13:24:00.970880Z","shell.execute_reply":"2025-12-25T13:24:01.127703Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", \"When grouping with\")\nwarnings.filterwarnings(\"ignore\", \"use_inf_as_na\")\nwarnings.filterwarnings(\"ignore\", \"The figure layout\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:01.129867Z","iopub.execute_input":"2025-12-25T13:24:01.130255Z","iopub.status.idle":"2025-12-25T13:24:01.136670Z","shell.execute_reply.started":"2025-12-25T13:24:01.130223Z","shell.execute_reply":"2025-12-25T13:24:01.135829Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# cifar-10","metadata":{}},{"cell_type":"code","source":"train_7z_file = \"/kaggle/input/cifar-10/train.7z\"\ntest_7z_file = \"/kaggle/input/cifar-10/test.7z\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:01.137454Z","iopub.execute_input":"2025-12-25T13:24:01.137694Z","iopub.status.idle":"2025-12-25T13:24:01.158880Z","shell.execute_reply.started":"2025-12-25T13:24:01.137674Z","shell.execute_reply":"2025-12-25T13:24:01.157760Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nwith py7zr.SevenZipFile(train_7z_file, 'r') as archive:\n    archive.extractall(path=\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:01.159861Z","iopub.execute_input":"2025-12-25T13:24:01.160160Z","iopub.status.idle":"2025-12-25T13:24:26.037530Z","shell.execute_reply.started":"2025-12-25T13:24:01.160141Z","shell.execute_reply":"2025-12-25T13:24:26.036604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_files = os.listdir('train/')\ntrain_files = sorted(train_files, key=lambda s: int(s.split('.')[0]))\nprint(len(train_files))\ntrain_files[:5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:26.038516Z","iopub.execute_input":"2025-12-25T13:24:26.038838Z","iopub.status.idle":"2025-12-25T13:24:26.116444Z","shell.execute_reply.started":"2025-12-25T13:24:26.038810Z","shell.execute_reply":"2025-12-25T13:24:26.115634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"trainImg_list = []\nfor ifile in train_files:\n    img = Image.open(f'train/{ifile}')\n    img_array = np.asarray(img)\n    trainImg_list.append(img_array)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:26.117380Z","iopub.execute_input":"2025-12-25T13:24:26.117993Z","iopub.status.idle":"2025-12-25T13:24:34.384537Z","shell.execute_reply.started":"2025-12-25T13:24:26.117963Z","shell.execute_reply":"2025-12-25T13:24:34.383242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train0 = np.stack(trainImg_list).astype('float32') / 255.0\nx_train0.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:34.385904Z","iopub.execute_input":"2025-12-25T13:24:34.386212Z","iopub.status.idle":"2025-12-25T13:24:34.929819Z","shell.execute_reply.started":"2025-12-25T13:24:34.386182Z","shell.execute_reply":"2025-12-25T13:24:34.928854Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train1 = x_train0[:,:,::-1,:,]\nx_train1.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:34.930784Z","iopub.execute_input":"2025-12-25T13:24:34.931069Z","iopub.status.idle":"2025-12-25T13:24:34.937840Z","shell.execute_reply.started":"2025-12-25T13:24:34.931044Z","shell.execute_reply":"2025-12-25T13:24:34.937117Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train = np.vstack([x_train0, x_train1])\nx_train.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:34.939412Z","iopub.execute_input":"2025-12-25T13:24:34.939706Z","iopub.status.idle":"2025-12-25T13:24:35.808846Z","shell.execute_reply.started":"2025-12-25T13:24:34.939686Z","shell.execute_reply":"2025-12-25T13:24:35.808129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nwith py7zr.SevenZipFile(test_7z_file, 'r') as archive:\n    archive.extractall(path=\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:24:35.809708Z","iopub.execute_input":"2025-12-25T13:24:35.810007Z","iopub.status.idle":"2025-12-25T13:27:00.484362Z","shell.execute_reply.started":"2025-12-25T13:24:35.809978Z","shell.execute_reply":"2025-12-25T13:27:00.483355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_files = os.listdir('test/')\ntest_files = sorted(test_files, key=lambda s: int(s.split('.')[0]))\nprint(len(test_files))\ntest_files[:5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:00.485490Z","iopub.execute_input":"2025-12-25T13:27:00.485832Z","iopub.status.idle":"2025-12-25T13:27:00.874607Z","shell.execute_reply.started":"2025-12-25T13:27:00.485797Z","shell.execute_reply":"2025-12-25T13:27:00.873671Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\ntestImg_list = []\nfor ifile in test_files:\n    img = Image.open(f'test/{ifile}')\n    img_array = np.asarray(img)\n    testImg_list.append(img_array)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:00.875646Z","iopub.execute_input":"2025-12-25T13:27:00.875905Z","iopub.status.idle":"2025-12-25T13:27:49.777627Z","shell.execute_reply.started":"2025-12-25T13:27:00.875886Z","shell.execute_reply":"2025-12-25T13:27:49.776641Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_test = np.stack(testImg_list).astype('float32') / 255.0\nx_test.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:49.778688Z","iopub.execute_input":"2025-12-25T13:27:49.779337Z","iopub.status.idle":"2025-12-25T13:27:53.235932Z","shell.execute_reply.started":"2025-12-25T13:27:49.779304Z","shell.execute_reply":"2025-12-25T13:27:53.235095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train_label = pd.read_csv('/kaggle/input/cifar-10/trainLabels.csv', index_col=0)\ndf_train_label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.236854Z","iopub.execute_input":"2025-12-25T13:27:53.237153Z","iopub.status.idle":"2025-12-25T13:27:53.318592Z","shell.execute_reply.started":"2025-12-25T13:27:53.237131Z","shell.execute_reply":"2025-12-25T13:27:53.317841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"id_key = dict([ee for ee in enumerate(np.unique(df_train_label.label.values))])\nid_key","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.319473Z","iopub.execute_input":"2025-12-25T13:27:53.319728Z","iopub.status.idle":"2025-12-25T13:27:53.353579Z","shell.execute_reply.started":"2025-12-25T13:27:53.319708Z","shell.execute_reply":"2025-12-25T13:27:53.352733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"key_id = dict([(ee[1], ee[0]) for ee in enumerate(np.unique(df_train_label.label.values))])\nkey_id","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.360838Z","iopub.execute_input":"2025-12-25T13:27:53.361151Z","iopub.status.idle":"2025-12-25T13:27:53.399178Z","shell.execute_reply.started":"2025-12-25T13:27:53.361126Z","shell.execute_reply":"2025-12-25T13:27:53.398342Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_labels = [key_id[l] for l in df_train_label['label'].values]\ny_labels[:10]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.400030Z","iopub.execute_input":"2025-12-25T13:27:53.400300Z","iopub.status.idle":"2025-12-25T13:27:53.416966Z","shell.execute_reply.started":"2025-12-25T13:27:53.400259Z","shell.execute_reply":"2025-12-25T13:27:53.416137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_labels2 = y_labels * 2\nprint(len(y_labels2))\ny_labels2[:10]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.418128Z","iopub.execute_input":"2025-12-25T13:27:53.418448Z","iopub.status.idle":"2025-12-25T13:27:53.435719Z","shell.execute_reply.started":"2025-12-25T13:27:53.418427Z","shell.execute_reply":"2025-12-25T13:27:53.434759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.unique(y_labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.436622Z","iopub.execute_input":"2025-12-25T13:27:53.437662Z","iopub.status.idle":"2025-12-25T13:27:53.455459Z","shell.execute_reply.started":"2025-12-25T13:27:53.437598Z","shell.execute_reply":"2025-12-25T13:27:53.454640Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sampleSubmission = pd.read_csv('/kaggle/input/cifar-10/sampleSubmission.csv', index_col=0)\nsampleSubmission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.456338Z","iopub.execute_input":"2025-12-25T13:27:53.456734Z","iopub.status.idle":"2025-12-25T13:27:53.537700Z","shell.execute_reply.started":"2025-12-25T13:27:53.456707Z","shell.execute_reply":"2025-12-25T13:27:53.536845Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img = Image.open('train/2811.png')\nimg\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.538671Z","iopub.execute_input":"2025-12-25T13:27:53.538996Z","iopub.status.idle":"2025-12-25T13:27:53.574846Z","shell.execute_reply.started":"2025-12-25T13:27:53.538966Z","shell.execute_reply":"2025-12-25T13:27:53.574142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import imageio.v2 as imageio\n\nimg_array = imageio.imread(\"train/2811.png\")\nimg_array.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.575708Z","iopub.execute_input":"2025-12-25T13:27:53.576014Z","iopub.status.idle":"2025-12-25T13:27:53.657387Z","shell.execute_reply.started":"2025-12-25T13:27:53.575984Z","shell.execute_reply":"2025-12-25T13:27:53.656595Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(img_array)\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.658244Z","iopub.execute_input":"2025-12-25T13:27:53.658525Z","iopub.status.idle":"2025-12-25T13:27:53.901188Z","shell.execute_reply.started":"2025-12-25T13:27:53.658506Z","shell.execute_reply":"2025-12-25T13:27:53.900414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img = Image.fromarray(img_array)\nimg\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.902111Z","iopub.execute_input":"2025-12-25T13:27:53.902708Z","iopub.status.idle":"2025-12-25T13:27:53.923604Z","shell.execute_reply.started":"2025-12-25T13:27:53.902678Z","shell.execute_reply":"2025-12-25T13:27:53.922739Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# #from tensorflow.keras.utils import PyDataset\n# from keras.utils import PyDataset\n\n# class CIFAR10PyDataset(PyDataset):\n\n#     def __init__(self, x_filename_list, y_class, batch_size=32, **kwargs):\n#         super().__init__(**kwargs)\n#         self.x, self.y = x_filename_list, y_class\n#         self.batch_size = batch_size\n\n#     def __len__(self):\n#         # Return number of batches.\n#         return int(np.ceil(len(self.x) / self.batch_size))\n\n#     def __getitem__(self, idx):\n#         # Return x, y for batch idx.\n#         low = idx * self.batch_size\n#         # Cap upper bound at array length; the last batch may be smaller\n#         # if the total number of items is not a multiple of batch size.\n#         high = min(low + self.batch_size, len(self.x))\n#         batch_x = self.x[low:high]\n#         batch_y = self.y[low:high]\n\n#         return (\n#             np.array([imageio.imread(f\"train/{file_name}\") / 255.0 for file_name in batch_x]),\n#             to_categorical(batch_y, num_classes=10)\n#         )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.924492Z","iopub.execute_input":"2025-12-25T13:27:53.924713Z","iopub.status.idle":"2025-12-25T13:27:53.929116Z","shell.execute_reply.started":"2025-12-25T13:27:53.924696Z","shell.execute_reply":"2025-12-25T13:27:53.928438Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# cifar_dataset = CIFAR10PyDataset(train_files, y_labels)\n# print(len(cifar_dataset))\n# x, y = cifar_dataset[0]\n# x.shape, y.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.930102Z","iopub.execute_input":"2025-12-25T13:27:53.930373Z","iopub.status.idle":"2025-12-25T13:27:53.944204Z","shell.execute_reply.started":"2025-12-25T13:27:53.930354Z","shell.execute_reply":"2025-12-25T13:27:53.943435Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# x, y = cifar_dataset[1562]\n# x.shape, y.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.945066Z","iopub.execute_input":"2025-12-25T13:27:53.946383Z","iopub.status.idle":"2025-12-25T13:27:53.961091Z","shell.execute_reply.started":"2025-12-25T13:27:53.946349Z","shell.execute_reply":"2025-12-25T13:27:53.960178Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_train = y_labels2\ny_cat_train0 = to_categorical(y_labels2)\ny_cat_train = y_cat_train0\nprint(y_cat_train.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.962029Z","iopub.execute_input":"2025-12-25T13:27:53.962970Z","iopub.status.idle":"2025-12-25T13:27:53.984772Z","shell.execute_reply.started":"2025-12-25T13:27:53.962936Z","shell.execute_reply":"2025-12-25T13:27:53.983801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = x_train0[ii*ncols + jj]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:27:53.985695Z","iopub.execute_input":"2025-12-25T13:27:53.985999Z","iopub.status.idle":"2025-12-25T13:28:03.772823Z","shell.execute_reply.started":"2025-12-25T13:27:53.985969Z","shell.execute_reply":"2025-12-25T13:28:03.771784Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = x_train1[ii*ncols + jj]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:03.773853Z","iopub.execute_input":"2025-12-25T13:28:03.774109Z","iopub.status.idle":"2025-12-25T13:28:14.675233Z","shell.execute_reply.started":"2025-12-25T13:28:03.774089Z","shell.execute_reply":"2025-12-25T13:28:14.674022Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=12\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    idx = (np.array(y_labels) == ii)\n    target_img = x_train0[idx][:ncols]\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = target_img[jj]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:14.676325Z","iopub.execute_input":"2025-12-25T13:28:14.676576Z","iopub.status.idle":"2025-12-25T13:28:27.347066Z","shell.execute_reply.started":"2025-12-25T13:28:14.676557Z","shell.execute_reply":"2025-12-25T13:28:27.345831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = x_test[ii*ncols + jj]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:27.348169Z","iopub.execute_input":"2025-12-25T13:28:27.348449Z","iopub.status.idle":"2025-12-25T13:28:37.178853Z","shell.execute_reply.started":"2025-12-25T13:28:27.348427Z","shell.execute_reply":"2025-12-25T13:28:37.177856Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# datagen = ImageDataGenerator(\n#     # set input mean to 0 over the dataset\n#     featurewise_center=False,\n#     # set each sample mean to 0\n#     samplewise_center=False,\n#     # divide inputs by std of dataset\n#     featurewise_std_normalization=False,\n#     # divide each input by its std\n#     samplewise_std_normalization=False,\n#     # apply ZCA whitening\n#     zca_whitening=False,\n#     # epsilon for ZCA whitening\n#     zca_epsilon=1e-06,\n#     # randomly rotate images in the range (deg 0 to 180)\n#     rotation_range=10,\n#     # randomly shift images horizontally\n#     width_shift_range=0.1,\n#     # randomly shift images vertically\n#     height_shift_range=0.1,\n#     # set range for random shear\n#     shear_range=0.,\n#     # set range for random zoom\n#     zoom_range=0.,\n#     # set range for random channel shifts\n#     channel_shift_range=0.,\n#     # set mode for filling points outside the input boundaries\n#     fill_mode='nearest',\n#     # value used for fill_mode = \"constant\"\n#     cval=0.,\n#     # randomly flip images\n#     horizontal_flip=True,\n#     # randomly flip images\n#     vertical_flip=False,\n#     # set rescaling factor (applied before any other transformation)\n#     rescale=None,\n#     # set function that will be applied on each input\n#     preprocessing_function=None,\n#     # image data format, either \"channels_first\" or \"channels_last\"\n#     data_format=None,\n#     # fraction of images reserved for validation (strictly between 0 and 1)\n#     validation_split=0.0)\n\n# datagen.fit(x_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.179900Z","iopub.execute_input":"2025-12-25T13:28:37.180168Z","iopub.status.idle":"2025-12-25T13:28:37.185258Z","shell.execute_reply.started":"2025-12-25T13:28:37.180147Z","shell.execute_reply":"2025-12-25T13:28:37.184269Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Conv2DRBF","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import (\n    Input, Conv2D, BatchNormalization, Activation, \n    Add, GlobalAveragePooling2D, GlobalMaxPooling2D, Dense, Reshape, TimeDistributed, Lambda, concatenate\n)\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import regularizers\nimport tensorflow.keras.backend as K","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.186531Z","iopub.execute_input":"2025-12-25T13:28:37.186870Z","iopub.status.idle":"2025-12-25T13:28:37.211366Z","shell.execute_reply.started":"2025-12-25T13:28:37.186841Z","shell.execute_reply":"2025-12-25T13:28:37.210436Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"THRESHOLD = 0.5\n\ndef f1_score_metric(y_true, y_pred):\n    \"\"\"\n    Kaggleでよく使用されるマクロF1スコアを計算するカスタムメトリック。\n    tf.is_nan を tf.math.is_nan に修正。\n    \"\"\"\n    \n    # y_predを閾値処理してバイナリ化\n    # K.clip(y_pred, 0, 1)は確率値を0〜1にクリップ\n    y_pred_thresh = K.cast(K.greater(K.clip(y_pred, 0, 1), THRESHOLD), K.floatx())\n    \n    # True Positives (TP), False Positives (FP), False Negatives (FN) を計算\n    # 各クラスごと (axis=0 はバッチ、axis=1 はクラス)\n    tp = K.sum(y_true * y_pred_thresh, axis=0)\n    fp = K.sum((1 - y_true) * y_pred_thresh, axis=0)\n    fn = K.sum(y_true * (1 - y_pred_thresh), axis=0)\n\n    # Precision (p) と Recall (r)\n    p = tp / (tp + fp + K.epsilon())\n    r = tp / (tp + fn + K.epsilon())\n\n    # F1 Score (各クラス)\n    f1_per_class = 2 * p * r / (p + r + K.epsilon())\n    \n    # NaNの処理: 0/0 (p=0, r=0の場合)を0に設定\n    # 【修正点】tf.is_nan を tf.math.is_nan に変更\n    f1_per_class = tf.where(tf.math.is_nan(f1_per_class), tf.zeros_like(f1_per_class), f1_per_class)\n    \n    # マクロF1スコア (クラス全体の平均)\n    return K.mean(f1_per_class)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.212510Z","iopub.execute_input":"2025-12-25T13:28:37.212843Z","iopub.status.idle":"2025-12-25T13:28:37.221011Z","shell.execute_reply.started":"2025-12-25T13:28:37.212817Z","shell.execute_reply":"2025-12-25T13:28:37.220041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Layer\nfrom tensorflow.keras import initializers, constraints\n\n# class Conv2DRBF(Layer):\n#     \"\"\"\n#     RBFカーネル畳み込みレイヤー (Conv2D-RBF)\n\n#     通常のConv2D層の積和演算（内積）を RBF カーネル（非線形類似度）に置き換えます。\n#     gammaパラメータは log(gamma)として保持され、学習時の安定性を向上させています。\n#     \"\"\"\n#     def __init__(self, filters, kernel_size,\n#                  gamma_initializer=initializers.Constant(np.log(1 / (0.2**2))),\n#                  gamma_regularizer=None,\n#                  kernel_initializer=initializers.RandomUniform(minval=0.0, maxval=1.0),\n#                  strides=(1, 1), padding='valid', **kwargs):\n        \n#         super(Conv2DRBF, self).__init__(**kwargs)\n        \n#         self.filters = filters\n#         self.kernel_size = tuple(kernel_size)\n#         self.strides = tuple(strides)\n#         # tf.image.extract_patchesに対応させるため、paddingを大文字に\n#         self.padding = padding.upper() \n        \n#         # log_gammaのパラメータ設定\n#         # log_gammaの初期値が0の場合、exp(0)=1となり、gamma=1からスタートします。\n#         self.gamma_initializer = initializers.get(gamma_initializer)\n#         self.gamma_regularizer = gamma_regularizer\n#         # log_gammaは非負制約が不要になるため、gamma_constraintは削除しました\n#         self.gamma_constraint = None \n\n#         self.kernel_initializer = kernel_initializer\n\n#     def build(self, input_shape):\n#         # input_shape: (B, H, W, C_in)\n        \n#         input_dim = input_shape[-1]\n        \n#         # 1. ランドマーク (カーネル μ) の定義\n#         # kernel_shape: (kH, kW, C_in, F)\n#         self.kernel = self.add_weight(\n#             shape=self.kernel_size + (input_dim, self.filters),\n#             # 入力がN(0, 1)付近の場合、小さな値 (例: TruncatedNormal) が望ましい\n#             initializer=self.kernel_initializer,\n#             name='rbf_kernel_landmarks',\n#             trainable=True,\n#         )\n\n#         # 2. log_gamma の定義\n#         # gammaの代わりにlog_gammaを学習する。非負制約は不要。\n#         self.log_gamma = self.add_weight(\n#             shape=(1,),\n#             # 初期値が'ones'だとlog_gamma=1となり、gamma=e^1≈2.71からスタート\n#             # 'zeros'だとlog_gamma=0となり、gamma=1からスタート。ここでは'zeros'を推奨\n#             initializer=self.gamma_initializer,\n#             regularizer=self.gamma_regularizer,\n#             name='log_gamma',\n#             trainable=True\n#         )\n        \n#         super(Conv2DRBF, self).build(input_shape)\n\n#     def call(self, inputs):\n#         # inputs: (B, H, W, C_in)\n        \n#         # log_gammaから実際のgamma値を計算\n#         gamma = tf.exp(self.log_gamma)\n\n#         # 1. パッチの抽出 (Sliding Window)\n#         ksizes = [1, self.kernel_size[0], self.kernel_size[1], 1]\n#         strides = [1, self.strides[0], self.strides[1], 1]\n#         rates = [1, 1, 1, 1] \n        \n#         # patches shape: (B, H_out, W_out, kH * kW * C_in)\n#         patches = tf.image.extract_patches(\n#             images=inputs,\n#             sizes=ksizes,\n#             strides=strides,\n#             rates=rates,\n#             padding=self.padding\n#         )\n\n#         # パッチが平坦化された次元サイズ: C_flat\n#         C_flat = tf.shape(patches)[-1]\n#         B, H_out, W_out = tf.shape(patches)[0], tf.shape(patches)[1], tf.shape(patches)[2]\n        \n#         # 2. 距離計算のための形状変更\n        \n#         # パッチ: (B, H_out, W_out, 1, C_flat)\n#         patches_for_dist = tf.reshape(patches, (B, H_out, W_out, 1, C_flat))\n\n#         # ランドマーク: (1, 1, 1, F, C_flat)\n#         kernel_flat = tf.reshape(self.kernel, (1, 1, 1, self.filters, C_flat))\n\n#         # 3. ユークリッド距離の二乗計算: ||x - μ||^2\n#         # (B, H_out, W_out, F, C_flat) から、最後の次元を reduce_sum\n#         sq_dist = tf.reduce_sum(tf.square(patches_for_dist - kernel_flat), axis=-1)\n#         # sq_dist shape: (B, H_out, W_out, F)\n\n#         # 4. RBFカーネル関数の適用: exp(-gamma * ||x - μ||^2)\n#         # tf.exp()を使用してRBFカーネルを計算\n#         rbf_output = tf.exp(-gamma * sq_dist)\n#         # rbf_output shape: (B, H_out, W_out, F)\n\n#         return rbf_output\n\n#     def compute_output_shape(self, input_shape):\n#         # KerasのConv2Dと同様のロジックで出力形状を計算\n#         H_in = input_shape[1]\n#         W_in = input_shape[2]\n        \n#         if self.padding == 'VALID':\n#             H_out = (H_in - self.kernel_size[0]) // self.strides[0] + 1\n#             W_out = (W_in - self.kernel_size[1]) // self.strides[1] + 1\n#         elif self.padding == 'SAME':\n#             H_out = (H_in + self.strides[0] - 1) // self.strides[0]\n#             W_out = (W_in + self.strides[1] - 1) // self.strides[1]\n#         else:\n#             raise ValueError(f\"Unknown padding: {self.padding}\")\n            \n#         return (input_shape[0], H_out, W_out, self.filters)\n\n#     def get_config(self):\n#         # モデル保存・読み込みのためにconfigを定義\n#         config = super(Conv2DRBF, self).get_config()\n#         config.update({\n#             'filters': self.filters,\n#             'kernel_size': self.kernel_size,\n#             'strides': self.strides,\n#             'padding': self.padding.lower(),\n#             'gamma_initializer': initializers.serialize(self.gamma_initializer),\n#             'gamma_regularizer': initializers.serialize(self.gamma_regularizer),\n#             # 'gamma_constraint'はlog_gammaの導入により不要になったため削除\n#         })\n#         return config\n\nclass Conv2DRBF_patch(Layer):\n    \"\"\"\n    RBFカーネル畳み込みレイヤー (Conv2D-RBF)\n\n    通常のConv2D層の積和演算（内積）を RBF カーネル（非線形類似度）に置き換えます。\n    gammaパラメータは log(gamma)として保持され、学習時の安定性を向上させています。\n    \"\"\"\n    def __init__(self, filters, kernel_size,\n                 gamma_initializer=initializers.Constant(np.log(1 / (0.2**2))),\n                 gamma_regularizer=None,\n                 kernel_initializer=initializers.RandomUniform(minval=0.0, maxval=1.0),\n                 strides=(1, 1), padding='valid', **kwargs):\n        \n        super(Conv2DRBF_patch, self).__init__(**kwargs)\n        \n        self.filters = filters\n        self.kernel_size = tuple(kernel_size)\n        self.strides = tuple(strides)\n        # tf.image.extract_patchesに対応させるため、paddingを大文字に\n        self.padding = padding.upper() \n        \n        # log_gammaのパラメータ設定\n        # log_gammaの初期値が0の場合、exp(0)=1となり、gamma=1からスタートします。\n        self.gamma_initializer = initializers.get(gamma_initializer)\n        self.gamma_regularizer = gamma_regularizer\n        # log_gammaは非負制約が不要になるため、gamma_constraintは削除しました\n        self.gamma_constraint = None \n\n        self.kernel_initializer = kernel_initializer\n\n    def build(self, input_shape):\n        # input_shape: (B, H, W, C_in)\n        \n        input_dim = input_shape[-1]\n        \n        # 1. ランドマーク (カーネル μ) の定義\n        # kernel_shape: (kH, kW, C_in, F)\n        self.kernel = self.add_weight(\n            shape=self.kernel_size + (input_dim, self.filters),\n            # 入力がN(0, 1)付近の場合、小さな値 (例: TruncatedNormal) が望ましい\n            initializer=self.kernel_initializer,\n            name='rbf_kernel_landmarks',\n            trainable=True,\n        )\n\n        # 2. log_gamma の定義\n        # gammaの代わりにlog_gammaを学習する。非負制約は不要。\n        self.log_gamma = self.add_weight(\n            shape=(1,),\n            # 初期値が'ones'だとlog_gamma=1となり、gamma=e^1≈2.71からスタート\n            # 'zeros'だとlog_gamma=0となり、gamma=1からスタート。ここでは'zeros'を推奨\n            initializer=self.gamma_initializer,\n            regularizer=self.gamma_regularizer,\n            name='log_gamma',\n            trainable=True\n        )\n        \n        super(Conv2DRBF_patch, self).build(input_shape)\n\n    def call(self, inputs):\n        # inputs: (B, H, W, C_in)\n        \n        # log_gammaから実際のgamma値を計算\n        gamma = tf.exp(self.log_gamma)\n\n        # 1. パッチの抽出 (Sliding Window)\n        ksizes = [1, self.kernel_size[0], self.kernel_size[1], 1]\n        strides = [1, self.strides[0], self.strides[1], 1]\n        rates = [1, 1, 1, 1] \n        \n        # patches shape: (B, H_out, W_out, kH * kW * C_in)\n        patches = tf.image.extract_patches(\n            images=inputs,\n            sizes=ksizes,\n            strides=strides,\n            rates=rates,\n            padding=self.padding\n        )\n\n        # パッチが平坦化された次元サイズ: C_flat\n        C_flat = tf.shape(patches)[-1]\n        B, H_out, W_out = tf.shape(patches)[0], tf.shape(patches)[1], tf.shape(patches)[2]\n        \n        # 2. 距離計算のための形状変更\n        \n        # パッチ: (B, H_out, W_out, 1, C_flat)\n        patches_for_dist = tf.reshape(patches, (B, H_out, W_out, 1, C_flat))\n        return patches_for_dist\n\n        # # ランドマーク: (1, 1, 1, F, C_flat)\n        # kernel_flat = tf.reshape(self.kernel, (1, 1, 1, self.filters, C_flat))\n\n        # # 3. ユークリッド距離の二乗計算: ||x - μ||^2\n        # # (B, H_out, W_out, F, C_flat) から、最後の次元を reduce_sum\n        # sq_dist = tf.reduce_sum(tf.square(patches_for_dist - kernel_flat), axis=-1)\n        # # sq_dist shape: (B, H_out, W_out, F)\n\n        # # 4. RBFカーネル関数の適用: exp(-gamma * ||x - μ||^2)\n        # # tf.exp()を使用してRBFカーネルを計算\n        # rbf_output = tf.exp(-gamma * sq_dist)\n        # rbf_output shape: (B, H_out, W_out, F)\n\n        return rbf_output\n\n    def compute_output_shape(self, input_shape):\n        # KerasのConv2Dと同様のロジックで出力形状を計算\n        H_in = input_shape[1]\n        W_in = input_shape[2]\n        \n        if self.padding == 'VALID':\n            H_out = (H_in - self.kernel_size[0]) // self.strides[0] + 1\n            W_out = (W_in - self.kernel_size[1]) // self.strides[1] + 1\n        elif self.padding == 'SAME':\n            H_out = (H_in + self.strides[0] - 1) // self.strides[0]\n            W_out = (W_in + self.strides[1] - 1) // self.strides[1]\n        else:\n            raise ValueError(f\"Unknown padding: {self.padding}\")\n            \n        return (input_shape[0], H_out, W_out, 1, self.kernel_size[0]*self.kernel_size[1]*input_shape[3])\n\n    def get_config(self):\n        # モデル保存・読み込みのためにconfigを定義\n        config = super(Conv2DRBF_patch, self).get_config()\n        config.update({\n            'filters': self.filters,\n            'kernel_size': self.kernel_size,\n            'strides': self.strides,\n            'padding': self.padding.lower(),\n            'gamma_initializer': initializers.serialize(self.gamma_initializer),\n            'gamma_regularizer': initializers.serialize(self.gamma_regularizer),\n            # 'gamma_constraint'はlog_gammaの導入により不要になったため削除\n        })\n        return config","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.222233Z","iopub.execute_input":"2025-12-25T13:28:37.222827Z","iopub.status.idle":"2025-12-25T13:28:37.246770Z","shell.execute_reply.started":"2025-12-25T13:28:37.222799Z","shell.execute_reply":"2025-12-25T13:28:37.245803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"### rbf_targetをパラメータにするのはやめる\n# class Conv2DRBF(Layer):\n#     \"\"\"\n#     RBFカーネル畳み込みレイヤー (Conv2D-RBF)\n\n#     通常のConv2D層の積和演算（内積）を RBF カーネル（非線形類似度）に置き換えます。\n#     gammaパラメータは log(gamma)として保持され、学習時の安定性を向上させています。\n#     \"\"\"\n#     def __init__(self, filters, kernel_size,\n#                  #gamma_initializer=initializers.Constant(np.log(1 / (0.2**2))),\n#                  gamma_regularizer=None,\n#                  rbf_target=0.01,\n#                  kernel_initializer=initializers.RandomUniform(minval=0.0, maxval=1.0),\n#                  strides=(1, 1), padding='valid', **kwargs):\n        \n#         super(Conv2DRBF, self).__init__(**kwargs)\n        \n#         self.filters = filters\n#         self.kernel_size = tuple(kernel_size)\n#         self.strides = tuple(strides)\n#         # tf.image.extract_patchesに対応させるため、paddingを大文字に\n#         self.padding = padding.upper() \n        \n#         # log_gammaのパラメータ設定\n#         #self.gamma_initializer = initializers.Constant(np.log(1 / (0.2**2)))\n#         self.gamma_regularizer = gamma_regularizer\n#         # log_gammaは非負制約が不要になるため、gamma_constraintは削除しました\n#         self.rbf_target = rbf_target\n\n#         self.kernel_initializer = kernel_initializer\n\n#     def build(self, input_shape):\n#         # input_shape: (B, H, W, C_in)\n        \n#         input_dim = input_shape[-1]\n        \n#         # 1. ランドマーク (カーネル μ) の定義\n#         # kernel_shape: (kH, kW, C_in, F)\n#         self.kernel = self.add_weight(\n#             shape=self.kernel_size + (input_dim, self.filters),\n#             # 入力がN(0, 1)付近の場合、小さな値 (例: TruncatedNormal) が望ましい\n#             initializer=self.kernel_initializer,\n#             name='rbf_kernel_landmarks',\n#             trainable=True,\n#         )\n\n#         # 2. log_gamma の定義\n#         # gammaの代わりにlog_gammaを学習する。非負制約は不要。\n#         D1, D2, Cin = self.kernel_size[0], self.kernel_size[1], input_shape[3]\n#         #print('D1, D2, Cin >>>', D1, D2, Cin)\n#         self.log_gamma = self.add_weight(\n#             shape=(1,),\n#             initializer=initializers.Constant(np.log(-np.log(self.rbf_target) / (D1*D2*Cin))),\n#             regularizer=self.gamma_regularizer,\n#             name='log_gamma',\n#             trainable=True\n#         )\n        \n#         super(Conv2DRBF, self).build(input_shape)\n\n#     def call(self, inputs):\n#         # inputs: (B, H, W, C_in)\n        \n#         # log_gammaから実際のgamma値を計算\n#         gamma = tf.exp(self.log_gamma)\n\n#         # 1. パッチの抽出 (Sliding Window)\n#         ksizes = [1, self.kernel_size[0], self.kernel_size[1], 1]\n#         strides = [1, self.strides[0], self.strides[1], 1]\n#         rates = [1, 1, 1, 1] \n        \n#         # patches shape: (B, H_out, W_out, kH * kW * C_in)\n#         patches = tf.image.extract_patches(\n#             images=inputs,\n#             sizes=ksizes,\n#             strides=strides,\n#             rates=rates,\n#             padding=self.padding\n#         )\n\n#         # パッチが平坦化された次元サイズ: C_flat\n#         C_flat = tf.shape(patches)[-1]\n#         B, H_out, W_out = tf.shape(patches)[0], tf.shape(patches)[1], tf.shape(patches)[2]\n        \n#         # 2. 距離計算のための形状変更\n        \n#         # パッチ: (B, H_out, W_out, 1, C_flat)\n#         patches_for_dist = tf.reshape(patches, (B, H_out, W_out, 1, C_flat))\n\n#         # ランドマーク: (1, 1, 1, F, C_flat)\n#         kernel_flat = tf.reshape(self.kernel, (1, 1, 1, self.filters, C_flat))\n\n#         # 3. ユークリッド距離の二乗計算: ||x - μ||^2\n        \n#         # # (B, H_out, W_out, F, C_flat) から、最後の次元を reduce_sum\n#         # sq_dist = tf.reduce_sum(tf.square(patches_for_dist - kernel_flat), axis=-1)\n#         # # sq_dist shape: (B, H_out, W_out, F)\n        \n#         # パッチのノルム二乗: ||x||^2\n#         # (B, H_out, W_out, 1) - F次元にブロードキャストされる\n#         patch_norm_sq = tf.reduce_sum(tf.square(patches_for_dist), axis=-1)\n#         #print('patch_norm_sq.shape >>>', patch_norm_sq.shape)\n\n#         # ランドマークのノルム二乗: ||μ||^2\n#         # (1, 1, 1, F) - B*H_out*W_out次元にブロードキャストされる\n#         kernel_norm_sq = tf.reduce_sum(tf.square(kernel_flat), axis=-1)\n#         #print('kernel_norm_sq.shape >>>', kernel_norm_sq.shape)\n\n#         # 内積: x・μ\n#         # (B, H_out, W_out, F)\n#         # inner_product = tf.reduce_sum(patches_for_dist * kernel_flat, axis=-1)\n#         inner_product = tf.tensordot(tf.reshape(patches, (B, H_out, W_out, C_flat)), tf.reshape(self.kernel, (self.filters, C_flat)), axes=[[3], [1]])\n#         #print('inner_product.shape >>>', inner_product.shape)\n        \n#         # 組み合わせ: ||x||^2 + ||μ||^2 - 2(x・μ)\n#         sq_dist = patch_norm_sq + kernel_norm_sq - 2.0 * inner_product\n#         # sq_dist shape: (B, H_out, W_out, F)\n\n#         # 4. RBFカーネル関数の適用: exp(-gamma * ||x - μ||^2)\n#         # tf.exp()を使用してRBFカーネルを計算\n#         rbf_output = tf.exp(-gamma * sq_dist)\n#         # rbf_output shape: (B, H_out, W_out, F)\n\n#         return rbf_output\n\n#     def compute_output_shape(self, input_shape):\n#         # KerasのConv2Dと同様のロジックで出力形状を計算\n#         H_in = input_shape[1]\n#         W_in = input_shape[2]\n        \n#         if self.padding == 'VALID':\n#             H_out = (H_in - self.kernel_size[0]) // self.strides[0] + 1\n#             W_out = (W_in - self.kernel_size[1]) // self.strides[1] + 1\n#         elif self.padding == 'SAME':\n#             H_out = (H_in + self.strides[0] - 1) // self.strides[0]\n#             W_out = (W_in + self.strides[1] - 1) // self.strides[1]\n#         else:\n#             raise ValueError(f\"Unknown padding: {self.padding}\")\n            \n#         return (input_shape[0], H_out, W_out, self.filters)\n\n#     def get_config(self):\n#         # モデル保存・読み込みのためにconfigを定義\n#         config = super(Conv2DRBF, self).get_config()\n#         config.update({\n#             'filters': self.filters,\n#             'kernel_size': self.kernel_size,\n#             'strides': self.strides,\n#             'padding': self.padding.lower(),\n#             'gamma_initializer': initializers.serialize(self.gamma_initializer),\n#             'gamma_regularizer': initializers.serialize(self.gamma_regularizer),\n#             # 'gamma_constraint'はlog_gammaの導入により不要になったため削除\n#         })\n#         return config\n\nclass Conv2DRBF(Layer):\n    \"\"\"\n    RBFカーネル畳み込みレイヤー (Conv2D-RBF)\n\n    通常のConv2D層の積和演算（内積）を RBF カーネル（非線形類似度）に置き換えます。\n    gammaパラメータは log(gamma)として保持され、学習時の安定性を向上させています。\n    \"\"\"\n    def __init__(self, filters, kernel_size,\n                 gamma_initializer=initializers.Constant(np.log(1 / (0.2**2))),\n                 gamma_regularizer=None,\n                 kernel_initializer=initializers.RandomUniform(minval=0.0, maxval=1.0),\n                 strides=(1, 1), padding='valid', **kwargs):\n        \n        super(Conv2DRBF, self).__init__(**kwargs)\n        \n        self.filters = filters\n        self.kernel_size = tuple(kernel_size)\n        self.strides = tuple(strides)\n        # tf.image.extract_patchesに対応させるため、paddingを大文字に\n        self.padding = padding.upper() \n        \n        # log_gammaのパラメータ設定\n        # log_gammaの初期値が0の場合、exp(0)=1となり、gamma=1からスタートします。\n        self.gamma_initializer = initializers.get(gamma_initializer)\n        self.gamma_regularizer = gamma_regularizer\n        # log_gammaは非負制約が不要になるため、gamma_constraintは削除しました\n        self.gamma_constraint = None \n\n        self.kernel_initializer = kernel_initializer\n\n    def build(self, input_shape):\n        # input_shape: (B, H, W, C_in)\n        \n        input_dim = input_shape[-1]\n        \n        # 1. ランドマーク (カーネル μ) の定義\n        # kernel_shape: (kH, kW, C_in, F)\n        self.kernel = self.add_weight(\n            shape=self.kernel_size + (input_dim, self.filters),\n            # 入力がN(0, 1)付近の場合、小さな値 (例: TruncatedNormal) が望ましい\n            initializer=self.kernel_initializer,\n            name='rbf_kernel_landmarks',\n            trainable=True,\n        )\n\n        # 2. log_gamma の定義\n        # gammaの代わりにlog_gammaを学習する。非負制約は不要。\n        self.log_gamma = self.add_weight(\n            shape=(1,),\n            # 初期値が'ones'だとlog_gamma=1となり、gamma=e^1≈2.71からスタート\n            # 'zeros'だとlog_gamma=0となり、gamma=1からスタート。ここでは'zeros'を推奨\n            initializer=self.gamma_initializer,\n            regularizer=self.gamma_regularizer,\n            name='log_gamma',\n            trainable=True\n        )\n        \n        super(Conv2DRBF, self).build(input_shape)\n\n    def call(self, inputs):\n        # inputs: (B, H, W, C_in)\n        \n        # log_gammaから実際のgamma値を計算\n        gamma = tf.exp(self.log_gamma)\n\n        # 1. パッチの抽出 (Sliding Window)\n        ksizes = [1, self.kernel_size[0], self.kernel_size[1], 1]\n        strides = [1, self.strides[0], self.strides[1], 1]\n        rates = [1, 1, 1, 1] \n        \n        # patches shape: (B, H_out, W_out, kH * kW * C_in)\n        patches = tf.image.extract_patches(\n            images=inputs,\n            sizes=ksizes,\n            strides=strides,\n            rates=rates,\n            padding=self.padding\n        )\n\n        # パッチが平坦化された次元サイズ: C_flat\n        C_flat = tf.shape(patches)[-1]\n        B, H_out, W_out = tf.shape(patches)[0], tf.shape(patches)[1], tf.shape(patches)[2]\n        \n        # 2. 距離計算のための形状変更\n        \n        # パッチ: (B, H_out, W_out, 1, C_flat)\n        patches_for_dist = tf.reshape(patches, (B, H_out, W_out, 1, C_flat))\n\n        # ランドマーク: (1, 1, 1, F, C_flat)\n        kernel_flat = tf.reshape(self.kernel, (1, 1, 1, self.filters, C_flat))\n\n        # 3. ユークリッド距離の二乗計算: ||x - μ||^2\n        \n        # # (B, H_out, W_out, F, C_flat) から、最後の次元を reduce_sum\n        # sq_dist = tf.reduce_sum(tf.square(patches_for_dist - kernel_flat), axis=-1)\n        # # sq_dist shape: (B, H_out, W_out, F)\n        \n        # パッチのノルム二乗: ||x||^2\n        # (B, H_out, W_out, 1) - F次元にブロードキャストされる\n        patch_norm_sq = tf.reduce_sum(tf.square(patches_for_dist), axis=-1)\n        #print('patch_norm_sq.shape >>>', patch_norm_sq.shape)\n\n        # ランドマークのノルム二乗: ||μ||^2\n        # (1, 1, 1, F) - B*H_out*W_out次元にブロードキャストされる\n        kernel_norm_sq = tf.reduce_sum(tf.square(kernel_flat), axis=-1)\n        #print('kernel_norm_sq.shape >>>', kernel_norm_sq.shape)\n\n        # 内積: x・μ\n        # (B, H_out, W_out, F)\n        # inner_product = tf.reduce_sum(patches_for_dist * kernel_flat, axis=-1)\n        inner_product = tf.tensordot(tf.reshape(patches, (B, H_out, W_out, C_flat)), tf.reshape(self.kernel, (self.filters, C_flat)), axes=[[3], [1]])\n        #print('inner_product.shape >>>', inner_product.shape)\n        \n        # 組み合わせ: ||x||^2 + ||μ||^2 - 2(x・μ)\n        sq_dist = patch_norm_sq + kernel_norm_sq - 2.0 * inner_product\n        # sq_dist shape: (B, H_out, W_out, F)\n\n        # 4. RBFカーネル関数の適用: exp(-gamma * ||x - μ||^2)\n        # tf.exp()を使用してRBFカーネルを計算\n        rbf_output = tf.exp(-gamma * sq_dist)\n        # rbf_output shape: (B, H_out, W_out, F)\n\n        return rbf_output\n\n    def compute_output_shape(self, input_shape):\n        # KerasのConv2Dと同様のロジックで出力形状を計算\n        H_in = input_shape[1]\n        W_in = input_shape[2]\n        \n        if self.padding == 'VALID':\n            H_out = (H_in - self.kernel_size[0]) // self.strides[0] + 1\n            W_out = (W_in - self.kernel_size[1]) // self.strides[1] + 1\n        elif self.padding == 'SAME':\n            H_out = (H_in + self.strides[0] - 1) // self.strides[0]\n            W_out = (W_in + self.strides[1] - 1) // self.strides[1]\n        else:\n            raise ValueError(f\"Unknown padding: {self.padding}\")\n            \n        return (input_shape[0], H_out, W_out, self.filters)\n\n    def get_config(self):\n        # モデル保存・読み込みのためにconfigを定義\n        config = super(Conv2DRBF, self).get_config()\n        config.update({\n            'filters': self.filters,\n            'kernel_size': self.kernel_size,\n            'strides': self.strides,\n            'padding': self.padding.lower(),\n            'gamma_initializer': initializers.serialize(self.gamma_initializer),\n            'gamma_regularizer': initializers.serialize(self.gamma_regularizer),\n            # 'gamma_constraint'はlog_gammaの導入により不要になったため削除\n        })\n        return config","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.248360Z","iopub.execute_input":"2025-12-25T13:28:37.248710Z","iopub.status.idle":"2025-12-25T13:28:37.272074Z","shell.execute_reply.started":"2025-12-25T13:28:37.248680Z","shell.execute_reply":"2025-12-25T13:28:37.271084Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inputs = Input(shape=(32, 32, 3))\nx = Conv2DRBF_patch(\n            filters=16, \n            kernel_size=(3, 3), \n            strides=(1, 1), \n            padding='same',\n            kernel_initializer=initializers.RandomUniform(minval=0.4, maxval=0.6, seed=10001),\n            name='rbf_conv_patch'\n        )(inputs)\nmodel_test = Model(inputs=inputs, outputs=x, name=f'Conv2DRBF_patch')\nmodel_test.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nmodel_test.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.273096Z","iopub.execute_input":"2025-12-25T13:28:37.273419Z","iopub.status.idle":"2025-12-25T13:28:37.371424Z","shell.execute_reply.started":"2025-12-25T13:28:37.273389Z","shell.execute_reply":"2025-12-25T13:28:37.370526Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ロジック②のための出力確定用\ninputs = Input(shape=(32, 32, 3))\nx = Conv2DRBF(\n            filters=16,\n            #rbf_target=0.1,\n            kernel_size=(3, 3), \n            strides=(1, 1), \n            padding='same',\n            kernel_initializer=initializers.RandomUniform(minval=0.4, maxval=0.6, seed=10001),\n            name='rbf_conv'\n        )(inputs)\nmodel_test = Model(inputs=inputs, outputs=x, name=f'Conv2DRBF_patch')\nmodel_test.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nmodel_test.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.372747Z","iopub.execute_input":"2025-12-25T13:28:37.373075Z","iopub.status.idle":"2025-12-25T13:28:37.403010Z","shell.execute_reply.started":"2025-12-25T13:28:37.373048Z","shell.execute_reply":"2025-12-25T13:28:37.402395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"rbf_conv = model_test.get_layer('rbf_conv')\nrbf_conv.get_weights()[1], np.log(-np.log(0.1)/(3*3*3)), np.exp(rbf_conv.get_weights()[1]), -np.log(0.1)/(3*3*3), ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.403852Z","iopub.execute_input":"2025-12-25T13:28:37.404130Z","iopub.status.idle":"2025-12-25T13:28:37.415208Z","shell.execute_reply.started":"2025-12-25T13:28:37.404108Z","shell.execute_reply":"2025-12-25T13:28:37.414425Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ロジック②のための出力確定用\ninputs = Input(shape=(32, 32, 3))\nx = Conv2DRBF(\n            filters=16, \n            kernel_size=(3, 3), \n            strides=(1, 1), \n            padding='same',\n            kernel_initializer=initializers.RandomUniform(minval=0.4, maxval=0.6, seed=10001),\n            name='rbf_conv'\n        )(inputs)\nmodel_test = Model(inputs=inputs, outputs=x, name=f'Conv2DRBF_patch')\nmodel_test.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nmodel_test.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.416004Z","iopub.execute_input":"2025-12-25T13:28:37.416314Z","iopub.status.idle":"2025-12-25T13:28:37.449307Z","shell.execute_reply.started":"2025-12-25T13:28:37.416263Z","shell.execute_reply":"2025-12-25T13:28:37.448590Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"rbf_conv = model_test.get_layer('rbf_conv')\nrbf_conv.get_weights()[1], np.log(-np.log(0.01)/(3*3*3)), np.exp(rbf_conv.get_weights()[1]), -np.log(0.01)/(3*3*3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.450167Z","iopub.execute_input":"2025-12-25T13:28:37.450430Z","iopub.status.idle":"2025-12-25T13:28:37.458834Z","shell.execute_reply.started":"2025-12-25T13:28:37.450412Z","shell.execute_reply":"2025-12-25T13:28:37.458014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_tmp = model_test.predict(x_train[:5])\npred_tmp.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.459827Z","iopub.execute_input":"2025-12-25T13:28:37.460481Z","iopub.status.idle":"2025-12-25T13:28:37.670525Z","shell.execute_reply.started":"2025-12-25T13:28:37.460452Z","shell.execute_reply":"2025-12-25T13:28:37.669606Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_tmp[0,:,:,0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.671616Z","iopub.execute_input":"2025-12-25T13:28:37.671953Z","iopub.status.idle":"2025-12-25T13:28:37.678220Z","shell.execute_reply.started":"2025-12-25T13:28:37.671926Z","shell.execute_reply":"2025-12-25T13:28:37.677506Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"```\narray([[0.0000000e+00, 0.0000000e+00, 0.0000000e+00, ..., 2.1169656e-32,\n        1.5532900e-32, 0.0000000e+00],\n       [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, ..., 6.0265011e-09,\n        4.5376872e-10, 1.8092175e-32],\n       [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, ..., 1.6769408e-12,\n        1.2224111e-14, 5.3832547e-36],\n       ...,\n       [2.2700840e-37, 1.6354445e-19, 3.0376850e-22, ..., 2.9154076e-18,\n        2.7575650e-28, 0.0000000e+00],\n       [9.9139967e-33, 6.3302748e-13, 1.1412688e-16, ..., 6.3013600e-14,\n        2.1247140e-19, 0.0000000e+00],\n       [0.0000000e+00, 1.9726915e-35, 7.7242789e-38, ..., 8.0902561e-37,\n        0.0000000e+00, 0.0000000e+00]], dtype=float32)\n```","metadata":{}},{"cell_type":"code","source":"pred_tmp[4,:,:,0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.679239Z","iopub.execute_input":"2025-12-25T13:28:37.679570Z","iopub.status.idle":"2025-12-25T13:28:37.693166Z","shell.execute_reply.started":"2025-12-25T13:28:37.679544Z","shell.execute_reply":"2025-12-25T13:28:37.692502Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"```\narray([[0.0000000e+00, 1.1824578e-37, 1.8343552e-38, ..., 0.0000000e+00,\n        2.7678475e-38, 0.0000000e+00],\n       [7.8956813e-35, 5.0660190e-14, 2.8089554e-14, ..., 8.4325042e-18,\n        3.9024241e-17, 3.4462602e-37],\n       [5.1693958e-33, 8.0586371e-11, 4.3569481e-10, ..., 1.7561913e-17,\n        1.0253279e-16, 7.8984446e-37],\n       ...,\n       [1.7020793e-34, 2.9708755e-13, 9.4201437e-13, ..., 1.5256531e-26,\n        3.0561479e-26, 0.0000000e+00],\n       [4.7863794e-35, 3.5058839e-14, 9.8011504e-14, ..., 8.4140086e-15,\n        3.6790910e-15, 2.4343777e-36],\n       [0.0000000e+00, 2.2774566e-37, 5.4866427e-37, ..., 9.0726923e-37,\n        8.9263788e-37, 0.0000000e+00]], dtype=float32)\n```","metadata":{}},{"cell_type":"code","source":"# # ----------------------------------------------------------------------\n# # 使用例\n# # ----------------------------------------------------------------------\n\n# # 議論に基づいたハイブリッドモデル構築例\n# def create_hybrid_model(input_shape=(32, 32, 3), num_classes=10):\n#     model = tf.keras.models.Sequential([\n#         # 1. 初段にConv2D-RBFを配置 (安定性が高く、計算コストも低い)\n#         Conv2DRBF(\n#             filters=16, \n#             kernel_size=(3, 3), \n#             strides=(1, 1), \n#             padding='same', \n#             name='rbf_conv_feature_extract'\n#         ),\n#         # RBFの出力は0-1なので、ReLUなどの活性化関数は不要\n        \n#         tf.keras.layers.MaxPooling2D((2, 2)), # 16x16x16\n        \n#         # 2. 後続は計算効率の良い標準Conv2Dで特徴を集約・抽象化\n#         tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same', name='conv2d_2'),\n#         tf.keras.layers.MaxPooling2D((2, 2)), # 8x8x32\n        \n#         tf.keras.layers.Flatten(),\n#         tf.keras.layers.Dense(128, activation='relu'),\n#         tf.keras.layers.Dense(num_classes, activation='softmax')\n#     ])\n#     return model\n\n# # モデルの確認\n# hybrid_model = create_hybrid_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.694133Z","iopub.execute_input":"2025-12-25T13:28:37.694417Z","iopub.status.idle":"2025-12-25T13:28:37.707797Z","shell.execute_reply.started":"2025-12-25T13:28:37.694397Z","shell.execute_reply":"2025-12-25T13:28:37.707023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 議論に基づいたハイブリッドモデル構築例\ndef create_hybrid_model(input_shape=(32, 32, 3), num_classes=10):\n    inputs = Input(shape=input_shape)\n    x = Conv2DRBF(\n            filters=16, \n            kernel_size=(3, 3), \n            strides=(1, 1), \n            padding='same',\n            kernel_initializer=initializers.RandomUniform(minval=0.4, maxval=0.6),\n            name='rbf_conv_feature_extract'\n        )(inputs)\n    x = tf.keras.layers.MaxPooling2D((2, 2))(x)\n\n    # 2. 後続は計算効率の良い標準Conv2Dで特徴を集約・抽象化\n    x = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same', name='conv2d_2')(x)\n    x = tf.keras.layers.MaxPooling2D((2, 2))(x)\n\n    x = tf.keras.layers.Flatten()(x)\n    x = tf.keras.layers.Dense(128, activation='relu')(x)\n    x = tf.keras.layers.Dense(num_classes, activation='softmax')(x)\n    model = Model(inputs=inputs, outputs=x, name=f'Conv2DRBF_hybrid')\n    return model\n\n# モデルの確認\nhybrid_model = create_hybrid_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.708848Z","iopub.execute_input":"2025-12-25T13:28:37.709172Z","iopub.status.idle":"2025-12-25T13:28:37.768102Z","shell.execute_reply.started":"2025-12-25T13:28:37.709143Z","shell.execute_reply":"2025-12-25T13:28:37.767434Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hybrid_model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nhybrid_model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.768959Z","iopub.execute_input":"2025-12-25T13:28:37.769195Z","iopub.status.idle":"2025-12-25T13:28:37.792192Z","shell.execute_reply.started":"2025-12-25T13:28:37.769176Z","shell.execute_reply":"2025-12-25T13:28:37.791542Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_model(hybrid_model, show_shapes=True, expand_nested=True, show_layer_names=True, dpi=70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.793170Z","iopub.execute_input":"2025-12-25T13:28:37.793510Z","iopub.status.idle":"2025-12-25T13:28:37.930218Z","shell.execute_reply.started":"2025-12-25T13:28:37.793484Z","shell.execute_reply":"2025-12-25T13:28:37.929264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = hybrid_model.predict(x_train[:5])\npred.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:37.931369Z","iopub.execute_input":"2025-12-25T13:28:37.932226Z","iopub.status.idle":"2025-12-25T13:28:38.110555Z","shell.execute_reply.started":"2025-12-25T13:28:37.932202Z","shell.execute_reply":"2025-12-25T13:28:38.109810Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.111351Z","iopub.execute_input":"2025-12-25T13:28:38.111594Z","iopub.status.idle":"2025-12-25T13:28:38.118525Z","shell.execute_reply.started":"2025-12-25T13:28:38.111576Z","shell.execute_reply":"2025-12-25T13:28:38.117781Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hybrid_model.layers","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.119415Z","iopub.execute_input":"2025-12-25T13:28:38.119736Z","iopub.status.idle":"2025-12-25T13:28:38.132748Z","shell.execute_reply.started":"2025-12-25T13:28:38.119715Z","shell.execute_reply":"2025-12-25T13:28:38.131559Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hybrid_model.layers[1].output","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.133793Z","iopub.execute_input":"2025-12-25T13:28:38.134109Z","iopub.status.idle":"2025-12-25T13:28:38.148626Z","shell.execute_reply.started":"2025-12-25T13:28:38.134089Z","shell.execute_reply":"2025-12-25T13:28:38.147925Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_test = Model(inputs=hybrid_model.input, outputs=hybrid_model.layers[1].output)\nmodel_test.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.149627Z","iopub.execute_input":"2025-12-25T13:28:38.149953Z","iopub.status.idle":"2025-12-25T13:28:38.175616Z","shell.execute_reply.started":"2025-12-25T13:28:38.149925Z","shell.execute_reply":"2025-12-25T13:28:38.174694Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_model(model_test, show_shapes=True, expand_nested=True, show_layer_names=True, dpi=70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.176427Z","iopub.execute_input":"2025-12-25T13:28:38.176654Z","iopub.status.idle":"2025-12-25T13:28:38.228806Z","shell.execute_reply.started":"2025-12-25T13:28:38.176636Z","shell.execute_reply":"2025-12-25T13:28:38.227800Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"rbf_conv_feature_extract = hybrid_model.get_layer('rbf_conv_feature_extract')\nrbf_conv_feature_extract","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.229779Z","iopub.execute_input":"2025-12-25T13:28:38.230029Z","iopub.status.idle":"2025-12-25T13:28:38.236212Z","shell.execute_reply.started":"2025-12-25T13:28:38.230010Z","shell.execute_reply":"2025-12-25T13:28:38.235542Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for ee in rbf_conv_feature_extract.weights:\n    print(ee.name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.237311Z","iopub.execute_input":"2025-12-25T13:28:38.237799Z","iopub.status.idle":"2025-12-25T13:28:38.252196Z","shell.execute_reply.started":"2025-12-25T13:28:38.237777Z","shell.execute_reply":"2025-12-25T13:28:38.251520Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"log_gamma = rbf_conv_feature_extract.get_weights()[1]\nnp.exp(log_gamma)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.253066Z","iopub.execute_input":"2025-12-25T13:28:38.253316Z","iopub.status.idle":"2025-12-25T13:28:38.270028Z","shell.execute_reply.started":"2025-12-25T13:28:38.253270Z","shell.execute_reply":"2025-12-25T13:28:38.269141Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"filters = rbf_conv_feature_extract.get_weights()[0]\nfilters.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.271049Z","iopub.execute_input":"2025-12-25T13:28:38.271310Z","iopub.status.idle":"2025-12-25T13:28:38.283115Z","shell.execute_reply.started":"2025-12-25T13:28:38.271263Z","shell.execute_reply":"2025-12-25T13:28:38.282348Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"filters.reshape(-1, filters.shape[-1]).shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.283990Z","iopub.execute_input":"2025-12-25T13:28:38.284564Z","iopub.status.idle":"2025-12-25T13:28:38.298477Z","shell.execute_reply.started":"2025-12-25T13:28:38.284534Z","shell.execute_reply":"2025-12-25T13:28:38.297572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tmp = pd.DataFrame(filters.reshape(-1, filters.shape[-1])[:,:3])\ndf_tmp.columns = [\"col1\", \"col2\", \"col3\"]\n# # df['cls'] = [str(ee) for ee in y] + ['Landmark']*wgt.shape[0]\n# # sns.lmplot(data=df, x=\"col1\", y=\"col2\", markers=['.', '.', 'o'], hue=\"cls\", fit_reg=False, height=6)\nsns.set_context('paper')\ng = sns.PairGrid(df_tmp, height=2.5)\ng.map_diag(plt.hist, edgecolor=\"w\")\ng.map_lower(scatter)\ng.map_upper(hexbin)\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:38.299539Z","iopub.execute_input":"2025-12-25T13:28:38.299908Z","iopub.status.idle":"2025-12-25T13:28:40.829662Z","shell.execute_reply.started":"2025-12-25T13:28:38.299874Z","shell.execute_reply":"2025-12-25T13:28:40.828721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_tmp = pd.DataFrame(filters.reshape(-1, filters.shape[-1])[:,13:16])\ndf_tmp.columns = [\"col1\", \"col2\", \"col3\"]\n# # df['cls'] = [str(ee) for ee in y] + ['Landmark']*wgt.shape[0]\n# # sns.lmplot(data=df, x=\"col1\", y=\"col2\", markers=['.', '.', 'o'], hue=\"cls\", fit_reg=False, height=6)\nsns.set_context('paper')\ng = sns.PairGrid(df_tmp, height=2.5)\ng.map_diag(plt.hist, edgecolor=\"w\")\ng.map_lower(scatter)\ng.map_upper(hexbin)\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:40.830780Z","iopub.execute_input":"2025-12-25T13:28:40.831522Z","iopub.status.idle":"2025-12-25T13:28:44.250576Z","shell.execute_reply.started":"2025-12-25T13:28:40.831491Z","shell.execute_reply":"2025-12-25T13:28:44.249740Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# ResNet","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import (\n    Input, Conv2D, BatchNormalization, Activation, \n    Add, GlobalAveragePooling2D, GlobalMaxPooling2D, Dense, Reshape, TimeDistributed, Lambda, concatenate\n)\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras import regularizers\nimport tensorflow.keras.backend as K","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.251577Z","iopub.execute_input":"2025-12-25T13:28:44.251868Z","iopub.status.idle":"2025-12-25T13:28:44.257922Z","shell.execute_reply.started":"2025-12-25T13:28:44.251838Z","shell.execute_reply":"2025-12-25T13:28:44.257120Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Hybrid_resnet_layer","metadata":{}},{"cell_type":"code","source":"rl = 0.005\n#rl = 0.008\nrbf_target = 0.1\nnum_epoch = 64\nstructure = 'S2B3'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.258749Z","iopub.execute_input":"2025-12-25T13:28:44.259005Z","iopub.status.idle":"2025-12-25T13:28:44.274937Z","shell.execute_reply.started":"2025-12-25T13:28:44.258987Z","shell.execute_reply":"2025-12-25T13:28:44.274207Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def Hybrid_resnet_layer(inputs,\n                      num_filters=16,\n                      kernel_size=3,\n                      strides=1,\n                      activation=None, # 'rbf'が指定されたらC-RBFに置き換え\n                      batch_normalization=False,\n                      conv_first=True,\n                      stage=None, res_block=None, unit=None):\n    \n    Cin = inputs.shape[-1]\n    # conv = Conv2D(num_filters,\n    #               kernel_size=kernel_size,\n    #               strides=strides,\n    #               padding='same',\n    #               kernel_initializer='he_normal',\n    #               kernel_regularizer=regularizers.l2(1e-4),\n    #               name=f'conv2d_{stage}_{res_block}_{unit}')\n    conv = Conv2DRBF(\n            filters=num_filters,\n            kernel_size=(kernel_size, kernel_size),\n            strides=(strides, strides), \n            padding='same', \n            # gamma_initializer=initializers.Constant(np.log(1 / (0.2**2))),\n            # gamma_initializer=initializers.Constant(np.log(-np.log(0.001) / 3)),\n            # gamma_initializer=initializers.Constant(np.log(-np.log(0.5) / 3)),\n            gamma_initializer=initializers.Constant(np.log(-np.log(rbf_target) / (kernel_size**2 * Cin))),\n            # rbf_target = 0.1,\n            kernel_initializer=initializers.RandomUniform(minval=0.4, maxval=0.6),\n            name=f'rbf_conv2d_{stage}_{res_block}_{unit}'\n        )\n    x = inputs\n    if conv_first:\n        # Conv-BN-Activation (ResNet V1 style: RBFは通常、Add()の前に入れる)\n        x = conv(x)\n        # RBF出力なのでBNもReLUも不要\n        # if batch_normalization:\n        #     x = BatchNormalization(name=f'bn_{stage}_{res_block}_{unit}')(x)\n        # if activation is not None:\n        #     x = Activation(activation, name=f'act_{stage}_{res_block}_{unit}')(x)\n    else:\n        # BN-Activation-Conv (ResNet V2 style: RBFはBNの後、Convの前に来る)\n        # if batch_normalization:\n        #     x = BatchNormalization(name=f'bn_{stage}_{res_block}_{unit}')(x)\n\n        # === 🎯 ここが 'relu' の置き換えポイント ===\n        if activation == 'rbf':\n            # 出力チャンネル数（ここでは入力チャンネル数）を使用\n            current_filters = K.int_shape(x)[-1] \n            #x = C_RBF_Transform_Block(x, name=f'rbf_act_{current_filters}', stage=stage, res_block=res_block, unit=unit)\n            x = CRBFActivation(name=f'rbf_act_{stage}_{res_block}_{unit}', num_landmarks=current_filters)(x)\n        elif activation is not None:\n            x = Activation(activation, name=f'act_{stage}_{res_block}_{unit}')(x)\n        \n        x = conv(x)\n    return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.275986Z","iopub.execute_input":"2025-12-25T13:28:44.276305Z","iopub.status.idle":"2025-12-25T13:28:44.291544Z","shell.execute_reply.started":"2025-12-25T13:28:44.276254Z","shell.execute_reply":"2025-12-25T13:28:44.290616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"### Hybrid_resnet_layer test\ninp = Input(shape=(8, 8, 32))\noup = Hybrid_resnet_layer(inp, num_filters=64)\nmodel_tmp = Model(inp, oup, name='tmp_m')\nmodel_tmp.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\nmodel_tmp.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.292370Z","iopub.execute_input":"2025-12-25T13:28:44.292583Z","iopub.status.idle":"2025-12-25T13:28:44.338084Z","shell.execute_reply.started":"2025-12-25T13:28:44.292567Z","shell.execute_reply":"2025-12-25T13:28:44.337404Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_model(model_tmp, show_shapes=True, expand_nested=True, show_layer_names=True, dpi=70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.338820Z","iopub.execute_input":"2025-12-25T13:28:44.339028Z","iopub.status.idle":"2025-12-25T13:28:44.388093Z","shell.execute_reply.started":"2025-12-25T13:28:44.339005Z","shell.execute_reply":"2025-12-25T13:28:44.387192Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ResNet20_C_RBF_Hybrid","metadata":{}},{"cell_type":"code","source":"def ResNet20_C_RBF_Hybrid(input_shape=(28, 28, 1), num_stages=3, depth=20, num_classes=10, activation='relu'):\n    \"\"\"\n    ResNet Version 2 (Bottleneck Block) Model builder。\n    RBF活性化をBottleneck Blockの2nd層(3x3 Convの前)に限定します。\n    \"\"\"\n    if (depth - 2) % 9 != 0:\n        raise ValueError('depth should be 9n+2 (eg 20, 38, 56, 110)')\n        \n    num_filters_in = 16\n    num_res_blocks = int((depth - 2) / 9)\n\n    inputs = Input(shape=input_shape, name='input')\n    # Initial Conv (v2 performs Conv2D with BN-ReLU on input)\n    # Stage 0の最初の層はBN-ReLU-Convの構造が特殊なので、そのままReLUを使用\n    x = Hybrid_resnet_layer(inputs=inputs,\n                            num_filters=num_filters_in,\n                            conv_first=True,\n                            activation=None, # 初期層はReLU固定\n                            stage=0, res_block=0, unit='init') # ここはConv-BN-ReLU\n\n    # Instantiate the stack of residual units\n    for stage in range(num_stages):\n        print(f'STAGE START : {stage+1} >>>', x.shape)\n        for res_block in range(num_res_blocks):\n            # --- Bottleneck Blockの特殊処理のための変数設定 ---\n            block_activation = activation \n            batch_normalization = True\n            strides = 1\n            \n            if stage == 0:\n                num_filters_out = num_filters_in * 4\n                if res_block == 0:  # first layer and first stage\n                    # 論文の構造では、最初のブロックのショートカットは非活性化\n                    block_activation = None  \n                    batch_normalization = False\n            else:\n                num_filters_out = num_filters_in * 2\n                if res_block == 0:  # first layer but not first stage\n                    strides = 2   # downsample\n\n            # Bottleneck Residual Unit (3 Conv Layers) - BN-RBF-Conv\n            \n            # 1st: 1x1 Conv (活性化を ReLU に固定。ただし、Noneの場合は維持)\n            # block_activation が None (ダウンサンプルの最初) の場合を除き、強制的に 'relu' に\n            activation_1st = 'relu' if block_activation == 'rbf' else block_activation \n\n            print('BLOCK START : x.shape >>>', x.shape)\n            y = Hybrid_resnet_layer(inputs=x,\n                                    num_filters=num_filters_in,\n                                    kernel_size=1,\n                                    strides=strides,\n                                    activation=None, # relu or None\n                                    batch_normalization=None,\n                                    conv_first=False,\n                                    stage=stage+1, res_block=res_block+1, unit='1st')\n            \n            # 2nd: 3x3 Conv\n            y = Hybrid_resnet_layer(inputs=y,\n                                    num_filters=num_filters_in,\n                                    activation=None,\n                                    conv_first=False,\n                                    stage=stage+1, res_block=res_block+1, unit='2nd')\n            print(f'y.shape stage={stage+1} res_block={res_block+1} unit={\"2nd\"} >>> ', y.shape)\n            \n            # 3rd: 1x1 Conv (活性化を ReLU に固定)\n            y = Hybrid_resnet_layer(inputs=y,\n                                    num_filters=num_filters_out,\n                                    kernel_size=1,\n                                    activation=None,\n                                    conv_first=False,\n                                    stage=stage+1, res_block=res_block+1, unit='3rd')\n            print(f'y.shape stage={stage+1} res_block={res_block+1} unit={\"2nd\"} >>> ', y.shape)\n            \n            # Shortcut Path\n            if res_block == 0:\n                # linear projection residual shortcut connection\n                x = Hybrid_resnet_layer(inputs=x,\n                                        num_filters=num_filters_out,\n                                        kernel_size=1,\n                                        strides=strides,\n                                        activation=None, # Shortcutは活性化なし\n                                        batch_normalization=False,\n                                        stage=stage+1, res_block=res_block+1, unit='sc')\n                print(f'x_sc.shape stage={stage+1} res_block={res_block+1} unit={\"sc\"} >>> ', x.shape)\n\n            x = Add(name=f'res_add_{stage+1}_{res_block+1}')([x, y]) # Addの後に活性化関数はない (V2の特徴)\n\n        num_filters_in = num_filters_out\n\n    # Add classifier on top.\n    # Final Stage (V2 final BN-ReLU before Pooling)\n    #x = BatchNormalization(name='final_bn')(x) # V2 final BN\n    #x = Activation('relu', name='final_relu')(x)   # V2 final ReLU\n    \n    # 分類ヘッド (AvgPoolとMaxPoolのConcatenateを使用)\n    x1 = GlobalMaxPooling2D(name='gmax_pool')(x)\n    x2 = GlobalAveragePooling2D(name='gavg_pool')(x)\n    x = concatenate([x1, x2], name='concat_pool')\n    \n    # 最後の活性化層はsigmoid\n    #x = Activation('sigmoid')(x) \n    x = Dense(num_classes, activation='softmax', name='predictions')(x) # 最終分類器はsoftmax\n\n    model = Model(inputs=inputs, outputs=x, name=f'resnet{depth}_{activation}_hybrid')\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.389212Z","iopub.execute_input":"2025-12-25T13:28:44.389499Z","iopub.status.idle":"2025-12-25T13:28:44.402441Z","shell.execute_reply.started":"2025-12-25T13:28:44.389477Z","shell.execute_reply":"2025-12-25T13:28:44.401695Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"THRESHOLD = 0.5\n\ndef f1_score_metric(y_true, y_pred):\n    \"\"\"\n    Kaggleでよく使用されるマクロF1スコアを計算するカスタムメトリック。\n    tf.is_nan を tf.math.is_nan に修正。\n    \"\"\"\n    \n    # y_predを閾値処理してバイナリ化\n    # K.clip(y_pred, 0, 1)は確率値を0〜1にクリップ\n    y_pred_thresh = K.cast(K.greater(K.clip(y_pred, 0, 1), THRESHOLD), K.floatx())\n    \n    # True Positives (TP), False Positives (FP), False Negatives (FN) を計算\n    # 各クラスごと (axis=0 はバッチ、axis=1 はクラス)\n    tp = K.sum(y_true * y_pred_thresh, axis=0)\n    fp = K.sum((1 - y_true) * y_pred_thresh, axis=0)\n    fn = K.sum(y_true * (1 - y_pred_thresh), axis=0)\n\n    # Precision (p) と Recall (r)\n    p = tp / (tp + fp + K.epsilon())\n    r = tp / (tp + fn + K.epsilon())\n\n    # F1 Score (各クラス)\n    f1_per_class = 2 * p * r / (p + r + K.epsilon())\n    \n    # NaNの処理: 0/0 (p=0, r=0の場合)を0に設定\n    # 【修正点】tf.is_nan を tf.math.is_nan に変更\n    f1_per_class = tf.where(tf.math.is_nan(f1_per_class), tf.zeros_like(f1_per_class), f1_per_class)\n    \n    # マクロF1スコア (クラス全体の平均)\n    return K.mean(f1_per_class)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.403353Z","iopub.execute_input":"2025-12-25T13:28:44.403589Z","iopub.status.idle":"2025-12-25T13:28:44.423395Z","shell.execute_reply.started":"2025-12-25T13:28:44.403570Z","shell.execute_reply":"2025-12-25T13:28:44.422455Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## モデルのインスタンス化と確認","metadata":{}},{"cell_type":"code","source":"# --- モデルのインスタンス化と確認 ---\n# model_baseline = ResNet20_C_RBF_Hybrid(input_shape=(32, 32, 3), num_stages=2, depth=20, num_classes=10, activation='relu')\nmodel_baseline = ResNet20_C_RBF_Hybrid(input_shape=(32, 32, 3), num_stages=2, depth=29, num_classes=10, activation='relu')\n# model_baseline = ResNet20_C_RBF_Hybrid(input_shape=(32, 32, 3), num_stages=3, depth=20, num_classes=10, activation='relu')\n# model_baseline = ResNet20_C_RBF_Hybrid(input_shape=(32, 32, 3), num_stages=3, depth=29, num_classes=10, activation='relu')\n# model_baseline = ResNet20_C_RBF_Hybrid(input_shape=(32, 32, 3), num_stages=4, depth=20, num_classes=10, activation='relu')\n\n# model_baseline.compile(optimizer=Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\n# model_baseline.compile(optimizer=Adam(learning_rate=0.002), loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nmodel_baseline.compile(optimizer=Adam(learning_rate=rl), loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\n\nmodel_baseline.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.432966Z","iopub.execute_input":"2025-12-25T13:28:44.433588Z","iopub.status.idle":"2025-12-25T13:28:44.642556Z","shell.execute_reply.started":"2025-12-25T13:28:44.433561Z","shell.execute_reply":"2025-12-25T13:28:44.641613Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_model(model_baseline, show_shapes=True, expand_nested=True, show_layer_names=True, dpi=70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.643365Z","iopub.execute_input":"2025-12-25T13:28:44.643611Z","iopub.status.idle":"2025-12-25T13:28:44.869269Z","shell.execute_reply.started":"2025-12-25T13:28:44.643593Z","shell.execute_reply":"2025-12-25T13:28:44.868330Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_baseline.predict(x_train[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:44.870226Z","iopub.execute_input":"2025-12-25T13:28:44.870522Z","iopub.status.idle":"2025-12-25T13:28:45.998756Z","shell.execute_reply.started":"2025-12-25T13:28:44.870495Z","shell.execute_reply":"2025-12-25T13:28:45.997532Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# モデルのウエイト保存確認\nfile_name = f'{structure}_rl{rl}_rbft{rbf_target}_epoch{num_epoch}_final.weights.h5'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:45.999799Z","iopub.execute_input":"2025-12-25T13:28:46.000133Z","iopub.status.idle":"2025-12-25T13:28:46.004557Z","shell.execute_reply.started":"2025-12-25T13:28:46.000108Z","shell.execute_reply":"2025-12-25T13:28:46.003654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_baseline.layers","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.006062Z","iopub.execute_input":"2025-12-25T13:28:46.006580Z","iopub.status.idle":"2025-12-25T13:28:46.025151Z","shell.execute_reply.started":"2025-12-25T13:28:46.006551Z","shell.execute_reply":"2025-12-25T13:28:46.024311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import h5py\n\ndef save_custom_weights(model, filepath):\n    \"\"\"\n    モデルのカスタムレイヤー名と重みを対応付けてHDF5ファイルに保存する。\n    \"\"\"\n    weights_map = {}\n    for layer in model.layers:\n        # 重みを持つレイヤーのみを対象とする (Conv2DRBF, Denseなど)\n        if layer.get_weights():\n            layer_name = layer.name\n            weights = layer.get_weights()\n            weights_map[layer_name] = weights\n\n    with h5py.File(filepath, 'w') as f:\n        # メタデータを保存するルートグループ\n        weights_group = f.create_group('custom_weights')\n\n        for layer_name, weights in weights_map.items():\n            layer_group = weights_group.create_group(layer_name)\n            \n            # 各レイヤーの複数の重み (μ, γ, biasなど) を連番で保存\n            for i, w in enumerate(weights):\n                layer_group.create_dataset(str(i), data=w)\n\n    print(f\"✅ カスタム重みマップを {filepath} に保存しました。\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.026158Z","iopub.execute_input":"2025-12-25T13:28:46.026493Z","iopub.status.idle":"2025-12-25T13:28:46.042937Z","shell.execute_reply.started":"2025-12-25T13:28:46.026464Z","shell.execute_reply":"2025-12-25T13:28:46.042016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# save_custom_weights(model_baseline, file_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.043929Z","iopub.execute_input":"2025-12-25T13:28:46.044171Z","iopub.status.idle":"2025-12-25T13:28:46.062474Z","shell.execute_reply.started":"2025-12-25T13:28:46.044152Z","shell.execute_reply":"2025-12-25T13:28:46.061543Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_custom_weights(model, filepath):\n    \"\"\"\n    HDF5ファイルからカスタム名に基づいて重みをロードし、モデルにセットする。\n    \"\"\"\n    weights_map = {}\n    \n    with h5py.File(filepath, 'r') as f:\n        weights_group = f['custom_weights']\n        \n        for layer_name in weights_group.keys():\n            layer_group = weights_group[layer_name]\n            weights = []\n            \n            # 保存されている重みを全てリストとして取得\n            i = 0\n            while str(i) in layer_group:\n                weights.append(np.array(layer_group[str(i)]))\n                i += 1\n                \n            weights_map[layer_name] = weights\n\n    # モデルに重みをセット\n    transfer_count = 0\n    for layer in model.layers:\n        layer_name = layer.name\n        \n        if layer_name in weights_map:\n            weights_to_transfer = weights_map[layer_name]\n            \n            try:\n                layer.set_weights(weights_to_transfer)\n                transfer_count += 1\n            except ValueError as e:\n                # 重みの形状が異なる場合 (通常は発生しないはず)\n                print(f\"⚠️ 警告: 重み形状が一致しないため {layer_name} の転送をスキップしました。エラー: {e}\")\n        \n    print(f\"✅ 合計 {transfer_count} 個のレイヤーの重みを {filepath} からロードしました。\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.063607Z","iopub.execute_input":"2025-12-25T13:28:46.064263Z","iopub.status.idle":"2025-12-25T13:28:46.079243Z","shell.execute_reply.started":"2025-12-25T13:28:46.064230Z","shell.execute_reply":"2025-12-25T13:28:46.078334Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 一番最初のConv2dRBF\nrbf_conv_feature_extract = model_baseline.get_layer('rbf_conv2d_0_0_init')\nrbf_conv_feature_extract","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.080329Z","iopub.execute_input":"2025-12-25T13:28:46.081142Z","iopub.status.idle":"2025-12-25T13:28:46.100227Z","shell.execute_reply.started":"2025-12-25T13:28:46.081120Z","shell.execute_reply":"2025-12-25T13:28:46.099298Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"log_gamma = rbf_conv_feature_extract.get_weights()[1]\nnp.exp(log_gamma)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.101222Z","iopub.execute_input":"2025-12-25T13:28:46.101526Z","iopub.status.idle":"2025-12-25T13:28:46.119352Z","shell.execute_reply.started":"2025-12-25T13:28:46.101504Z","shell.execute_reply":"2025-12-25T13:28:46.118551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''\npredictしてみる\n10分類の確率が0.1で同じなら、勾配が消失している可能性がある\n\n最後のpredictionsレイヤーへの入力が０。\n入力が０であればdenseのパラメータがどのような値であっても、\nバイアスしか出力されないので、10分類の値が同じになり、softmaxで0.1となる\n'''\nmodel_baseline.predict(x_train[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:28:46.120082Z","iopub.execute_input":"2025-12-25T13:28:46.120333Z","iopub.status.idle":"2025-12-25T13:28:46.252712Z","shell.execute_reply.started":"2025-12-25T13:28:46.120304Z","shell.execute_reply":"2025-12-25T13:28:46.251988Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## adjust_rbf_weights","metadata":{}},{"cell_type":"code","source":"def adjust_rbf_weights(model, x_sample, rbf_target=0.5, mode='avg', bins=19):\n    \"\"\"\n    RBF層の出力統計量が rbf_target になるように gamma を自動調整する。\n    \n    Args:\n        model: 対象のKerasモデル\n        x_sample: 統計計算用のサンプルデータ (例: x_train[:1000])\n        rbf_target: 統計量として目指すRBF出力値 (デフォルト: 0.5)\n        mode: 'avg' (平均), 'median' (中央値), 'mode' (最頻値)\n        bins: mode='mode' の場合のヒストグラム分割数\n    \"\"\"\n    print(f\"--- Adjusting RBF weights (target: {rbf_target}, mode: {mode}) ---\")\n    \n    # モデル内のConv2dRBF層（またはRBF層）を抽出\n    # 層の名前やクラス名でフィルタリングしてください\n    rbf_layers = [l for l in model.layers if 'rbf_conv2d' in l.name.lower()]\n    print('len(rbf_layers) >>>', len(rbf_layers))\n    \n    if not rbf_layers:\n        print(\"No RBF layers found.\")\n        return\n\n    for i, layer in enumerate(rbf_layers):\n        print(layer.name)\n        # 中間出力を取得するためのサブモデルを作成\n        intermediate_model = tf.keras.Model(inputs=model.input, outputs=layer.output)\n        \n        # RBF層の出力を計算 (ガウス関数適用後の 0~1 の値)\n        # 構造によっては、RBF計算直前の「距離」が必要な場合がありますが、\n        # ここでは「現在の出力」から逆算するロジックとします。\n        out = intermediate_model.predict(x_sample, verbose=0)\n        \n        # 統計量の算出\n        if mode == 'avg':\n            current_val = np.mean(out)\n        elif mode == 'median':\n            current_val = np.median(out)\n        elif mode == 'mode':\n            counts, bin_edges = np.histogram(out, bins=bins)\n            current_val = bin_edges[np.argmax(counts) + 1] # 頻度最大のbinの中央付近\n        \n        # 1.0 または 0.0 への張り付きを回避するための安全策\n        current_val = np.clip(current_val, 1e-7, 1.0 - 1e-7)\n        print(f'current_val : {mode} - {current_val}')\n        \n        # ガウス関数 y = exp(-gamma * d^2) の逆算\n        # log(y) = -gamma * d^2  =>  d^2 = -log(y) / gamma_old\n        # 新しい gamma_new = -log(target) / d^2\n        # => gamma_new = gamma_old * (log(target) / log(current_val))\n        \n        weights = layer.get_weights()\n        # 重みの並びが [kernel, gamma] または [gamma] の場合を想定\n        # ※層の実装に合わせてインデックスを調整してください\n        gamma_index = -1 \n        old_gamma = np.exp(weights[gamma_index])\n        \n        # 新しいgammaの計算\n        gamma_adjustment = np.log(rbf_target) / np.log(current_val)\n        new_gamma = old_gamma * gamma_adjustment\n        \n        # 重みの更新\n        weights[gamma_index] = np.log(new_gamma)\n        layer.set_weights(weights)\n        \n        print(f\"Layer {i} ({layer.name}): {mode}={current_val:.4f} -> target {rbf_target}. Gamma updated. {old_gamma} -> {new_gamma}\")\n\n    print(\"--- Adjustment completed ---\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:33:45.589138Z","iopub.execute_input":"2025-12-25T13:33:45.589616Z","iopub.status.idle":"2025-12-25T13:33:45.601829Z","shell.execute_reply.started":"2025-12-25T13:33:45.589585Z","shell.execute_reply":"2025-12-25T13:33:45.600505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"SAMPLE_SIZE = 10000\nadjust_rbf_weights(model_baseline, x_train[:SAMPLE_SIZE], rbf_target=rbf_target, mode='median', bins=19)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:33:49.670132Z","iopub.execute_input":"2025-12-25T13:33:49.671345Z","iopub.status.idle":"2025-12-25T13:34:24.874324Z","shell.execute_reply.started":"2025-12-25T13:33:49.671300Z","shell.execute_reply":"2025-12-25T13:34:24.873446Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## model_test2","metadata":{}},{"cell_type":"code","source":"model_test = Model(inputs=model_baseline.input, outputs=model_baseline.layers[1].output)\nmodel_test.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy', f1_score_metric])\nmodel_test.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:30:27.612650Z","iopub.execute_input":"2025-12-25T13:30:27.613030Z","iopub.status.idle":"2025-12-25T13:30:27.636462Z","shell.execute_reply.started":"2025-12-25T13:30:27.613007Z","shell.execute_reply":"2025-12-25T13:30:27.635643Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = model_test.predict(x_train[:100])\npred.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:30:29.181747Z","iopub.execute_input":"2025-12-25T13:30:29.182426Z","iopub.status.idle":"2025-12-25T13:30:29.452101Z","shell.execute_reply.started":"2025-12-25T13:30:29.182400Z","shell.execute_reply":"2025-12-25T13:30:29.451242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,0]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:30:31.036503Z","iopub.execute_input":"2025-12-25T13:30:31.036829Z","iopub.status.idle":"2025-12-25T13:30:42.212342Z","shell.execute_reply.started":"2025-12-25T13:30:31.036806Z","shell.execute_reply":"2025-12-25T13:30:42.211150Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,1]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:30:42.214545Z","iopub.execute_input":"2025-12-25T13:30:42.215101Z","iopub.status.idle":"2025-12-25T13:30:53.077466Z","shell.execute_reply.started":"2025-12-25T13:30:42.215067Z","shell.execute_reply":"2025-12-25T13:30:53.075927Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,2]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:30:53.078760Z","iopub.execute_input":"2025-12-25T13:30:53.079650Z","iopub.status.idle":"2025-12-25T13:31:02.976808Z","shell.execute_reply.started":"2025-12-25T13:30:53.079613Z","shell.execute_reply":"2025-12-25T13:31:02.975707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,15]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:31:02.978462Z","iopub.execute_input":"2025-12-25T13:31:02.978980Z","iopub.status.idle":"2025-12-25T13:31:14.072472Z","shell.execute_reply.started":"2025-12-25T13:31:02.978947Z","shell.execute_reply":"2025-12-25T13:31:14.071457Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"%%time\nhst = model_baseline.fit(x_train, y_cat_train, batch_size=512,\n                         #validation_data=(x_val, y_cat_val),\n                         #epochs=2,\n                         epochs=num_epoch,\n                         verbose=2,\n                         #callbacks=callbacks,\n                         validation_split=0.2\n                        )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-09T15:21:19.408155Z","iopub.execute_input":"2025-12-09T15:21:19.408411Z","iopub.status.idle":"2025-12-09T15:22:43.784144Z","shell.execute_reply.started":"2025-12-09T15:21:19.408393Z","shell.execute_reply":"2025-12-09T15:22:43.78345Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(file_name)\nsave_custom_weights(model_baseline, file_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:17.308871Z","iopub.execute_input":"2025-12-25T13:36:17.309576Z","iopub.status.idle":"2025-12-25T13:36:17.358740Z","shell.execute_reply.started":"2025-12-25T13:36:17.309541Z","shell.execute_reply":"2025-12-25T13:36:17.357715Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hst_history = hst.history\nfig, ax = plt.subplots(1, 3, figsize=(20,5))\nax[0].set_title('loss')\nax[0].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"loss\"], label=\"Train loss\")\nax[0].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"val_loss\"], label=\"val loss\")\nax[1].set_title('acc')\nax[1].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"categorical_accuracy\"], label=\"categorical_accuracy\")\nax[1].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"val_categorical_accuracy\"], label=\"val categorical_accuracy\")\nax[2].set_title('f1_score')\nax[2].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"f1_score_metric\"], label=\"f1 score\")\nax[2].plot(list(range(len(hst_history[\"loss\"]))), hst_history[\"val_f1_score_metric\"], label=\"val f1 score\")\nax[0].legend()\nax[1].legend()\nax[2].legend()\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T03:49:00.200416Z","iopub.execute_input":"2025-12-08T03:49:00.200676Z","iopub.status.idle":"2025-12-08T03:49:00.96197Z","shell.execute_reply.started":"2025-12-08T03:49:00.200659Z","shell.execute_reply":"2025-12-08T03:49:00.961406Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"log_gamma = rbf_conv_feature_extract.get_weights()[1]\nnp.exp(log_gamma)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:21.841906Z","iopub.execute_input":"2025-12-25T13:36:21.842839Z","iopub.status.idle":"2025-12-25T13:36:21.849953Z","shell.execute_reply.started":"2025-12-25T13:36:21.842806Z","shell.execute_reply":"2025-12-25T13:36:21.849003Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = model_test.predict(x_train[:100])\npred.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:22.151415Z","iopub.execute_input":"2025-12-25T13:36:22.151721Z","iopub.status.idle":"2025-12-25T13:36:22.295810Z","shell.execute_reply.started":"2025-12-25T13:36:22.151699Z","shell.execute_reply":"2025-12-25T13:36:22.294983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,0]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:24.037413Z","iopub.execute_input":"2025-12-25T13:36:24.038358Z","iopub.status.idle":"2025-12-25T13:36:35.062793Z","shell.execute_reply.started":"2025-12-25T13:36:24.038322Z","shell.execute_reply":"2025-12-25T13:36:35.061584Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,1]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:35.064848Z","iopub.execute_input":"2025-12-25T13:36:35.065217Z","iopub.status.idle":"2025-12-25T13:36:45.088404Z","shell.execute_reply.started":"2025-12-25T13:36:35.065186Z","shell.execute_reply":"2025-12-25T13:36:45.087383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,2]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:45.089617Z","iopub.execute_input":"2025-12-25T13:36:45.090016Z","iopub.status.idle":"2025-12-25T13:36:56.033482Z","shell.execute_reply.started":"2025-12-25T13:36:45.089979Z","shell.execute_reply":"2025-12-25T13:36:56.032388Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nrows=10\nncols=10\nfig, subs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15, 10))\n\nfor ii in range(nrows):\n    for jj in range(ncols):\n        iplt = subs[ii, jj]\n        img_array = pred[ii*ncols + jj,:,:,15]\n        iplt.imshow(img_array)\n\nsave_img()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-25T13:36:56.035639Z","iopub.execute_input":"2025-12-25T13:36:56.036088Z","iopub.status.idle":"2025-12-25T13:37:06.994350Z","shell.execute_reply.started":"2025-12-25T13:36:56.036057Z","shell.execute_reply":"2025-12-25T13:37:06.993333Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 予測結果をKaggle CIFAR-10の提出ファイル形式に変換し、表示します。","metadata":{}},{"cell_type":"code","source":"predictions = model_baseline.predict(x_test, verbose=1)\npredictions.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T03:49:43.295162Z","iopub.execute_input":"2025-12-08T03:49:43.296094Z","iopub.status.idle":"2025-12-08T03:50:45.065847Z","shell.execute_reply.started":"2025-12-08T03:49:43.296049Z","shell.execute_reply":"2025-12-08T03:50:45.065139Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 予測されたクラス (最も高い確率を持つインデックス)\npredicted_classes = np.argmax(predictions, axis=1)\npredicted_classes_name = [id_key[ee] for ee in predicted_classes]\n\nsubmission_file = sampleSubmission.copy()\nsubmission_file['label'] = predicted_classes_name\nsubmission_file","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T03:50:45.067159Z","iopub.execute_input":"2025-12-08T03:50:45.067465Z","iopub.status.idle":"2025-12-08T03:50:45.137032Z","shell.execute_reply.started":"2025-12-08T03:50:45.067447Z","shell.execute_reply":"2025-12-08T03:50:45.136356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_file.to_csv('submission.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T03:50:45.137904Z","iopub.execute_input":"2025-12-08T03:50:45.138159Z","iopub.status.idle":"2025-12-08T03:50:45.361721Z","shell.execute_reply.started":"2025-12-08T03:50:45.138126Z","shell.execute_reply":"2025-12-08T03:50:45.361123Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def create_submission_file(predictions):\n#     \"\"\"\n#     予測結果をKaggle Digit Recognizerの提出ファイル形式に変換し、表示します。\n#     \"\"\"\n#     # 予測されたクラス (最も高い確率を持つインデックス)\n#     predicted_classes = np.argmax(predictions, axis=1)\n    \n#     # Kaggle提出形式: ImageId,Label\n#     # ImageId は 1 から始まる\n#     image_ids = np.arange(1, len(predicted_classes) + 1)\n    \n#     # CSV形式の文字列を構築\n#     submission_content = \"ImageId,Label\\n\"\n#     for img_id, label in zip(image_ids, predicted_classes):\n#         submission_content += f\"{img_id},{label}\\n\"\n        \n#     # ファイルとして出力\n#     with open(\"submission.csv\", \"w\") as f:\n#         f.write(submission_content)\n        \n#     # 最初と最後の数行を表示\n#     print(\"\\n--- Submission File Preview (Kaggle Format) ---\")\n#     print(submission_content.split('\\n')[0])\n#     for line in submission_content.split('\\n')[1:6]:\n#         print(line)\n#     print(\"...\")\n#     for line in submission_content.split('\\n')[-6:-1]:\n#         print(line)\n#     print(f\"\\nTotal predictions generated: {len(predicted_classes)}\")\n#     print(\"\\n✅ Submission file 'submission.csv' generated for download.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T00:45:09.170059Z","iopub.execute_input":"2025-11-30T00:45:09.170325Z","iopub.status.idle":"2025-11-30T00:45:09.174189Z","shell.execute_reply.started":"2025-11-30T00:45:09.170299Z","shell.execute_reply":"2025-11-30T00:45:09.173651Z"}},"outputs":[],"execution_count":null}]}