{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":16017,"databundleVersionId":708189,"sourceType":"competition"}],"dockerImageVersionId":30715,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-01T09:38:35.255271Z","iopub.execute_input":"2024-06-01T09:38:35.255791Z","iopub.status.idle":"2024-06-01T09:38:36.678459Z","shell.execute_reply.started":"2024-06-01T09:38:35.255732Z","shell.execute_reply":"2024-06-01T09:38:36.675987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix\nfrom torch.optim.lr_scheduler import StepLR","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:38:41.051447Z","iopub.execute_input":"2024-06-01T09:38:41.051861Z","iopub.status.idle":"2024-06-01T09:38:47.370829Z","shell.execute_reply.started":"2024-06-01T09:38:41.051820Z","shell.execute_reply":"2024-06-01T09:38:47.369701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train=pd.read_csv('/kaggle/input/Kannada-MNIST/train.csv')\ntest=pd.read_csv('/kaggle/input/Kannada-MNIST/test.csv')\nprint(train.shape)\nprint(test.shape)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:40:05.519881Z","iopub.execute_input":"2024-06-01T09:40:05.520350Z","iopub.status.idle":"2024-06-01T09:40:11.573169Z","shell.execute_reply.started":"2024-06-01T09:40:05.520317Z","shell.execute_reply":"2024-06-01T09:40:11.571938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#数据预处理\ndef data_prep(raw):\n    nums=raw.shape[0]\n    image_1d_list=raw.values[:,1:]\n    image_2d_list=image_1d_list.reshape(nums,28,28,1)\n    label_list=raw.values[:,0]\n    return image_2d_list,label_list\nimage_list,label_list=data_prep(train)\nimage_train_list,image_test_list,label_train_list,label_test_list=train_test_split(image_list,label_list,test_size=0.2, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:40:23.835348Z","iopub.execute_input":"2024-06-01T09:40:23.835855Z","iopub.status.idle":"2024-06-01T09:40:24.527704Z","shell.execute_reply.started":"2024-06-01T09:40:23.835806Z","shell.execute_reply":"2024-06-01T09:40:24.526251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#绘图\ndef draw_pics(image_list,label_list):\n    for i in range(10):\n        imgs=[]\n        for index,label in enumerate(label_list):\n            if label==i:\n                imgs.append(image_list[index])\n        for index,img in enumerate(imgs):\n            if index==5:\n                break\n            plt.subplot(5,10,i+index*10+1)\n            plt.imshow(imgs[index], cmap='gray')\n            plt.axis(\"off\")   ","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:40:32.647419Z","iopub.execute_input":"2024-06-01T09:40:32.647907Z","iopub.status.idle":"2024-06-01T09:40:32.658152Z","shell.execute_reply.started":"2024-06-01T09:40:32.647870Z","shell.execute_reply":"2024-06-01T09:40:32.656829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#LeNet\nclass LeNet(nn.Module):\n    def __init__(self):\n        super(LeNet, self).__init__()\n        self.conv1 = nn.Conv2d(1, 6, 5)   # 第一个卷积层，输入通道为1，输出通道为6，卷积核大小为5x5\n        self.conv2 = nn.Conv2d(6, 16, 5)  # 第二个卷积层，输入通道为6，输出通道为16，卷积核大小为5x5\n        self.fc1 = nn.Linear(16*4*4, 120)  # 第一个全连接层，输入大小为16*4*4，输出大小为120\n        self.fc2 = nn.Linear(120, 84)      # 第二个全连接层，输入大小为120，输出大小为84\n        self.fc3 = nn.Linear(84, 10)       # 输出层，输入大小为84，输出大小为10\n\n    def forward(self, x):\n        x = torch.relu(self.conv1(x))   # 第一个卷积层的激活函数为ReLU\n        x = torch.max_pool2d(x, 2)      # 最大池化层，核大小为2x2\n        x = torch.relu(self.conv2(x))   # 第二个卷积层的激活函数为ReLU\n        x = torch.max_pool2d(x, 2)      # 最大池化层，核大小为2x2\n        x = x.view(-1, 16*4*4)          # 将特征图展平成一维向量\n        x = torch.relu(self.fc1(x))     # 第一个全连接层的激活函数为ReLU\n        x = torch.relu(self.fc2(x))     # 第二个全连接层的激活函数为ReLU\n        x = self.fc3(x)                # 输出层不使用激活函数\n        return x","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:40:42.477466Z","iopub.execute_input":"2024-06-01T09:40:42.477976Z","iopub.status.idle":"2024-06-01T09:40:42.490969Z","shell.execute_reply.started":"2024-06-01T09:40:42.477937Z","shell.execute_reply":"2024-06-01T09:40:42.489891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#训练函数\ndef KannadaTrain(model, criterion, optimizer, trainloader, epochs=5):\n    losses = []\n    for epoch in range(epochs):\n        running_loss = 0.0\n        for i, data in enumerate(trainloader):\n            inputs, labels = data#获取输入数据及对应的标签\n            optimizer.zero_grad()       # 梯度清零\n            outputs = model(inputs)     # 前向传播，调用cnn中的forward，计算出结果\n            loss = criterion(outputs, labels)  # 计算损失，利用交叉熵计算损失\n            loss.backward()            # 对损失进行反向传播，计算损失函数对模型参数的梯度\n            optimizer.step()\n            running_loss += loss.item()\n        losses.append(running_loss / len(trainloader))#第i次训练的交叉熵损失\n        print(f\"Epoch {epoch+1}, Loss: {running_loss / len(trainloader)}\")\n    return losses","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:40:52.489547Z","iopub.execute_input":"2024-06-01T09:40:52.489961Z","iopub.status.idle":"2024-06-01T09:40:52.498464Z","shell.execute_reply.started":"2024-06-01T09:40:52.489932Z","shell.execute_reply":"2024-06-01T09:40:52.497138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#组建dataloader\nclass KannadaDataset(Dataset):\n\n    def __init__(self, images, labels):\n        self.images = images\n        self.labels = labels\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        image = self.images[idx].reshape(1, 28, 28).astype('float32')\n        label = self.labels[idx]\n        return image, label\ntrain_dataset=KannadaDataset(image_train_list,label_train_list)\ntrain_dataloader = DataLoader(train_dataset, batch_size=100, shuffle=True)\ntest_dataset=KannadaDataset(image_test_list,label_test_list)\ntest_dataloader=DataLoader(test_dataset, batch_size=100, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:41:48.186065Z","iopub.execute_input":"2024-06-01T09:41:48.186463Z","iopub.status.idle":"2024-06-01T09:41:48.196315Z","shell.execute_reply.started":"2024-06-01T09:41:48.186435Z","shell.execute_reply":"2024-06-01T09:41:48.194990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#开始训练\nmodel = LeNet()\noptimizer = optim.SGD(model.parameters(), lr=0.001)\ncriterion = nn.CrossEntropyLoss()#创建损失函数为交叉熵\nlosses= KannadaTrain(model, criterion, optimizer, train_dataloader,100)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:41:51.315805Z","iopub.execute_input":"2024-06-01T09:41:51.316238Z","iopub.status.idle":"2024-06-01T09:51:38.741106Z","shell.execute_reply.started":"2024-06-01T09:41:51.316205Z","shell.execute_reply":"2024-06-01T09:51:38.739752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#可视化指标\ndef plot_losses(losses):\n    plt.plot(losses)\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.title('Training Loss Curve')\n    plt.show()\nplot_losses(losses)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:51:43.116573Z","iopub.execute_input":"2024-06-01T09:51:43.117026Z","iopub.status.idle":"2024-06-01T09:51:43.434617Z","shell.execute_reply.started":"2024-06-01T09:51:43.116992Z","shell.execute_reply":"2024-06-01T09:51:43.433475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#评估模型\ndef evaluate_model(model, testloader):\n    model.eval()  # 设置模型为评估模式，模型不会梯度计算，不会更新参数\n    y_true = []\n    y_pred = []\n    with torch.no_grad():\n        for data in testloader:\n            images, labels = data\n            outputs = model(images)   # 前向传播\n            _, predicted = torch.max(outputs, 1)  # 获取预测结果，返回向量第一列10维中最大的数字及其索引，_代表不关心第一个返回值\n            y_true.extend(labels.numpy())   # 将真实标签添加到列表中\n            y_pred.extend(predicted.numpy())   # 将预测标签添加到列表中\n\n    accuracy = accuracy_score(y_true, y_pred)   # 计算准确率\n    precision = precision_score(y_true, y_pred, average='macro')   # 计算精确率\n    recall = recall_score(y_true, y_pred, average='macro')   # 计算召回率\n    f1 = f1_score(y_true, y_pred, average='macro')   # 计算F1分数\n    conf_matrix = confusion_matrix(y_true, y_pred)   # 计算混淆矩阵\n    return accuracy, precision, recall, f1, conf_matrix","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:51:47.577623Z","iopub.execute_input":"2024-06-01T09:51:47.578095Z","iopub.status.idle":"2024-06-01T09:51:47.588537Z","shell.execute_reply.started":"2024-06-01T09:51:47.578062Z","shell.execute_reply":"2024-06-01T09:51:47.586913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#评估模型的混淆矩阵可视化\naccuracy, precision, recall, f1, conf_matrix=evaluate_model(model, test_dataloader)\nprint(f\"Accuracy: {accuracy}\")\nprint(f\"Precision: {precision}\")\nprint(f\"Recall: {recall}\")\nprint(f\"F1: {f1}\")\nplt.matshow(conf_matrix, cmap='viridis')  # 绘制混淆矩阵\nplt.colorbar()  # 显示颜色条\nplt.xlabel('Predicted label')\nplt.ylabel('True label')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:51:51.097355Z","iopub.execute_input":"2024-06-01T09:51:51.097858Z","iopub.status.idle":"2024-06-01T09:51:52.586825Z","shell.execute_reply.started":"2024-06-01T09:51:51.097818Z","shell.execute_reply":"2024-06-01T09:51:52.585351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#目的：分类kannada手写数字\ntarget_label=[]\nnums=test.shape[0]\ntarget_1d_list=test.values[:,1:]\ntarget_2d_list=target_1d_list.reshape(nums,28,28,1)\nfor image in target_2d_list:\n    target=image.reshape(1, 28, 28).astype('float32')\n    target= torch.from_numpy(target)\n    output = model(target)\n    _, predicted = torch.max(output, 1)\n    target_label.append(predicted.item())  ","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:51:56.226191Z","iopub.execute_input":"2024-06-01T09:51:56.226609Z","iopub.status.idle":"2024-06-01T09:51:59.577045Z","shell.execute_reply.started":"2024-06-01T09:51:56.226580Z","shell.execute_reply":"2024-06-01T09:51:59.576051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#输出\nresult=[]\nfor index, value in enumerate(target_label):\n    result.append([index,value])\nfile_path = 'submission.csv'\ndf = pd.DataFrame(result, columns=['id', 'label'])\ndf.to_csv(file_path, index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:52:01.741495Z","iopub.execute_input":"2024-06-01T09:52:01.742155Z","iopub.status.idle":"2024-06-01T09:52:01.777543Z","shell.execute_reply.started":"2024-06-01T09:52:01.742118Z","shell.execute_reply":"2024-06-01T09:52:01.775893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"draw_pics(target_2d_list,target_label)","metadata":{"execution":{"iopub.status.busy":"2024-06-01T09:52:19.642359Z","iopub.execute_input":"2024-06-01T09:52:19.642880Z","iopub.status.idle":"2024-06-01T09:52:21.723101Z","shell.execute_reply.started":"2024-06-01T09:52:19.642838Z","shell.execute_reply":"2024-06-01T09:52:21.721425Z"},"trusted":true},"execution_count":null,"outputs":[]}]}