{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":30587,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Phần 1: Nhập các thư viện cần thiết\n------","metadata":{"_uuid":"ebd546a2-326f-4a93-9042-31cb470d1cc4","_cell_guid":"fe85bd07-ce02-43ce-933f-2d24429c163b","trusted":true}},{"cell_type":"markdown","source":"Cơ sở dữ liệu MNIST (Modified National Institute of Standards and Technology) là một cơ sở dữ liệu lớn chứa các chữ số viết tay thường được sử dụng để huấn luyện các hệ thống xử lý ảnh khác nhau. Khi các kỹ thuật học máy mới xuất hiện, MNIST vẫn là một nguồn tài nguyên đáng tin cậy cho các nhà nghiên cứu và người học.\n\nCác hình ảnh đen trắng gốc đã được chuẩn hóa để vừa với một hộp giới hạn 28x28 pixel và được làm mịn, từ đó đã giới thiệu các mức xám. Cơ sở dữ liệu MNIST gốc chứa 60.000 hình ảnh huấn luyện và 10.000 hình ảnh kiểm tra, nhưng trong cuộc thi này, chúng ta được cung cấp 42.000 hình ảnh huấn luyện (70%) và 18.000 hình ảnh kiểm tra (30%).\n\nCác kỹ thuật tiên tiến nhất để tiếp cận bất kỳ vấn đề Phân loại Ảnh nào thường dựa vào Mạng Nơ-ron Tích chập. Loại kiến trúc này rất tốt trong việc rút trích các mẫu từ hình ảnh. Tuy nhiên, vì MNIST là một vấn đề đơn giản, trong sổ tay này, chúng ta sẽ áp dụng các thuật toán Học máy đơn giản (và sẽ đạt được độ chính xác khá!).\n\nĐầu tiên, chúng ta sẽ thực hiện một Phân tích thành phần chính để giảm chiều dữ liệu (từ 784 giá trị pixel xuống còn 10 thành phần chính). Sau đó, chúng ta sẽ chạy thuật toán yêu thích của chúng ta: K-Nearest Neighbors. Kết hợp này đạt được Độ chính xác Kiểm tra là 0.9271, đó là một kết quả đáng chú ý !!!\n\nBảng nội dung:\n🔎 Đọc & Khám phá Dữ liệu 🔍:\n- Kiểm tra xem có giá trị thiếu không.\n- Kiểm tra phạm vi của các giá trị pixel.\n- Trực quan hóa dữ liệu (Hình ảnh).\n- Kiểm tra xem mục tiêu có cân bằng không.\n\n🔶 PCA 🔶:\n- Giới thiệu thuật toán PCA.\n- Tiền xử lý (tỉ lệ) dữ liệu.\n- Thực hiện thuật toán PCA bằng thư viện Sklearn.\n- Nhúng các mô-đun vào một Ống đường Sklearn.\n- Vẽ biểu đồ phương sai được giải thích của các thành phần.\n- Trực quan hóa hai chiều của dữ liệu bằng seaborn.\n- Trực quan hóa ba chiều động của dữ liệu bằng plotly.\n- Trực quan hóa biến đổi nghịch đảo.\n- Kiểm tra xem các thành phần có không tương quan không.\n\n🔶 Bộ phân loại KNN 🔶:\n- Xây dựng một Bộ phân loại KNN sử dụng Sklearn.\n- Sử dụng kỹ thuật PCA như một bộ trích chọn đặc trưng cho KNN.\n- Chạy một Lưới tìm kiếm chéo để tối ưu hóa các siêu tham số n_neighbors.\n- So sánh các chỉ số đo huấn luyện và xác thực để kiểm tra việc quá mức (overfitting).\n- Vẽ ma trận nhầm lẫn.\n- Tính toán Báo cáo Phân loại.","metadata":{}},{"cell_type":"code","source":"## NHẬP CÁC THƯ VIỆN PYTHON CẦN THIẾT\n\n# Đọc & Khám phá Dữ liệu\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.preprocessing import MinMaxScaler\n\n# thuật toán Principal Component Analysis (PCA)\nfrom sklearn.decomposition import PCA\nfrom sklearn.pipeline import Pipeline\nimport plotly.express as px\n\n# thuật toán -Nearest Neighbor Classifier (KNN)\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn.metrics import classification_report, \\\n    confusion_matrix, ConfusionMatrixDisplay \n\n# VHT\nfrom scipy.ndimage import rotate\n# Mô-đun scipy.ndimage là một phần của thư viện scipy trong Python, cung cấp các công cụ để xử lý và thao tác trên hình ảnh nhiều chiều. Trong trường hợp này, rotate là một hàm trong mô-đun này được sử dụng để xoay hình ảnh.\n\n","metadata":{"_uuid":"c9f6edfd-588d-4af2-97d8-1073e4883692","_cell_guid":"8d8d769c-d2a0-4558-b63f-86352b4bafb8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:47.760347Z","iopub.execute_input":"2024-06-11T18:05:47.760900Z","iopub.status.idle":"2024-06-11T18:05:47.770595Z","shell.execute_reply.started":"2024-06-11T18:05:47.760850Z","shell.execute_reply":"2024-06-11T18:05:47.768632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Hàm này nhận ba đối số: Narray1d là một mảng NumPy 1D chứa nhiều mảng 2D. Mỗi hàng của mảng này đại diện cho một mảng 2D được làm phẳng. rotate_angle là góc (đơn vị độ) mà các mảng 2D sẽ được xoay. sizePixel là kích thước của mỗi mảng vuông 2D.\n\n","metadata":{}},{"cell_type":"code","source":"def func_array1d_rotate2d(Narray1d,rotate_angle,sizePixel):\n\n    N = Narray1d.shape[0]\n\n    Narray1d_rotate = np.zeros(Narray1d.shape)\n    \n    for i in range(N):\n        image = np.reshape(Narray1d[i,:],(sizePixel,sizePixel))\n        rotated_image = rotate(image,rotate_angle, reshape=False)\n        rotated_array1d = np.reshape(rotated_image,(1,-1))\n        Narray1d_rotate[i,:] = rotated_array1d\n        \n    return Narray1d_rotate","metadata":{"_uuid":"76ecec72-7aaa-4e9c-9366-c53a6fb1d164","_cell_guid":"f51ca997-1fbb-4259-94ee-5b05b70a035a","collapsed":false,"jupyter":{"outputs_hidden":false},"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-06-11T18:05:47.773436Z","iopub.execute_input":"2024-06-11T18:05:47.774045Z","iopub.status.idle":"2024-06-11T18:05:47.786820Z","shell.execute_reply.started":"2024-06-11T18:05:47.774002Z","shell.execute_reply":"2024-06-11T18:05:47.785149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"----\n# Phần 2: Đọc dữ liệu và khai thác dữ liệu","metadata":{"_uuid":"0ff27da2-835c-4122-aca0-9e731f3dc7ea","_cell_guid":"6248d1ca-53a8-45d0-9ab6-9003187ef756","trusted":true}},{"cell_type":"markdown","source":"Trong phần này, chúng ta sẽ sử dụng thư viện Python nổi tiếng là <code>Pandas</code> để đọc dữ liệu từ các tệp <code>.csv</code>.<br><br>Chúng ta sẽ trực quan hóa <b>phân phối các giá trị pixel</b> (biểu đồ histogram) bằng cách sử dụng các thư viện Python <code>Seaborn</code> và <code>Matplotlib</code>. Chúng ta cũng sẽ kiểm tra xem có <b>giá trị còn thiếu</b> không và các <b>lớp mục tiêu có cân bằng</b> không.<br><br>Cuối cùng, chúng ta sẽ <b>trực quan hóa các hình ảnh</b> bằng cách vẽ một hình ảnh từ mỗi lớp.","metadata":{"_uuid":"08c1c024-9f04-4d45-80af-6f8b9ed71f30","_cell_guid":"e27a867c-ee7f-4c03-85fd-bec46a9f2fd2","_kg_hide-input":false,"trusted":true}},{"cell_type":"code","source":"# đọc dữ liệu sử dụng pandas\ndf_train = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')\ndf_test =  pd.read_csv('/kaggle/input/digit-recognizer/test.csv')","metadata":{"_uuid":"078702a8-cfea-4f1c-bb0b-1018fea19c2c","_cell_guid":"8b4f5e4b-fc80-473b-bd7a-7e620b412c90","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:47.788914Z","iopub.execute_input":"2024-06-11T18:05:47.789495Z","iopub.status.idle":"2024-06-11T18:05:53.417850Z","shell.execute_reply.started":"2024-06-11T18:05:47.789447Z","shell.execute_reply":"2024-06-11T18:05:53.416337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# kiểm tra kích thước của các DataFrame dùng để huấn luyện\nprint(\"df_train shape:\", df_train.shape)  # 70%\nprint(\"df_test shape: \", df_test.shape)  # 30%","metadata":{"_uuid":"ca8aa9af-b761-403d-aa85-a3642ea77c5c","_cell_guid":"ba38193d-5d27-48f6-a7b3-f505b93dfe84","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:53.420392Z","iopub.execute_input":"2024-06-11T18:05:53.420793Z","iopub.status.idle":"2024-06-11T18:05:53.427061Z","shell.execute_reply.started":"2024-06-11T18:05:53.420758Z","shell.execute_reply":"2024-06-11T18:05:53.425736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fortunately there are no missing values in our data\nprint(\n    \"Missing values in df_train: \", \\\n    df_train.isna().sum().sum()\n)\nprint(\n    \"Missing values in df_test: \", \\\n    df_test.isna().sum().sum()\n)","metadata":{"_uuid":"a10fb707-86d3-4a6b-98f0-ace8a866768f","_cell_guid":"7cede701-9df4-4ac1-a358-2c567d72cd67","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:53.428388Z","iopub.execute_input":"2024-06-11T18:05:53.428939Z","iopub.status.idle":"2024-06-11T18:05:53.500772Z","shell.execute_reply.started":"2024-06-11T18:05:53.428904Z","shell.execute_reply":"2024-06-11T18:05:53.499532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# xem năm dòng đầu tiên của dữ liệu huấn luyện\ndf_train.head()","metadata":{"_uuid":"087da919-79ff-4a00-a357-fdb65381edda","_cell_guid":"cbfdc56f-8ade-4af2-b159-a2f526b273a5","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:53.502729Z","iopub.execute_input":"2024-06-11T18:05:53.503158Z","iopub.status.idle":"2024-06-11T18:05:53.527361Z","shell.execute_reply.started":"2024-06-11T18:05:53.503115Z","shell.execute_reply":"2024-06-11T18:05:53.525496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We can see that the first colum is the label,\n# and the rest of the columns are the 784 pixels\n# that represent 28x28 gray-scale images.\n# Let's separate X and Y\n\nX_train = df_train.drop(columns=['label']).values\ny_train = df_train['label'].values","metadata":{"_uuid":"2aefa02a-2611-42d1-9764-6ab390b73c0b","_cell_guid":"ccfff756-d687-424c-877d-028bb3180a59","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:53.529716Z","iopub.execute_input":"2024-06-11T18:05:53.530155Z","iopub.status.idle":"2024-06-11T18:05:53.636844Z","shell.execute_reply.started":"2024-06-11T18:05:53.530119Z","shell.execute_reply":"2024-06-11T18:05:53.634790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# Biểu đồ này minh họa phân phối của các giá trị pixel trong hình ảnh.\n\nax = sns.histplot(x=X_train.flatten(), color='#4895EE')\n_ = ax.set(title='Pixel Value Histogram', xlabel='Pixel Value')\n\n# Các giá trị pixel thường nằm trong khoảng từ 0 đến 255. \n# Giá trị 0 thường đại diện cho màu nền, trong khi các giá trị lớn hơn 0 biểu thị các đặc trưng chính trong hình ảnh như các ký tự hoặc chi tiết khác.\n# Biểu đồ cho thấy có nhiều pixel có giá trị 0, chủ yếu là nền, và các giá trị lớn hơn 0 biểu thị các đặc trưng chính của hình ảnh.","metadata":{"_uuid":"7a976629-a208-4444-970a-6f990f01b730","_cell_guid":"f8a9174d-c11e-4467-8dcd-bba2e0d51ac3","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:05:53.639035Z","iopub.execute_input":"2024-06-11T18:05:53.639660Z","iopub.status.idle":"2024-06-11T18:06:12.372853Z","shell.execute_reply.started":"2024-06-11T18:05:53.639619Z","shell.execute_reply":"2024-06-11T18:06:12.371351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# kiểm tra xem mục tiêu có cân bằng không.\n\nax = sns.countplot(x=y_train, color='#4895EE')\nax.set(\n    title='Target distribution is balanced? Yes!',\n    xlabel='Label'\n)\n# Số lượng mẫu kỳ vọng cho một phân phối lớp cân bằng là 42000/10 = 4200\n\n_ = ax.axhline(y=4200, color='#12086F', linestyle='--')\n\n# Vì các lớp mục tiêu đã cân bằng, chúng ta không cần\n# lo lắng về các phương pháp lấy mẫu và sự thiên vị trong các mô hình của chúng ta.","metadata":{"_uuid":"56cd7484-96d5-4052-a732-31184b3010be","_cell_guid":"31dd96d2-e9fc-4ec8-8027-6182b59bbb56","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:06:12.376868Z","iopub.execute_input":"2024-06-11T18:06:12.377289Z","iopub.status.idle":"2024-06-11T18:06:12.675981Z","shell.execute_reply.started":"2024-06-11T18:06:12.377241Z","shell.execute_reply":"2024-06-11T18:06:12.674750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# sử dụng matplotlib để hiện thị\n\nfig, axs = plt.subplots(nrows=2, ncols=5, figsize=(10,5))\n\nfor i in range(10):\n    idx = np.where(y_train==i)[0][2]\n    img = axs[int(i >= 5), i%5].imshow(\n        X=X_train[idx].reshape(28, 28),\n        cmap='Blues'\n    )\n    img.axes.get_yaxis().set_visible(False)\n    img.axes.get_xaxis().set_visible(False)\n    img.axes.set_title(f'Label: {i}')","metadata":{"_uuid":"6e57247a-308f-4d8c-b860-3fcca06504e8","_cell_guid":"85fb1afc-211b-4d78-a121-385e208ece49","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:06:12.677839Z","iopub.execute_input":"2024-06-11T18:06:12.678201Z","iopub.status.idle":"2024-06-11T18:06:13.251115Z","shell.execute_reply.started":"2024-06-11T18:06:12.678170Z","shell.execute_reply":"2024-06-11T18:06:13.249774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### transform data","metadata":{"_uuid":"9d4cd46f-3405-4ee3-a2e3-758b928024b1","_cell_guid":"abe3ee94-93c7-4941-9358-150e526414ec","trusted":true}},{"cell_type":"code","source":"# -------------------------------------------------- declare\nnumRotate_prior = 10\n\nangleOffset_prior = -20\nangleRange_prior = 40\n\nX_train_pick2rotate = {\n    'index': np.array([\n        1400, 1401, 1402, 1403, 1404,\n        1405, 1406, 1407, 1408, 1409,\n        1410, 1411, 1412, 1413, 1414,\n        1415, 1416, 1417, 1418, 1419,\n        1420, 1421, 1422, 1423, 1424,\n        1425, 1426, 1427, 1428, 1429,\n        1430, 1431, 1432, 1433, 1434,\n        1435, 1436, 1437, 1438, 1439,\n        1440, 1441, 1442, 1443, 1444,\n        1445, 1446, 1447, 1448, 1449,\n        1450, 1451, 1452, 1453, 1454,\n        1455, 1456, 1457, 1458, 1459,\n        1460, 1461, 1462, 1463, 1464,\n        1465, 1466, 1467, 1468, 1469,\n        1470, 1471, 1472, 1473, 1474,\n        1475, 1476, 1477, 1478, 1479,\n        1480, 1481, 1482, 1483, 1484,\n        1485, 1486, 1487, 1488, 1489,\n        1490, 1491, 1492, 1493, 1494,\n        1495, 1496, 1497, 1498, 1499,\n    ]),\n    'offset': np.array([\n        [5, -20, 0, -10, 0, 5, 15, -5, 20, 10],# 1400\n        [0, -10, -5, -10, -5, 0, -90, -5, -5, 0], # 1401\n        [20, -10, -20, -5, -10, 5, 5, 10, -5, -5], # 1402\n        [-20, -15, 5, -15, -5, 0, -40, 0, 15, 0],#1403\n        [25, 20, -10, 0, -20, -10, -40, 10, 10, -20],# 1404\n        [45, 5, -20, -10, -5, -5, -5, 0, -25, -10],#1405\n        [5, -20, -5, 0, 10, 0, -20, 0, 15, 15], # 1406\n        [-10, 0, -15, -5, 5, -10, -5, 5, 25, 10], #1407\n        [20, -20, 0, -15, 0, -10, 0, -5, 10, 0], #1408\n        [0, -20, -10, 5, 0, -10, -20, 5, 0, -20], #1409\n        [20, -15, -20, -5, -15, -25, -25, 10, 5, 20], #1410\n        [-25, -5, -10, -15, 5, -5, 0, 0, 0, 5],# 1411\n        [-10, 0, -15, -15, 5, 0, -5, 0, -15, -5], #1412\n        [-10, -15, -15, -20, 5, 5, -5, -5, 0, -5],# 1413\n        [0, 0, 5, -25, -10, -10, -25, 5, 5, -35],# 1414\n        [-5, -5, -5, -5, 0, 5, -35, 5, -15, 0], # 1415\n        [0, -5, -10, -15, 0, -10, -5, 5, -5, -15], # 1416\n        [15, -10, -10, 0, 10, -10, -15, -15, 25, 0], #1417\n        [-5, -10, -10, -20, -5, 0, -20, -5, -5, 0], #1418\n        [-5, -10, -10, -10, 0, 5, -10, 15, 5, -15], #1419\n        [0, -5, 5, -10, -15, 0, -5, 5, -10, -20], # 1420      \n        [20, 10, -10, -15, 20, -25, -15, -10, 0, 0],#1421\n        [-10, -5, -15, -15, 20, 0, -10, -5, -5, -15],#1422\n        [-5, 5, -15, -15, -10, 5, -40, 5, 5, -10],#1423\n        [-5, -40, -10, 0, 5, 0, -15, 10, 0, -5],#1424\n        [0, -30, 0, -10, 0, 5, -5, 0, 5, -5],#1425\n        [5, -15, 0, 5, -5, -5, -15, 0, -15, 0],#1426\n        [-15, -30, -10, -10, 5, 0, 0, 0, -5, -15],#1427\n        [0, -25, 0, -5, -5, 0, -15, 0, -5, 5],#1428 \n        [15, -10, -10, -10, -5, 0, -15, 5, 0, -5],#1429\n        [-5, -5, -10, -5, 0, 5, -20, 0, -5, -5],#1430\n        [-5, -5, -15, 0, 0, -10, -5, 5, -15, -15],#1431\n        [-5, 5, -5, 0, -15, 0, -5, -5, -5, -15],#1432\n        [-20, 0, 0, 0, 0, -5, -30, 0, 0, 0],#1433\n        [0, -5, 0, -30, 0, 0, -5, 30, 0, 0],#1434\n        [0, -20, 0, -15, 5, 0, -15, 0, 5, -25],#1435\n        [-10, 0, -15, -10, -5, 5, -15, 0, 5, -5],#1436\n        [0, -5, -10, -10, -5, -5, -5, 5, 0, 10], #1437\n        [5, -5, -15, -15, -5, -5, 0, -5, 15, 0],#1438\n        [-5, 10, 5, -10, -5, -5, -30, 40, -15, 15],#1439\n        [0, -5, -15, -10, 5, 5, 5, 40, 0, 5],#1440\n        [0, -15, 0, -10, -5, 5, -25, 0, -5, 0],#1441\n        [0, 0, 0, -5, 5, 0, -10, 0, -20, -5],#1442\n        [0, -5, -5, -10, 0, -10, 0, 0, -5, 0],#1443\n        [-10, 0, -5, 0, -20, 0, 0, 0, 0, -10],#1444\n        [-5, -15, -5, -10, -5, -15, -10, 0, -5, 0],#1445\n        [5, 10, -10, 0, -15, -5, -5, 10, -10, -5],#1446\n        [0, -5, 0, -5, 5, 5, -5, -10, -5, 0],#1447\n        [-5, -5, 0, -10, -10, 10, -5, 5, 10, 0],#1448\n        [-10, -10, 0, -20, 0, 5, -5, 5, 5, 0],#1449\n        [5, 0, -10, -5, 0, 0, -5, -5, 0, -10],#1450\n        [-10, -15, 5, -10, -5, 5, 0, -5, 0, 0],#1451\n        [5, -10, -10, 0, -5, 5, -20, 5, 10, -10],#1452\n        [10, -5, -5, -5, -10, -10, -15, -5, 0, -5],#1453\n        [-10, 0, -5, -10, 0, -10, 0, 5, -5, -20],#1454\n        [-10, -5, -5, -5, -10, -5, -20, -10, 0, -5],#1455\n        [-5, 0, -5, -15, 5, -5, 5, -5, 5, 0],#1456\n        [-10, -10, 0, -5, -5, 0, -10, -5, 0, -5],#1457\n        [5, -5, -5, 0, -10, 0, -5, -5, -5, -5],#1458\n        [-10, 0, -5, -5, -5, -5, 5, 0, 0, -5],#1459\n       [20, -10, 0, -15, -10, -10, -20, 5, 10, -5],#1460\n        [0, -10, -10, 5, -5, 5, -5, -5, 0, 0], #1461\n        [0, 15, -10, -10, -15, -5, -15, -5, 0, 0],#1462\n        [-5, -10, 0, 0, 0, -10, 0, 0, 0, 0],#1463\n        [0, 0, -5, -25, -5, 5, -5, 0, -5, -5],#1464\n        [-20, -10, -5, 5, 0, -5, 10, 0, -5, 0],#1465\n        [15, 0, -5, -15, -20, -10, -20, 10, 0, -20],#1466\n        [0, 0, -10, -5, 5, 0, -5, 0, -10, 0],#1467\n        [10, -10, -5, -15, 5, -5, 0, 10, 0, -5],#1468\n        [0, -20, -10, -10, -5, 0, -5, 0, 10, -25],#1469\n        [15, -5, -5, 0, -10, 0, -25, 5, -15, 0],#1470\n        [15, 20, -5, 0, 5, -10, -20, -5, -10, -5],#1471\n        [-5, -5, -15, -5, -5, 10, -15, 0, 10, -15],#1472\n        [15, 0, -5, 0, -10, -20, -15, 0, 5, -20],#1473\n        [-5, 0, -5, -5, 0, -10, -15, -10, -10, -15],#1474\n        [15, -15, -10, -5, -15, 0, -15, 0, -20, -25],#1475\n        [5, 0, -5, -10, 0, 15, -10, 0, 0, 5],#1476\n        [-5, -10, -10, -10, 0, 0, -15, 5, -5, -5],#1477\n        [0, 5, -15, 0, -5, 0, -10, 0, 10, -10],#1478\n        [-5, 5, -10, 5, -5, 0, -10, 0, 10, -10], #1479\n        [-5, 0, -10, 5, 5, 20, -10, 0, 0, -10],#1480\n        [-10, -10, -15, -15, 0, 0, -15, -10, 5, 0], #1481\n        [10, -10, -15, -10, -5, 10, -20, -5, 0, -5], #1482\n        [-10, 0, -10, -15, 0, 15, -20, -5, 5, -15], #1483\n        [-5, 10, 0, -5, 0, 5, -20, 5, 5, -15], #1484\n        [10, -10, -5, 0, 5, 10, -20, -10, 0, -15], #1485\n        [-10, 10, 0, -5, -10, 0, -10, -10, 5, -5], #1486\n        [0, -5, -5, -5, -5, 0, -20, 0, -10, 0], #1487\n        [0, 0, -10, -10, 0, 0, -5, -5, 5, -10], #1488\n        [0, 10, 0, -5, 0, 0, -10, -5, 5, -10], #1489\n        [15, -10, -10, -5, -10, 5, -15, 0, 0, -15], #1490\n        [5, -10, -10, -10, -5, 5, -10, 0, -10, -10], #1491\n        [0, -5, 0, -15, 0, 5, -15, -5, 0, -10], #1492\n        [-10, -5, -10, -10, -5, 5, -10, 0, 0, 0], #1493\n        [0, 0, -5, -5, 0, 5, -20, 0, 0, -5], #1494\n        [-10, 10, -5, -15, -10, 5, -15, 0, -10, -15], #1495\n        [-10, -15, -5, -10, -10,5, -20, 5, 5, 0], #1496\n        [-10, 0, -5, 5, 5, 5, -15, 5, -10, 10], #1497\n        [30, -15, -5, -15, -5, 20, -15, 15, 10, -60], #1498\n        [-10, 5, -10, -10, 5, 10, -15, -15, 30, 15], #1499\n        \n    ])\n}\n\nnumPickRotate = len(X_train_pick2rotate['index'])\n\nprint('numPickRotate = ', numPickRotate)\n\n# -------------------------------------------------- rotate\n\nX_sample_rotate = np.zeros((10,numRotate_prior,numPickRotate,X_train.shape[1]))\ny_sample_rotate = np.zeros((10,numRotate_prior,numPickRotate))\n\nfor k0 in range(10):\n    for k1 in range(numRotate_prior):\n        for k2 in range(numPickRotate):\n            \n                idxPick_X_train = X_train_pick2rotate['index'][k2]\n                \n                idx = np.where(y_train==k0)[0][idxPick_X_train]\n                \n                y_sample_rotate[k0,k1,k2] = k0 * numRotate_prior + k1\n                \n                angleRotate = (k1/numRotate_prior * angleRange_prior) + angleOffset_prior + X_train_pick2rotate['offset'][k2][k0]\n                \n                X_sample_rotate[k0,k1,k2,:] = func_array1d_rotate2d(X_train[idx][np.newaxis,:],angleRotate, 28)\n\n                \nX_sample_rotate[X_sample_rotate < 10] = 0\n#X_sample_rotate[X_sample_rotate > 300] = 0\n\n# Let's normalize the pixel values to the interval [0,1]\n# Formula: MinMaxscale(X) = (X - X_min) / (X_max - X_min)\n\nprint(\"Before applying MinMax Scaler:\")\nprint(\"  - Minimum value:\", X_sample_rotate.min())\nprint(\"  - Maximum value:\", X_sample_rotate.max())\n\nminmax_scaler = MinMaxScaler()\n\nfor k0 in range(10):\n    for k1 in range(numRotate_prior):\n        X_sample_rotate[k0,k1,:,:] = minmax_scaler.fit_transform(X_sample_rotate[k0,k1,:,:]) * 255\n\nprint(\"\\nAfter applying MinMax Scaler:\")\nprint(\"  - Minimum value:\", X_sample_rotate.min())\nprint(\"  - Maximum value:\", X_sample_rotate.max())\n\n\n\n# Next, let's visualize one image from each class.\n# We will use the matplotlib 'imshow' function.\n\n# for k2 in range(numPickRotate):\nfor k2 in range(100):\n    k1 = 0\n    # k1 = numRotate_prior - 1\n\n    fig, axs = plt.subplots(nrows=2, ncols=5, figsize=(10,5))\n\n    for k0 in range(10):\n        img = axs[int(k0 >= 5), k0%5].imshow(\n            X=X_sample_rotate[k0,k1,k2,:].reshape(28, 28),\n            cmap='Blues'\n        )\n        img.axes.get_yaxis().set_visible(False)\n        img.axes.get_xaxis().set_visible(False)\n        img.axes.set_title(f'Label: {k0}')\n        img.axes.annotate(f'{X_train_pick2rotate[\"index\"][k2]}', xy=(1, 1), xycoords='axes fraction', fontsize=12, color='red', xytext=(-5, -5), textcoords='offset points', ha='right', va='top')\n        \nX_train_rotate = np.reshape(X_sample_rotate, (-1,784))\ny_train_rotate = np.reshape(y_sample_rotate, (-1,1)).flatten()\n","metadata":{"_uuid":"e87363e6-d051-4009-be4f-a825679930e7","_cell_guid":"db89b71d-4901-4716-9507-e9497e268d74","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:06:13.252849Z","iopub.execute_input":"2024-06-11T18:06:13.253330Z","iopub.status.idle":"2024-06-11T18:07:21.885132Z","shell.execute_reply.started":"2024-06-11T18:06:13.253292Z","shell.execute_reply":"2024-06-11T18:07:21.883951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Perform PCA on rotated data\npca = PCA(n_components=3)\nX_train_rotate_pca = pca.fit_transform(X_train_rotate)\n\n# Put the PCA components in a Pandas DataFrame\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca, \n    columns=['x', 'y', 'z']\n)\n\n# Add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()\n","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:21.886862Z","iopub.execute_input":"2024-06-11T18:07:21.887334Z","iopub.status.idle":"2024-06-11T18:07:22.592939Z","shell.execute_reply.started":"2024-06-11T18:07:21.887292Z","shell.execute_reply":"2024-06-11T18:07:22.591588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's put the components in Pandas DataFrame format\n# This way we can use the seaborn and plotly libraries\n# to visualize the data.\n# (these packages work better with Pandas DataFrames)\n\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca[:,:3], \n    columns=['x', 'y', 'z']\n)\n# Let's also add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.600665Z","iopub.execute_input":"2024-06-11T18:07:22.614671Z","iopub.status.idle":"2024-06-11T18:07:22.645880Z","shell.execute_reply.started":"2024-06-11T18:07:22.614578Z","shell.execute_reply":"2024-06-11T18:07:22.644550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's put the components in Pandas DataFrame format\n# This way we can use the seaborn and plotly libraries\n# to visualize the data.\n# (these packages work better with Pandas DataFrames)\n\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca[:,:3], \n    columns=['x', 'y', 'z']\n)\n# Let's also add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.647503Z","iopub.execute_input":"2024-06-11T18:07:22.647893Z","iopub.status.idle":"2024-06-11T18:07:22.670406Z","shell.execute_reply.started":"2024-06-11T18:07:22.647856Z","shell.execute_reply":"2024-06-11T18:07:22.669161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's put the components in Pandas DataFrame format\n# This way we can use the seaborn and plotly libraries\n# to visualize the data.\n# (these packages work better with Pandas DataFrames)\n\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca[:,:3], \n    columns=['x', 'y', 'z']\n)\n# Let's also add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.671879Z","iopub.execute_input":"2024-06-11T18:07:22.672236Z","iopub.status.idle":"2024-06-11T18:07:22.691341Z","shell.execute_reply.started":"2024-06-11T18:07:22.672204Z","shell.execute_reply":"2024-06-11T18:07:22.690006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's put the components in Pandas DataFrame format\n# This way we can use the seaborn and plotly libraries\n# to visualize the data.\n# (these packages work better with Pandas DataFrames)\n\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca[:,:3], \n    columns=['x', 'y', 'z']\n)\n# Let's also add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.693327Z","iopub.execute_input":"2024-06-11T18:07:22.693780Z","iopub.status.idle":"2024-06-11T18:07:22.712742Z","shell.execute_reply.started":"2024-06-11T18:07:22.693741Z","shell.execute_reply":"2024-06-11T18:07:22.711602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"_uuid":"e87363e6-d051-4009-be4f-a825679930e7","_cell_guid":"db89b71d-4901-4716-9507-e9497e268d74","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---------\n# Phần 3: Phân tích thành phần chính","metadata":{"_uuid":"8794e86b-0a44-46a2-8d06-c6186454767d","_cell_guid":"d404fd37-ba51-4a9f-9de3-878c4bb0ad21","trusted":true}},{"cell_type":"markdown","source":"<div style=\"border-radius: 10px; border: #4361EE solid; padding: 15px; background-color: #ffffff00; font-size: 100%; text-align: left;\">\n    <b>Phân tích thành phần chính</b> (PCA - Principal Component Analysis) là một kỹ thuật thống kê để giảm chiều dữ liệu. Điều này được thực hiện bằng cách <b>biến đổi tuyến tính dữ liệu</b> thành một hệ trục tọa độ mới, trong đó (hầu hết) sự biến thiên trong dữ liệu có thể được mô tả bằng ít chiều hơn so với dữ liệu ban đầu.<br><br>\n    Thành phần chính đầu tiên có thể được định nghĩa tương đương như là một <b>hướng mà tối đa hóa phương sai của dữ liệu được chiếu</b>. Thành phần chính thứ <i>i</i> có thể được lấy là một hướng vuông góc với các thành phần chính đầu tiên <i>i-1</i> mà tối đa hóa phương sai của dữ liệu được chiếu.<br><br>\n    <code>sklearn.decomposition.PCA</code>: Giảm chiều dữ liệu tuyến tính bằng cách sử dụng Phân rã Giá trị Đơn (Singular Value Decomposition - SVD) của dữ liệu để chiếu nó xuống không gian chiều thấp hơn.<br><br>\n    Ở đây, chúng ta sẽ sử dụng <b>10 thành phần chính hàng đầu</b>, mà giải thích <b>gần 50% phương sai</b> trong dữ liệu. Điều này có nghĩa là chúng ta có thể diễn giải 50% phương sai của dữ liệu với một không gian tính năng <b>>98% nhỏ hơn so với ban đầu</b> (10 tính năng so với 784 tính năng)\n</div>","metadata":{"_uuid":"988c70b6-e9d9-4ae7-b127-921423ab0f0e","_cell_guid":"231a3cf2-1f44-475b-a745-a28f3eb35d1e","trusted":true}},{"cell_type":"code","source":"# chuẩn hóa các giá trị pixel về khoảng [0,1]\n# Công thức: MinMaxscale(X) = (X - X_min) / (X_max - X_min)\n\n\nprint(\"Before applying MinMax Scaler:\")\nprint(\"  - Minimum value:\", X_train.min())\nprint(\"  - Maximum value:\", X_train.max())\n\nminmax_scaler = MinMaxScaler()\nX_train_rotate_scaled = minmax_scaler.fit_transform(X_train_rotate)\n\nprint(\"\\nAfter applying MinMax Scaler:\")\nprint(\"  - Minimum value:\", X_train_rotate_scaled.min())\nprint(\"  - Maximum value:\", X_train_rotate_scaled.max())","metadata":{"_uuid":"2f018749-1981-43d6-b1b8-b1716a72e3fb","_cell_guid":"7c68f163-b747-4392-9a1e-8792cb07ccde","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.714607Z","iopub.execute_input":"2024-06-11T18:07:22.715171Z","iopub.status.idle":"2024-06-11T18:07:22.867527Z","shell.execute_reply.started":"2024-06-11T18:07:22.715135Z","shell.execute_reply":"2024-06-11T18:07:22.865913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Nhúng MinMaxScaler và PCA vào một đường ống cho phép chúng ta thực hiện các bước chuẩn hóa dữ liệu và giảm chiều dữ liệu một cách dễ dàng và linh hoạt.\n# modules into a Sklearn Pipeline.\n\npca = Pipeline(steps=[\n    ('scaler', MinMaxScaler()),\n    ('pca', PCA(n_components=80))\n])\n\nX_train_rotate_pca = pca.fit_transform(X=X_train_rotate)\n\nprint('X_train_pca shape:', X_train_rotate_pca.shape)","metadata":{"_uuid":"4bfc3273-16ce-4a37-93ae-9cf46373e2c4","_cell_guid":"2d2d1d92-8b2d-4b97-af06-40a19024b09e","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:22.870170Z","iopub.execute_input":"2024-06-11T18:07:22.870608Z","iopub.status.idle":"2024-06-11T18:07:24.815488Z","shell.execute_reply.started":"2024-06-11T18:07:22.870574Z","shell.execute_reply":"2024-06-11T18:07:24.813435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# trích xuất tỷ lệ phương sai được giải thích\n# tính tổng tích lũy của chúng\n\npca_object = pca.named_steps['pca']\nvar_ratio = pd.Series(\n    data=pca_object.explained_variance_ratio_,\n    index=range(1, 81)\n)\n\ncumsum_var_ratio = var_ratio.cumsum()","metadata":{"_uuid":"e551b2e2-ce61-4b14-abca-472ab8f8fa6f","_cell_guid":"8fe76194-de6d-44ef-89b7-489a936a3a12","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:24.826762Z","iopub.execute_input":"2024-06-11T18:07:24.833426Z","iopub.status.idle":"2024-06-11T18:07:24.849205Z","shell.execute_reply.started":"2024-06-11T18:07:24.833368Z","shell.execute_reply":"2024-06-11T18:07:24.847379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Vẽ biểu đồ tỷ lệ phương sai được giải thích cho mỗi thành phần (bên trái)\n# Và vẽ tổng tích lũy của chúng (bên phải)\n\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15,5))\n\nsns.barplot(\n    x=var_ratio.index, \n    y=var_ratio.values, \n    color='#4895EE', \n    ax=ax1\n)\nax1.set(\n    title='Explained Variance Ratio PCA',\n    xlabel='Component',\n    ylabel='Var Ratio',\n)\nax1.set_ylim(0, 0.5)\n\nsns.barplot(\n    x=cumsum_var_ratio.index, \n    y=cumsum_var_ratio.values, \n    color='#4895EE', \n    ax=ax2\n)\nax2.set(\n    title='Cumulative Explained Variance Ratio PCA',\n    xlabel='Component',\n    ylabel='Cumulative Var Ratio',\n)\n_ = ax2.set_ylim(0, 0.5)","metadata":{"_uuid":"34ab9680-e976-4c81-bf92-6e9d8a0236bb","_cell_guid":"5e8c9489-629b-45b3-a577-b855fe33869f","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:24.854877Z","iopub.execute_input":"2024-06-11T18:07:24.855293Z","iopub.status.idle":"2024-06-11T18:07:27.066605Z","shell.execute_reply.started":"2024-06-11T18:07:24.855240Z","shell.execute_reply":"2024-06-11T18:07:27.065282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# đưa các thành phần vào định dạng DataFrame của Pandas\n\n\ndf_train_pca = pd.DataFrame(\n    data=X_train_rotate_pca[:,:3], \n    columns=['x', 'y', 'z']\n)\n# Let's also add the target to set the colors\ndf_train_pca['target'] = y_train_rotate\n\nprint(df_train_pca.shape)\ndf_train_pca.head()","metadata":{"_uuid":"b779e0bc-6938-424a-9c08-3579404299da","_cell_guid":"8d64a105-5b85-4924-9d4c-d5bc95d474e8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:27.068209Z","iopub.execute_input":"2024-06-11T18:07:27.068704Z","iopub.status.idle":"2024-06-11T18:07:27.086094Z","shell.execute_reply.started":"2024-06-11T18:07:27.068670Z","shell.execute_reply":"2024-06-11T18:07:27.084815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Two-dimensional visualization of the data\n# Here the Top2 principal components are plotted\n\nsns.set_style(\"dark\")\nax = sns.scatterplot(\n    data=df_train_pca,\n    x='x', \n    y='y', \n    hue='target', \n    palette='Blues',\n)\nax.set(\n    title='PCA Two-Dimensional Projection',\n    xlabel='1st Comp.',\n    ylabel='2nd Comp.'\n)\nax.axhline(y=0, linestyle='--', color='#FFBF00', zorder=-1)\nax.axvline(x=0, linestyle='--', color='#FFBF00', zorder=-1)","metadata":{"_uuid":"90d9d1e3-fbcb-400a-b8d5-68d2a5f4f646","_cell_guid":"c05ac3f3-ec1c-4fd0-8e88-cd0991afb146","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:27.087585Z","iopub.execute_input":"2024-06-11T18:07:27.087955Z","iopub.status.idle":"2024-06-11T18:07:28.649547Z","shell.execute_reply.started":"2024-06-11T18:07:27.087916Z","shell.execute_reply":"2024-06-11T18:07:28.647393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Two-dimensional visualization of the data\n# Here the Top3 principal components are plotted\n\nsns.set_style(\"white\")\nfig = px.scatter_3d(\n    data_frame=df_train_pca,\n    x='x',\n    y='y',\n    z='z',\n    labels={\n        'x': '1st Comp.',\n        'y': '2nd Comp.',\n        'z': '3rd Comp.'\n    },\n    color='target',\n    title='PCA Three-Dimensional Projection',\n    color_continuous_scale='blues',\n    template='ggplot2'\n)\n\nfig.show()","metadata":{"_uuid":"1fb19f51-6852-4f02-8660-90a8a537fa30","_cell_guid":"b76b9b11-2a7e-4cc9-983c-0ae311d92428","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:28.652391Z","iopub.execute_input":"2024-06-11T18:07:28.653543Z","iopub.status.idle":"2024-06-11T18:07:30.983236Z","shell.execute_reply.started":"2024-06-11T18:07:28.653434Z","shell.execute_reply":"2024-06-11T18:07:30.981965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now, let's apply the inverse_transform to compute\n# the approximation of images based on the 10 principal\n# compontents.\n# We can see that with just 10 components we convey a large\n# part of the information of each image.\n\npca_object = pca.named_steps['pca']\n\nfig, axs = plt.subplots(nrows=10, ncols=2, figsize=(6,20))\n\nfor i in range(10):\n    idx = np.where(y_train==i)[0][0]\n    original_img = axs[i, 0].imshow(\n        X=X_train_rotate[idx].reshape(28, 28),\n        cmap='Blues'\n    )\n    original_img.axes.get_yaxis().set_visible(False)\n    original_img.axes.get_xaxis().set_visible(False)\n    original_img.axes.set_title(f'Original [{i}]:')\n    \n    approx_img_ = pca_object.inverse_transform(X=X_train_rotate_pca[idx])\n    approx_img = axs[i, 1].imshow(\n        X=approx_img_.reshape(28, 28),\n        cmap='Blues'\n    )\n    approx_img.axes.get_yaxis().set_visible(False)\n    approx_img.axes.get_xaxis().set_visible(False)\n    approx_img.axes.set_title(f'Approximation [{i}]:')","metadata":{"_uuid":"0d814515-0bec-4c78-af57-09ed84b2dfc4","_cell_guid":"7e42f02f-c973-4898-8c10-80b0ca2d625b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:30.990061Z","iopub.execute_input":"2024-06-11T18:07:30.990521Z","iopub.status.idle":"2024-06-11T18:07:32.107171Z","shell.execute_reply.started":"2024-06-11T18:07:30.990484Z","shell.execute_reply":"2024-06-11T18:07:32.105933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Show that the PCA components are uncorrelated\n# (This statement is true by definition and construction\n# of the Principal Component Analysis algorithm)\n\ncorr = np.corrcoef(x=X_train_rotate_pca, rowvar=False)\ncorr = np.around(corr, decimals=2)\n\nax = sns.heatmap(\n    data=corr, \n    vmax=1, \n    vmin=-1,\n    square=True,\n    linewidths=.5,\n    annot=True,\n    cmap='Blues',\n)\n\n_ = ax.set(\n    title='Correlation PCA Components [Uncorrelated]',\n    xlabel='Components',\n    ylabel='Components'\n)","metadata":{"_uuid":"8a21533b-a961-49b1-b24c-d4e7050cc806","_cell_guid":"32e1e369-193f-4071-9914-b2f03cce2893","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:32.108589Z","iopub.execute_input":"2024-06-11T18:07:32.108934Z","iopub.status.idle":"2024-06-11T18:07:50.958460Z","shell.execute_reply.started":"2024-06-11T18:07:32.108904Z","shell.execute_reply":"2024-06-11T18:07:50.957180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"----\n# Phần 4: Sử dụng K-Nearest Neighbors Classifier phân loại 10 thành phần chính hàng đầu từ PCA.","metadata":{"_uuid":"370f38cc-e5fb-4b4e-8dd3-6b9e303ee060","_cell_guid":"43a48481-ea7f-470e-b826-8fd2fcc9e37f","trusted":true}},{"cell_type":"markdown","source":"<div style=\"border-radius: 10px; border: #4361EE solid; padding: 15px; background-color: #ffffff00; font-size: 100%; text-align: left;\">\nThe <b>K-Nearest Neighbors</b> algorithm is a <i>non-parametric</i>, supervised learning classifier, which uses <b>proximity</b> to make classifications or predictions about the grouping of an individual data point. Prediction: A class label is assigned on the basis of a <b>majority vote</b>. the label that is most frequently represented around a given data point.<br><br>\nIn this project, the input of the KNN Classifier will be the top 10 principal components from the PCA.<br><br>\n<code>sklearn.neighbors.KNeighborsClassifier</code>: Classifier implementing the k-nearest neighbors vote. We will run a GridSearchCV to optimize the <code>n_neighbors</code> hyperparameter.\n</div>","metadata":{"_uuid":"db9e5ad7-aa3d-4606-9848-526bc3dc048f","_cell_guid":"efff5a1e-7ac3-41a4-b464-77ed4de056d3","trusted":true}},{"cell_type":"markdown","source":"---\n#  mô hình học máy trên tập dữ liệu Train","metadata":{"_uuid":"7c0a4822-eedd-4aa0-bac6-a2cf5a7b89bf","_cell_guid":"39e3a7f5-5363-4914-b78d-295251352529","trusted":true}},{"cell_type":"code","source":"knn_clf = Pipeline(steps=[\n    ('scaler', MinMaxScaler()),\n    ('pca', PCA(n_components=80)),\n    ('knn', KNeighborsClassifier())\n])\n\nknn_clf_params = {\n    'knn__n_neighbors': [2, 4, 8, 16, 32]\n}\n\nknn_clf_gs = GridSearchCV(\n    estimator=knn_clf, \n    param_grid=knn_clf_params,\n    scoring='accuracy',\n    n_jobs=-1,\n    cv=5,\n    verbose=1,\n    return_train_score=True\n)\n\nknn_clf_gs.fit(X=X_train_rotate_pca, y=y_train_rotate)\n\nprint('best PCA+KNN params:', knn_clf_gs.best_params_)\nprint('best PCA+KNN cv accuracy:', knn_clf_gs.best_score_)","metadata":{"_uuid":"2d7cd392-e51f-420a-aad2-0eb5c72ff742","_cell_guid":"797ae756-d6fc-4456-83e5-447d3cc034e2","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:07:50.959822Z","iopub.execute_input":"2024-06-11T18:07:50.960164Z","iopub.status.idle":"2024-06-11T18:08:10.962506Z","shell.execute_reply.started":"2024-06-11T18:07:50.960134Z","shell.execute_reply":"2024-06-11T18:08:10.960527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Vẽ sơ đồ độ chính xác trong đào tạo và xác nhận\n# cho mỗi giá trị Siêu tham số được kiểm tra trong quá trình\n# Tìm kiếm lưới.\n# Biểu đồ này cho phép chúng ta kiểm tra xem có trang bị quá mức hay không.\n\nfig, ax = plt.subplots()\n\nax.plot(\n    range(len(knn_clf_params['knn__n_neighbors'])), \n    knn_clf_gs.cv_results_['mean_train_score'],\n    label='train',\n    color='blue'\n)\nax.plot(\n    range(len(knn_clf_params['knn__n_neighbors'])),\n    knn_clf_gs.cv_results_['mean_test_score'],\n    label='test',\n    color='orange'\n)\nax.set_xticks(\n    ticks=range(len(knn_clf_params['knn__n_neighbors'])),\n    labels=knn_clf_params['knn__n_neighbors']\n)\n\nii = knn_clf_params['knn__n_neighbors'].index(\n    knn_clf_gs.best_params_['knn__n_neighbors']\n)\n\nplt.axvline(x=ii, linestyle='--', color='red', label='best', alpha=0.3)\nplt.legend()\nplt.xlabel(\"'n_neighbors' vals\")\nplt.ylabel('Accuracy')\nplt.title(\"PCA+KNN GridSearchCV Results\")\nplt.show()","metadata":{"_uuid":"2abf36ed-c1a2-4581-8a67-414fbfe556f5","_cell_guid":"38a69c14-7bf2-4328-abc9-45a9ef2c1b11","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-11T18:08:10.972254Z","iopub.execute_input":"2024-06-11T18:08:10.980421Z","iopub.status.idle":"2024-06-11T18:08:11.438488Z","shell.execute_reply.started":"2024-06-11T18:08:10.980312Z","shell.execute_reply":"2024-06-11T18:08:11.437328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---\n# Phần 5: Tạo một tệp tin chứa các dự đoán của mô hình học máy trên tập dữ liệu Test","metadata":{"_uuid":"2254c327-a8ec-41ca-9fa2-c41a850f4c75","_cell_guid":"adcdd26f-00ba-479f-8e33-e1bc6d65eafb","trusted":true}},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\n\n# Tính toán và hiển thị Ma trận nhầm lẫn\n# Lưu ý: toàn bộ tập dữ liệu huấn luyện được sử dụng ở đây\n\nX_val = X_train_rotate_pca\nY_val = y_train_rotate\n\nbest_cv_clf = knn_clf_gs.best_estimator_\ny_pred = best_cv_clf.predict(X=X_val)\n\ny_val_number = Y_val // numRotate_prior\ny_pred_number = y_pred // numRotate_prior\n\ny_val_angle = (Y_val % numRotate_prior)\ny_pred_angle = (y_pred % numRotate_prior)\n\nprint('KNN number + angle, Acc({:.2f}%)', accuracy_score(Y_val, y_pred))\nprint('KNN number, Acc({:.2f}%)', accuracy_score(y_val_number, y_pred_number))\nprint('KNN angle, Acc({:.2f}%)', accuracy_score(y_val_angle, y_pred_angle))\n\n# print('y_val_number =', y_val_number)\n# print('y_pred_number =', y_pred_number)\n\ny_val_angle_degree = y_val_angle/numRotate_prior * angleRange_prior + angleOffset_prior\ny_pred_angle_degree = y_pred_angle/numRotate_prior * angleRange_prior + angleOffset_prior\n\n# print('y_val_angle_degree =', y_val_angle_degree)\n# print('y_pred_angle_degree =', y_pred_angle_degree)\n\nconf_matrix = confusion_matrix(y_val_number, y_pred_number)\nconf_matrix_disp = ConfusionMatrixDisplay(conf_matrix)\nconf_matrix_disp.plot(cmap='Blues')\n\nconf_matrix = confusion_matrix(y_val_angle, y_pred_angle)\nconf_matrix_disp = ConfusionMatrixDisplay(conf_matrix)\nconf_matrix_disp.plot(cmap='Blues')","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:11.440151Z","iopub.execute_input":"2024-06-11T18:08:11.440613Z","iopub.status.idle":"2024-06-11T18:08:14.239578Z","shell.execute_reply.started":"2024-06-11T18:08:11.440572Z","shell.execute_reply":"2024-06-11T18:08:14.238308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_val = pca.transform(X_train)\nY_val = y_train\n\nbest_cv_clf = knn_clf_gs.best_estimator_\ny_pred = best_cv_clf.predict(X=X_val)\n\ny_pred_number = y_pred\ny_val_number = Y_val\n\nprint('KNN number, Acc({:.2f}%)', accuracy_score(y_val_number, y_pred_number))\n\nconf_matrix = confusion_matrix(y_val_number, y_pred_number)\nconf_matrix_disp = ConfusionMatrixDisplay(conf_matrix)\nconf_matrix_disp.plot(cmap='Blues')\n\ny_pred_angle = (y_pred % numRotate_prior)\n\ny_pred_angle_degree = y_pred_angle/numRotate_prior * angleRange_prior + angleOffset_prior\n\nprint('y_pred_angle_degree =', y_pred_angle_degree)","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:14.241869Z","iopub.execute_input":"2024-06-11T18:08:14.242350Z","iopub.status.idle":"2024-06-11T18:08:47.131733Z","shell.execute_reply.started":"2024-06-11T18:08:14.242306Z","shell.execute_reply":"2024-06-11T18:08:47.130519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Bây giờ, hãy áp dụng biến đổi nghịch đảo để tính toán\n# sự gần đúng của hình ảnh dựa trên nguyên tắc 10\n#thành phần.\n# Chúng ta có thể thấy rằng chỉ với 10 thành phần chúng ta đã truyền tải được một lượng lớn\n# một phần thông tin của mỗi hình ảnh.\n\npca_object = pca.named_steps['pca']\n\nfig, axs = plt.subplots(nrows=10, ncols=2, figsize=(6,20))\n\nfor i in range(10):\n    idx = np.where(y_train == i )[0][0]\n    original_img = axs[i, 0].imshow(\n        X=X_train[idx].reshape(28, 28),\n        cmap='Blues'\n    )\n    original_img.axes.get_yaxis().set_visible(False)\n    original_img.axes.get_xaxis().set_visible(False)\n    original_img.axes.set_title(f'Original [{i}]:')\n    \n    approx_img_ = pca_object.inverse_transform(X=X_val[idx])\n    approx_img = axs[i, 1].imshow(\n        X=approx_img_.reshape(28, 28),\n        cmap='Blues'\n    )\n    approx_img.axes.get_yaxis().set_visible(False)\n    approx_img.axes.get_xaxis().set_visible(False)\n    approx_img.axes.set_title(f'Predicted angle [{y_pred_angle_degree[idx]}]:')","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:47.133296Z","iopub.execute_input":"2024-06-11T18:08:47.133686Z","iopub.status.idle":"2024-06-11T18:08:48.314710Z","shell.execute_reply.started":"2024-06-11T18:08:47.133647Z","shell.execute_reply":"2024-06-11T18:08:48.313347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📃 References 📃","metadata":{"_uuid":"0bf02057-e66b-4045-bf4b-b91fb25f67ba","_cell_guid":"b35209f1-8bed-48cd-986d-7c85a99a4519","trusted":true}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"import plotly.express as px\nfrom plotly.offline import init_notebook_mode, iplot\nimport plotly.graph_objects as go\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:48.316534Z","iopub.execute_input":"2024-06-11T18:08:48.317063Z","iopub.status.idle":"2024-06-11T18:08:48.324310Z","shell.execute_reply.started":"2024-06-11T18:08:48.317011Z","shell.execute_reply":"2024-06-11T18:08:48.323062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_confusion_matrix(cm, labels, title):\n    # cm : danh sách ma trận nhầm lẫn(danh sách)\n    # labels : tên danh sách dữ liệu(str)\n    # title : tiêu đề cho bản đồ nhiệt\n    data = go.Heatmap(z=cm, y=labels, x=labels)\n    annotations = []\n    for i, row in enumerate(cm):\n        for j, value in enumerate(row):\n            annotations.append(\n                {\n                    \"x\": labels[i],\n                    \"y\": labels[j],\n                    \"font\": {\"color\": \"white\"},\n                    \"text\": str(value),\n                    \"xref\": \"x1\",\n                    \"yref\": \"y1\",\n                    \"showarrow\": False\n                }\n            )\n    layout = {\n        \"title\": title,\n        \"xaxis\": {\"title\": \"Predicted value\"},\n        \"yaxis\": {\"title\": \"Real value\"},\n        \"annotations\": annotations\n    }\n    fig = go.Figure(data=data, layout=layout)\n    return fig","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:48.325912Z","iopub.execute_input":"2024-06-11T18:08:48.326640Z","iopub.status.idle":"2024-06-11T18:08:48.339298Z","shell.execute_reply.started":"2024-06-11T18:08:48.326605Z","shell.execute_reply":"2024-06-11T18:08:48.337917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from tensorflow.keras.utils import np_utils\nfrom tensorflow.keras import utils\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom tensorflow.keras import datasets, layers, models","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:08:48.340781Z","iopub.execute_input":"2024-06-11T18:08:48.341159Z","iopub.status.idle":"2024-06-11T18:09:05.097979Z","shell.execute_reply.started":"2024-06-11T18:08:48.341108Z","shell.execute_reply":"2024-06-11T18:09:05.096096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train_cnn = X_train_rotate.reshape(-1,28,28,1)\n# X_val = np.array(pca.transform(X_train)).reshape(-1,28,28,1)\ny_train_cnn = utils.to_categorical(np.array(y_train_rotate// numRotate_prior))\nX_val = X_train.reshape(-1,28,28,1)\nY_val = utils.to_categorical(np.array(y_train))","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:09:05.099938Z","iopub.execute_input":"2024-06-11T18:09:05.101063Z","iopub.status.idle":"2024-06-11T18:09:05.110806Z","shell.execute_reply.started":"2024-06-11T18:09:05.101020Z","shell.execute_reply":"2024-06-11T18:09:05.109539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# In hình dạng của dữ liệu huấn luyện để xác nhận\nX_train_cnn.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:09:05.113181Z","iopub.execute_input":"2024-06-11T18:09:05.113760Z","iopub.status.idle":"2024-06-11T18:09:05.143803Z","shell.execute_reply.started":"2024-06-11T18:09:05.113711Z","shell.execute_reply":"2024-06-11T18:09:05.142333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Định nghĩa mô hình\nmodel = models.Sequential()\nmodel.add(layers.Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', \n                 activation ='relu', input_shape = (28,28,1)))\nmodel.add(layers.Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', \n                 activation ='relu'))\nmodel.add(layers.MaxPool2D(pool_size=(2,2)))\nmodel.add(layers.BatchNormalization())\nmodel.add(layers.Dropout(0.25))\nmodel.add(layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', \n                 activation ='relu'))\nmodel.add(layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', \n                 activation ='relu'))\nmodel.add(layers.MaxPool2D(pool_size=(2,2), strides=(2,2)))\nmodel.add(layers.BatchNormalization())\nmodel.add(layers.Dropout(0.25))\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(256, activation = \"relu\"))\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.BatchNormalization())\nmodel.add(layers.Dense(10, activation = \"softmax\"))\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:09:05.145856Z","iopub.execute_input":"2024-06-11T18:09:05.146365Z","iopub.status.idle":"2024-06-11T18:09:05.611855Z","shell.execute_reply.started":"2024-06-11T18:09:05.146326Z","shell.execute_reply":"2024-06-11T18:09:05.610106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_path = './best_model.h5'\ncheckpointer = ModelCheckpoint(\n    filepath=model_path,\n    monitor='val_accuracy',\n    verbose=1,\n    mode='max',\n    save_best_only=True)\n\nmodel.compile(loss='categorical_crossentropy',\n             optimizer='adam',\n             metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:09:05.614371Z","iopub.execute_input":"2024-06-11T18:09:05.614981Z","iopub.status.idle":"2024-06-11T18:09:05.653756Z","shell.execute_reply.started":"2024-06-11T18:09:05.614929Z","shell.execute_reply":"2024-06-11T18:09:05.651847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Huấn luyện mô hình\nhistory = model.fit(X_train_cnn, y_train_cnn, validation_data = (X_val, Y_val), epochs=100, batch_size = 128, callbacks=[checkpointer])","metadata":{"execution":{"iopub.status.busy":"2024-06-11T18:09:05.655780Z","iopub.execute_input":"2024-06-11T18:09:05.656243Z","iopub.status.idle":"2024-06-11T19:56:44.165618Z","shell.execute_reply.started":"2024-06-11T18:09:05.656205Z","shell.execute_reply":"2024-06-11T19:56:44.162605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\nimport numpy as np\n\nfig = go.Figure()\n\nlabels = ['Loss', 'Accuracy']\ncolors = ['rgb(67,67,67)', 'rgb(49,130,189)']\n\nmode_size = [8, 8]\nline_size = [2, 2]\n\nx_data = np.vstack((np.arange(1, 51),)*2)\n\ny_data = np.array([\n    np.array(history.history['loss']), \n                      np.array(history.history['accuracy'])\n])\n\nfor i in range(0, 2):\n    fig.add_trace(go.Scatter(x=x_data[i], y=y_data[i], mode='lines',\n        name=labels[i],\n        line=dict(color=colors[i], width=line_size[i]),\n        connectgaps=True,\n    ))\n\n    # endpoints\n    fig.add_trace(go.Scatter(\n        x=[x_data[i][0], x_data[i][-1]],\n        y=[y_data[i][0], y_data[i][-1]],\n        mode='markers',\n        marker=dict(color=colors[i], size=mode_size[i])\n    ))\n\nfig.update_layout(\n    xaxis=dict(\n        showline=True,\n        showgrid=False,\n        showticklabels=True,\n        linecolor='rgb(204, 204, 204)',\n        linewidth=2,\n        ticks='outside',\n        tickfont=dict(\n            family='Arial',\n            size=12,\n            color='rgb(82, 82, 82)',\n        ),\n    ),\n    yaxis=dict(\n        showgrid=False,\n        zeroline=False,\n        showline=False,\n        showticklabels=False,\n    ),\n    autosize=False,\n    margin=dict(\n        autoexpand=False,\n        l=100,\n        r=20,\n        t=110,\n    ),\n    showlegend=False,\n    plot_bgcolor='white'\n)\n\nannotations = []\n\n# Adding labels\nfor y_trace, label, color in zip(y_data, labels, colors):\n    # labeling the left_side of the plot\n    annotations.append(dict(xref='paper', x=0.05, y=y_trace[0],\n                                  xanchor='right', yanchor='middle',\n                                  text=label + ' {:.2f}'.format(y_trace[0]),\n                                  font=dict(family='Arial',\n                                            size=16),\n                                  showarrow=False))\n    # labeling the right_side of the plot\n    annotations.append(dict(xref='paper', x=0.95, y=y_trace[99],\n                                  xanchor='left', yanchor='middle',\n                                  text='{:.4f}%'.format(y_trace[99]),\n                                  font=dict(family='Arial',\n                                            size=16),\n                                  showarrow=False))\n# Title\nannotations.append(dict(xref='paper', yref='paper', x=0.0, y=1.05,\n                              xanchor='left', yanchor='bottom',\n                              text='Training Loss & Accuracy',\n                              font=dict(family='Arial',\n                                        size=30,\n                                        color='rgb(37,37,37)'),\n                              showarrow=False))\n# Source\nannotations.append(dict(xref='paper', yref='paper', x=0.5, y=-0.1,\n                              xanchor='center', yanchor='top',\n                              text='Epochs',\n                              font=dict(family='Arial',\n                                        size=12,\n                                        color='rgb(150,150,150)'),\n                              showarrow=False))\n\nfig.update_layout(annotations=annotations,height=600, width=1000)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-11T19:56:44.170483Z","iopub.execute_input":"2024-06-11T19:56:44.171087Z","iopub.status.idle":"2024-06-11T19:56:44.331777Z","shell.execute_reply.started":"2024-06-11T19:56:44.170999Z","shell.execute_reply":"2024-06-11T19:56:44.330483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import load_model\nmodel = load_model('./best_model.h5')\ny_pred = model.predict(X_val)\nM = confusion_matrix(np.argmax(Y_val,1), np.argmax(y_pred,1))\nplot_confusion_matrix(M, sorted(np.unique(np.argmax(Y_val,1))), 'Simple CNN Confusion Matrix, Acc({:.2f}%)'.format(accuracy_score(np.argmax(Y_val,1), np.argmax(y_pred,1))*100))","metadata":{"execution":{"iopub.status.busy":"2024-06-11T19:56:44.333626Z","iopub.execute_input":"2024-06-11T19:56:44.334026Z","iopub.status.idle":"2024-06-11T19:57:23.351904Z","shell.execute_reply.started":"2024-06-11T19:56:44.333994Z","shell.execute_reply":"2024-06-11T19:57:23.350643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Checking Failure Cases","metadata":{}},{"cell_type":"code","source":"n = np.where(np.argmax(y_pred,1)!=np.argmax(Y_val,1))\nn = np.array(n).reshape(-1)\nn","metadata":{"execution":{"iopub.status.busy":"2024-06-11T19:57:23.353840Z","iopub.execute_input":"2024-06-11T19:57:23.354227Z","iopub.status.idle":"2024-06-11T19:57:23.371446Z","shell.execute_reply.started":"2024-06-11T19:57:23.354192Z","shell.execute_reply":"2024-06-11T19:57:23.369880Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_val_vis = np.array(X_val).reshape(X_val.shape[0], 28, 28)\nX_val_vis = X_val_vis\nfig, axis = plt.subplots(int(len(n)/8), 8, figsize=(35, 15))\nfor i, ax in enumerate(axis.flat):\n    ax.imshow(X_val_vis[n[i]], cmap='binary')\n    digit = np.argmax(y_pred,1)[n[i]]\n    digit2 = np.argmax(Y_val,1)[n[i]]\n    ax.set(title = f\"Pred Number is {digit}\\n Real Number is {digit2}\");","metadata":{"execution":{"iopub.status.busy":"2024-06-11T19:57:23.372923Z","iopub.execute_input":"2024-06-11T19:57:23.373415Z","iopub.status.idle":"2024-06-11T20:00:47.714426Z","shell.execute_reply.started":"2024-06-11T19:57:23.373376Z","shell.execute_reply":"2024-06-11T20:00:47.713103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_test = np.array(df_test).reshape(-1,28,28,1)","metadata":{"execution":{"iopub.status.busy":"2024-06-11T20:00:47.716551Z","iopub.execute_input":"2024-06-11T20:00:47.717043Z","iopub.status.idle":"2024-06-11T20:00:47.798806Z","shell.execute_reply.started":"2024-06-11T20:00:47.716997Z","shell.execute_reply":"2024-06-11T20:00:47.797657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = load_model('./best_model.h5')\ny_pred = model.predict(X_test)\ny_pred = np.argmax(y_pred,1)\npd_submit = pd.read_csv('../input/digit-recognizer/sample_submission.csv')\npd_submit['Label'] = y_pred\npd_submit.to_csv('submission.csv', header=True, index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-11T20:00:47.800219Z","iopub.execute_input":"2024-06-11T20:00:47.800760Z","iopub.status.idle":"2024-06-11T20:01:13.808460Z","shell.execute_reply.started":"2024-06-11T20:00:47.800720Z","shell.execute_reply":"2024-06-11T20:01:13.807304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"border-radius: 10px; border: #4361EE solid; padding: 15px; background-color: #ffffff00; font-size: 100%; text-align: left;\">\n    <ul>\n        <li>MNIST database. (2023, September 8). In Wikipedia. [<a href=https://en.wikipedia.org/wiki/MNIST_database>LINK</a>]</li>\n        <li>Principal component analysis. (2023, November 18). In Wikipedia. [<a href=https://en.wikipedia.org/wiki/Principal_component_analysis>LINK</a>]</li>\n        <li>PCA, scikit-learn documentation. [<a href=https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html>LINK</a>]\n        <li>K. (2023, September 27). In Wikipedia. [<a href=https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm>LINK</a>]</li>\n        <li>KNNeighborsClassifier, scikit-learn documentation. [<a href=https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier>LINK</a>]</li>\n    </ul>\n</div>","metadata":{"_uuid":"ba488a1a-be81-42a7-8169-c106278b9f85","_cell_guid":"7d3e9231-c38d-42ac-ae5b-8c18407ec2ff","trusted":true}}]}