From d294ac0e389b2c551d4b03450127de2bd6ae88b3 Mon Sep 17 00:00:00 2001 From: Yadunand Prem Date: Mon, 29 Apr 2024 12:45:46 +0800 Subject: [PATCH] feat: idek anymore --- cs2109s/labs/final/final.py | 44 +-- cs2109s/labs/final/main.ipynb | 64 +++-- cs2109s/labs/final/scratchpad.ipynb | 407 ++++++++++++++++++++++++---- 3 files changed, 417 insertions(+), 98 deletions(-) diff --git a/cs2109s/labs/final/final.py b/cs2109s/labs/final/final.py index 311373c..27b4795 100644 --- a/cs2109s/labs/final/final.py +++ b/cs2109s/labs/final/final.py @@ -16,6 +16,7 @@ from torch import nn import numpy as np import torch import os +from torchvision.transforms.functional import equalize class CNN3D(nn.Module): def __init__(self, hidden_size=32, dropout=0.0): @@ -27,7 +28,7 @@ class CNN3D(nn.Module): self.maxpool = nn.MaxPool3d(kernel_size=2, stride=2) self.fc1 = nn.Linear(hidden_size*32, 256) # Calculate input size based on output from conv3 self.fc2 = nn.Linear(256, 6) - self.dropout = nn.Dropout(dropout) + # self.dropout = nn.Dropout(dropout) def forward(self, x): x = self.conv1(x) @@ -37,7 +38,7 @@ class CNN3D(nn.Module): x = self.conv2(x) x = self.relu(x) x = self.maxpool(x) - x = self.dropout(x) + # x = self.dropout(x) x = x.view(x.size(0), -1) # Flatten features for fully connected layers x = self.fc1(x) @@ -56,17 +57,16 @@ def train(model, criterion, optimizer, loader, epochs=5): print(f'Epoch {epoch}, Loss: {loss.item()}') return model - - - class Model(): - def __init__(self, batch_size=8,lr=0.001,epochs=10, dropout=0.0, hidden_size=32): + def __init__(self, batch_size=64,lr=0.001,epochs=5, dropout=0.0, hidden_size=32, n_samples=900): + print(batch_size, epochs, lr, dropout, hidden_size, n_samples) self.batch_size = batch_size self.lr = lr self.epochs = epochs self.model = CNN3D(dropout=dropout, hidden_size=hidden_size) self.criterion = nn.CrossEntropyLoss() self.optimizer = torch.optim.Adam(self.model.parameters(), lr=self.lr) + self.n_samples = n_samples def fit(self, X, y): X, y = self.process_data(X, y) @@ -81,31 +81,25 @@ class Model(): tensor_videos = torch.tensor(X, dtype=torch.float32) # Clip values to 0 and 255 tensor_videos = np.clip(tensor_videos, 0, 255) - # TEMP - threshold = 180 - tensor_videos[tensor_videos > threshold] = 255 - tensor_videos[tensor_videos < threshold] = 0 - # END TEMP # Replace NaNs in each frame, with the average of the frame. This was generated with GPT for i in range(tensor_videos.shape[0]): for j in range(tensor_videos.shape[1]): tensor_videos[i][j][torch.isnan(tensor_videos[i][j])] = torch.mean( tensor_videos[i][j][~torch.isnan(tensor_videos[i][j])]) - X = torch.Tensor(tensor_videos.unsqueeze(1)) - result = self.model(X) + # tensor_videos = torch.Tensor(tensor_videos).to(torch.uint8).reshape(-1, 1, 16, 16) + # tensor_videos = equalize(tensor_videos).float().reshape(-1, 1, 6, 16, 16) + tensor_videos = torch.Tensor(tensor_videos).reshape(-1, 1, 6, 16, 16) + # some funky code to make the features more prominent + + result = self.model(tensor_videos) return torch.max(result, dim=1)[1].numpy() - def process_data(self, X, y, n_samples=600): + def process_data(self, X, y): y = np.array(y) X = np.array([video[:6] for video in X]) tensor_videos = torch.tensor(X, dtype=torch.float32) # Clip values to 0 and 255 tensor_videos = np.clip(tensor_videos, 0, 255) - # TEMP - threshold = 180 - tensor_videos[tensor_videos > threshold] = 255 - tensor_videos[tensor_videos < threshold] = 0 - # END TEMP # Replace NaNs in each frame, with the average of the frame. This was generated with GPT for i in range(tensor_videos.shape[0]): @@ -118,13 +112,19 @@ class Model(): indices = [np.argwhere(y == i).squeeze(1) for i in range(6)] # Get the number of samples to take for each class # Get the indices of the samples to take - indices_to_take = [np.random.choice(indices[i], n_samples, replace=True) for i in range(6)] + indices_to_take = [np.random.choice(indices[i], self.n_samples, replace=True) for i in range(6)] # Concatenate the indices indices_to_take = np.concatenate(indices_to_take) # Select the samples - tensor_videos = tensor_videos[indices_to_take].unsqueeze(1) + tensor_videos = tensor_videos[indices_to_take] + + tensor_videos = torch.Tensor(tensor_videos).reshape(-1, 1, 6, 16, 16) + # Reshape the tensor to int for image processing + # tensor_videos = torch.Tensor(tensor_videos).to(torch.uint8).reshape(-1, 1, 16, 16) + # tensor_videos = equalize(tensor_videos).float().reshape(-1, 1, 6, 16, 16) + y = y[indices_to_take] - return torch.Tensor(tensor_videos), torch.Tensor(y).long() + return tensor_videos, torch.Tensor(y).long() X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1) diff --git a/cs2109s/labs/final/main.ipynb b/cs2109s/labs/final/main.ipynb index 15c8937..aec4b4a 100644 --- a/cs2109s/labs/final/main.ipynb +++ b/cs2109s/labs/final/main.ipynb @@ -315,12 +315,12 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 10, "id": "a44b7aa4", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T12:00:17.228662Z", - "start_time": "2024-04-28T12:00:17.209494Z" + "end_time": "2024-04-28T12:27:25.926991Z", + "start_time": "2024-04-28T12:27:25.917322Z" } }, "outputs": [], @@ -406,8 +406,8 @@ " def fit(self, X, y):\n", " X, y = process_data(X, y)\n", " train_dataset = torch.utils.data.TensorDataset(X, y)\n", - " train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)\n", - " train(self.model, self.criterion, self.optimizer, train_loader, 10)\n", + " train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)\n", + " train(self.model, self.criterion, self.optimizer, train_loader, 20)\n", "\n", " def predict(self, X):\n", " self.model.eval()\n", @@ -438,12 +438,12 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 2, "id": "4f4dd489", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T12:00:19.363096Z", - "start_time": "2024-04-28T12:00:19.352424Z" + "end_time": "2024-04-28T12:09:46.115322Z", + "start_time": "2024-04-28T12:09:45.631452Z" } }, "outputs": [], @@ -458,12 +458,12 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 3, "id": "3064e0ff", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T12:00:20.265060Z", - "start_time": "2024-04-28T12:00:20.234748Z" + "end_time": "2024-04-28T12:09:47.340881Z", + "start_time": "2024-04-28T12:09:47.317719Z" } }, "outputs": [], @@ -477,12 +477,12 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 12, "id": "27c9fd10", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T12:00:37.185569Z", - "start_time": "2024-04-28T12:00:22.239036Z" + "end_time": "2024-04-28T12:28:29.269402Z", + "start_time": "2024-04-28T12:28:02.494602Z" } }, "outputs": [ @@ -490,19 +490,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "Epoch 0, Loss: 0.7495917081832886\n", - "Epoch 1, Loss: 0.42713749408721924\n", - "Epoch 2, Loss: 0.21424821019172668\n", - "Epoch 3, Loss: 0.02086367830634117\n", - "Epoch 4, Loss: 0.005386564414948225\n", - "Epoch 5, Loss: 0.00319607718847692\n", - "Epoch 6, Loss: 0.007663913071155548\n", - "Epoch 7, Loss: 0.003004509722813964\n", - "Epoch 8, Loss: 0.0044013322331011295\n", - "Epoch 9, Loss: 0.0016760551370680332\n", - "F1 Score (macro): 0.75\n", - "CPU times: user 57.8 s, sys: 1min 12s, total: 2min 10s\n", - "Wall time: 14.9 s\n" + "Epoch 0, Loss: 0.5610745549201965\n", + "Epoch 1, Loss: 0.22023160755634308\n", + "Epoch 2, Loss: 0.03679683431982994\n", + "Epoch 3, Loss: 0.009054183959960938\n", + "Epoch 4, Loss: 0.0021134500857442617\n", + "Epoch 5, Loss: 0.002705463906750083\n", + "Epoch 6, Loss: 0.0045105633325874805\n", + "Epoch 7, Loss: 0.001958428416401148\n", + "Epoch 8, Loss: 0.0010891605634242296\n", + "Epoch 9, Loss: 0.0010821395553648472\n", + "Epoch 10, Loss: 0.0007317279814742506\n", + "Epoch 11, Loss: 0.0006673489115200937\n", + "Epoch 12, Loss: 0.00047141974209807813\n", + "Epoch 13, Loss: 0.00024128056247718632\n", + "Epoch 14, Loss: 0.0003150832490064204\n", + "Epoch 15, Loss: 0.0004005862574558705\n", + "Epoch 16, Loss: 0.00024190203112084419\n", + "Epoch 17, Loss: 0.0004451812419574708\n", + "Epoch 18, Loss: 0.000376795680494979\n", + "Epoch 19, Loss: 0.0003616203321143985\n", + "F1 Score (macro): 0.65\n", + "CPU times: user 2min 33s, sys: 255 ms, total: 2min 34s\n", + "Wall time: 26.8 s\n" ] } ], diff --git a/cs2109s/labs/final/scratchpad.ipynb b/cs2109s/labs/final/scratchpad.ipynb index 602d5f6..f014c4e 100644 --- a/cs2109s/labs/final/scratchpad.ipynb +++ b/cs2109s/labs/final/scratchpad.ipynb @@ -39,54 +39,52 @@ "id": "9c14a2d8", "metadata": {}, "source": [ - "**[TODO]**\n", - "\n", - "Please provide a summary of the ideas and steps that led you to your final model. Someone reading this summary should understand why you chose to approach the problem in a particular way and able to replicate your final model at a high level. Please ensure that your summary is detailed enough to provide an overview of your thought process and approach but also concise enough to be easily understandable. Also, please follow the guidelines given in the `main.ipynb`.\n", - "\n", - "This report should not be longer than **1-2 pages of A4 paper (up to around 1,000 words)**. Marks will be deducted if you do not follow instructions and you include too many words here. \n", - "\n", - "**[DELETE EVERYTHING FROM THE PREVIOUS TODO TO HERE BEFORE SUBMISSION]**\n", - "\n", "##### Overview\n", - "**[TODO]**\n", + "https://chat.openai.com/share/ec6c6778-d7cc-48e2-98d1-24b7f6a6a769\n", "\n", "##### 1. Descriptive Analysis\n", - "**[TODO]**\n", + "At the start, I *did* not read the main.ipynb and jumped straight into teh scratchpad to read the data directly. After fiddling with the data for about an hour, being confused about the variable n (6-10) x 16 x 16 images, I decided to read the main.ipynb fully. I then realised that the data was a list of videos. With that in mind, I decided to plot out the images. However, on first observation, I did not come to realise teh images as japanese characters. I only came to this understanding at 9.30PM on Sunday.\n", "\n", "##### 2. Detection and Handling of Missing Values\n", - "**[TODO]**\n", + "There were quite a few NaNs for both the X and y values. Initially, I considered the y NaNs as a class of its own. On further reading of teh main file, I realised that the Nans were not a class, but rows to be removed. After filtering out the y values, there was still the X values to consider. Initially, to get a quick model out, I decided to zero out the values. In the end, I decided to replace the NaNs with the average of the frame. This was done by iterating through each frame, and replacing the NaNs with the average of the frame. This was done with the assistance of GPT for the code generation.\n", "\n", "##### 3. Detection and Handling of Outliers\n", - "**[TODO]**\n", + "There were quite a few outliers in teh dataset, which strayed away from the general min and max of 0 and 255. To resolve this, I used the np.clip(X, 0, 255) to upper bound and lowerbound the values. I did some experimentation with trying to make the different values more distinct, but this was not successful. With some rudimentary code, I was able to improve the performance of teh detection, somewhat, but it was not very consistent. \n", + "\n", + "I decided to use equalize also, which should make the data more prominent. However, with the equalize method, I hit time limit, and was not able to use that. \n", "\n", "##### 4. Detection and Handling of Class Imbalance \n", - "**[TODO]**\n", + "There was heavy class imbalance in the dataset. This was fixed with sampling the data. I used both upsampling and downsampling, where I upsampled data when it didn't hit the minimum I needed from each class, and downsampled data when it exceeded the maximum I needed from each class. \n", "\n", "##### 5. Understanding Relationship Between Variables\n", - "**[TODO]**\n", + "This analysis was not particularly done. Since I was processing it as images, I didn't plan to use dimentionality reduction techniques or other means. \n", + "\n", "\n", "##### 6. Data Visualization\n", - "**[TODO]** \n", + "The data visualisation can be seen below. Generally, I used data visualisation to directly see the images, and also see the distribution of the classes. \n", + "\n", + "Visualization was also helpful in viewing the outliers, especially with boxplots. However, I didn't use visualiastions to inspect the model output. \n", "##### 7. General Preprocessing\n", - "**[TODO]**\n", + "The general preprocessing was done by reducing the data to 6 frames, and then processing the data to remove NaNs and clip the values. The data was then sampled to `600` elements, (which was obtained through hyperparameter optimisation). \n", " \n", "##### 8. Feature Selection \n", - "**[TODO]**\n", + "NO feature selection and engineering was done, generally the entire dataset was used. NaN values were replaced by frame averages. \n", "\n", "##### 9. Feature Engineering\n", - "**[TODO]**\n", + "No featuer engineering was also done. \n", "\n", "##### 10. Creating Models\n", - "**[TODO]**\n", - "\n", + "The model that I eventually came up with after a lot of experimentation is a 2 layer CNN. I had experimented with a CNN -> RNN, but that didn't work very well. The first model I had created was a 2D CNN, but I struggled with mapping the Videos to a stream of photos effectively. I then created a 1 layer conv3d model, and that gave me a solid result. I then experimented with the possible 2nd layers for the model. I first used LSTM, as I thought that since this was video data, it would be more effective. However, the LSTM model did not give good results. I am predicting this is due to bad hyperparameter optimisation. When I switched the 2nd layer to another 3D CNN, it worked quite well. Implementing batch normalization also improved the results greatly. \n", "##### 11. Model Evaluation\n", - "**[TODO]**\n", + "The model was evaludated using F1. I averaged out the results of 3 runs of the model with F1 before I decided to finalize this. \n", "\n", "##### 12. Hyperparameters Search\n", - "**[TODO]**\n", + "Optuna was used to search for hyperparameters. Learning this library was quite useful. However, I wasn't able to optimally implement this, due to large variances when running hte model multiple times. Figuring out how to take the average value of multiple runs for each parameter search would have been useful to find the most optimal parameters. I mainly used this to find parameters for lr, hidden layers and batch size. I wasn't able to use it optimally due to time constraints too. \n", "\n", "##### Conclusion\n", - "**[TODO]**" + "I spent way too long due to a bad understanding of a lot of concepts in AI. This exam helped me to learn a lot of stuff that we had used in class, but didn't fully understand. For example, in the psets, a lot of the code writing was very machanical. But this exam allowed us to be creative and problem solve. However, it would have been nicer if the duration was much shorter. \n", + "\n", + "The main aspects I struggled with was trying to figure out what to with the videos. The initial method of processing them as just images was not very effective. This was mainly due to my inability to code out a solution well. " ] }, { @@ -156,12 +154,12 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 267, "id": "6297e25a", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T06:46:52.453152Z", - "start_time": "2024-04-28T06:46:52.428539Z" + "end_time": "2024-04-28T13:26:08.028976Z", + "start_time": "2024-04-28T13:26:08.014557Z" } }, "outputs": [ @@ -205,40 +203,124 @@ }, { "cell_type": "code", - "execution_count": 44, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import torch\n", + "\n", + "def show_images(images, n_row=5, n_col=5, figsize=[12,12]):\n", + " _, axs = plt.subplots(n_row, n_col, figsize=figsize)\n", + " axs = axs.flatten()\n", + " for img, ax in zip(images, axs):\n", + " ax.imshow(img, cmap='gray')\n", + " plt.show()" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2024-04-28T15:03:57.588510Z", + "start_time": "2024-04-28T15:03:57.585485Z" + } + }, + "id": "f8155151c5e660f5", + "execution_count": 330 + }, + { + "cell_type": "code", + "execution_count": 338, "id": "3b1f62dd", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T06:46:52.472306Z", - "start_time": "2024-04-28T06:46:52.454360Z" + "end_time": "2024-04-28T15:07:52.672987Z", + "start_time": "2024-04-28T15:07:51.997288Z" } }, "outputs": [ { - "ename": "ValueError", - "evalue": "setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2250,) + inhomogeneous part.", - "output_type": "error", - "traceback": [ - "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[0;31mValueError\u001B[0m Traceback (most recent call last)", - "Cell \u001B[0;32mIn[44], line 10\u001B[0m\n\u001B[1;32m 8\u001B[0m X6 \u001B[38;5;241m=\u001B[39m np\u001B[38;5;241m.\u001B[39marray([video[:\u001B[38;5;241m6\u001B[39m] \u001B[38;5;28;01mfor\u001B[39;00m video \u001B[38;5;129;01min\u001B[39;00m X])\n\u001B[1;32m 9\u001B[0m \u001B[38;5;66;03m# Now that they are consistent, we can convert them to a numpy array\u001B[39;00m\n\u001B[0;32m---> 10\u001B[0m X6 \u001B[38;5;241m=\u001B[39m \u001B[43mnp\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43marray\u001B[49m\u001B[43m(\u001B[49m\u001B[43mX\u001B[49m\u001B[43m)\u001B[49m\n", - "\u001B[0;31mValueError\u001B[0m: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2250,) + inhomogeneous part." + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([6, 1, 16, 16])\n" + ] + }, + { + "data": { + "text/plain": "
", + "image/png": "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CZG+ffvK6tWrTacGoAWgIwBYoScAWKEnALhDRwCwQk8A0DJeMCkvL5cBAwbI4sWLm91m7NixUlhYWH9at26d2/9z69atMmXKFJk+fbrs3r1bpk+fLjfffLP68xUB+A8dAcAKPQHACj0BwB06AoAVegKAlvG382VkZEhGRobbbUJCQoy+CHPRokUyevRoyczMFBGRzMxMycrKkkWLFsmrr75qOkUAfkRHALBCTwCwQk8AcIeOAGCFngCg5ZXvMNm8ebN07dpVevXqJXfeeacUFxe73X7r1q2Snp7e4LIxY8bIJ5980mymsrJSnE5ngxOAwEBHALBCTwCwQk8AcMcXHSFCTwCBjGMJAE3x+IJJRkaGvPzyy/LBBx/IX/7yF9m+fbtce+21UllZ2WymqKhIoqKiGlwWFRUlRUVFzWYWLFggkZGR9ae4uDiPXQcA3kNHALBCTwCwQk8AcMdXHSFCTwCBimMJAM0x/kguK1OmTKn/d//+/WXQoEGSkJAga9eulQkTJjSbczgcDc67XK5Gl50rMzNT5syZU3/e6XRSOkAAoCMAWKEnAFihJwC446uOEKEngEDFsQSA5nh8weR8MTExkpCQILm5uc1uEx0d3Wg1tri4uNGq7blCQkIkJCTEY/ME4B90BAAr9AQAK/QEAHe81REi9ARwqeBYAkAdr3yHybmOHz8uBQUFEhMT0+w2aWlpsmHDhgaXrV+/XoYOHert6QHwMzoCgBV6AoAVegKAO3QEACv0BIA6xu8wKSsrk4MHD9afz8vLk5ycHOnYsaN07NhR5s+fLxMnTpSYmBj56quv5De/+Y107txZbrrppvrMrbfeKt26dZMFCxaIiMj9998v11xzjTz66KNy4403yptvvikbN26Ujz76yANXEYAv0REArNATAKzQEwDcoSMAWKEnAGgZL5js2LFDRo4cWX++7nP4ZsyYIU8//bTs2bNHli9fLqdOnZKYmBgZOXKkrFixQsLDw+sz+fn50qrVf97cMnToUHnttdfkt7/9rfzud7+T5ORkWbFihQwePPhirhsAP6AjAFihJwBYoScAuENHALBCTwDQMl4wGTFihLhcrmZ//t5771n+H5s3b2502aRJk2TSpEmm06lXNyen02mcbd26tXrclu706dOqnGY/XozS0lJV7uzZs6pceXm5KqfZL9qxtHx13ep+Z+f3waXY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" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": "
", + "image/png": "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CZG+ffvK6tWrTacGoAWgIwBYoScAWKEnALhDRwCwQk8A0DJeMCkvL5cBAwbI4sWLm91m7NixUlhYWH9at26d2/9z69atMmXKFJk+fbrs3r1bpk+fLjfffLP68xUB+A8dAcAKPQHACj0BwB06AoAVegKAlvG382VkZEhGRobbbUJCQoy+CHPRokUyevRoyczMFBGRzMxMycrKkkWLFsmrr75qOkUAfkRHALBCTwCwQk8AcIeOAGCFngCg5ZXvMNm8ebN07dpVevXqJXfeeacUFxe73X7r1q2Snp7e4LIxY8bIJ5980mymsrJSnE5ngxOAwEBHALBCTwCwQk8AcMcXHSFCTwCBjGMJAE3x+IJJRkaGvPzyy/LBBx/IX/7yF9m+fbtce+21UllZ2WymqKhIoqKiGlwWFRUlRUVFzWYWLFggkZGR9ae4uDiPXQcA3kNHALBCTwCwQk8AcMdXHSFCTwCBimMJAM0x/kguK1OmTKn/d//+/WXQoEGSkJAga9eulQkTJjSbczgcDc67XK5Gl50rMzNT5syZU3/e6XRSOkAAoCMAWKEnAFihJwC446uOEKEngEDFsQSA5nh8weR8MTExkpCQILm5uc1uEx0d3Wg1tri4uNGq7blCQkIkJCTEY/ME4B90BAAr9AQAK/QEAHe81REi9ARwqeBYAkAdr3yHybmOHz8uBQUFEhMT0+w2aWlpsmHDhgaXrV+/XoYOHert6QHwMzoCgBV6AoAVegKAO3QEACv0BIA6xu8wKSsrk4MHD9afz8vLk5ycHOnYsaN07NhR5s+fLxMnTpSYmBj56quv5De/+Y107txZbrrppvrMrbfeKt26dZMFCxaIiMj9998v11xzjTz66KNy4403yptvvikbN26Ujz76yANXEYAv0REArNATAKzQEwDcoSMAWKEnAGgZL5js2LFDRo4cWX++7nP4ZsyYIU8//bTs2bNHli9fLqdOnZKYmBgZOXKkrFixQsLDw+sz+fn50qrVf97cMnToUHnttdfkt7/9rfzud7+T5ORkWbFihQwePPhirhsAP6AjAFihJwBYoScAuENHALBCTwDQMl4wGTFihLhcrmZ//t5771n+H5s3b2502aRJk2TSpEmm06lXNyen02mcbd26tXrclu706dOqnGY/XozS0lJV7uzZs6pceXm5KqfZL9qxtHx13ep+Z+f3waXY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" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tensor([227, 255, 255, 255, 212, 242, 255, 255, 247, 255, 255, 255, 208, 231,\n", + " 230, 223], dtype=torch.uint8)\n", + "[227. 255. 255. 255. 212. 242. 255. 255. 247. 255. 255. 255. 208. 231.\n", + " 230. 223.]\n" ] } ], "source": [ - "# Remove nans from the input. This needs to be done in the model for training data as well\n", + "# Remove NaN's from the input\n", + "import torchvision\n", "not_nan_indices = np.argwhere(~np.isnan(np.array(y))).squeeze()\n", "y = [y[i] for i in not_nan_indices]\n", "X = [X[i] for i in not_nan_indices]\n", - "y = np.array(y).astype(int)\n", + "# Plot each image in a row\n", + "tmp = X[0][:6].copy()\n", + "# Set 255 to all values in X which are greater than 120\n", + "# Set 0 to all values in X which are less than 100\n", "\n", - "# Since each video varies in length, we will take the min length, 6, for each video\n", - "X6 = np.array([video[:6] for video in X])\n", - "# Now that they are consistent, we can convert them to a numpy array\n", - "X6 = np.array(X)\n" + "tmp = np.array(tmp)\n", + "tmp = np.nan_to_num(tmp, 0)\n", + "tmp = np.clip(tmp, 0, 255)\n", + "tensor = torch.Tensor(tmp)\n", + "tensor = tensor.to(torch.uint8).reshape(-1, 1, 16, 16)\n", + "print(tensor.shape)\n", + "tensor = torchvision.transforms.functional.equalize(tensor)\n", + "tensor = tensor.reshape(6, 16, 16)\n", + "# 100 all values less than \n", + "show_images(tensor, n_row=1, n_col=6, figsize=[20, 20])\n", + "show_images(tmp, n_row=1, n_col=6, figsize=[20, 20])\n", + "print(tensor[0][0])\n", + "print(tmp[0][0])\n", + "# At 9.30PM on Sunday I've come to realies that this is japanese characters... A bit too late to figure that out...\n" ] }, + { + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1.0, 1.0, 4.0, 1.0, 1.0, 3.0, 1.0, 1.0, 1.0, 0.0]\n" + ] + } + ], + "source": [ + "print(y[:10]) # y is just a list of values" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2024-04-28T14:16:29.783690Z", + "start_time": "2024-04-28T14:16:29.781229Z" + } + }, + "id": "3b890da00340343f", + "execution_count": 294 + }, { "cell_type": "code", "outputs": [], @@ -356,16 +438,73 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 349, "id": "93f82e42", "metadata": { "ExecuteTime": { - "end_time": "2024-04-28T06:46:52.483551Z", - "start_time": "2024-04-28T06:46:52.482068Z" + "end_time": "2024-04-28T15:44:25.035919Z", + "start_time": "2024-04-28T15:44:24.956794Z" } }, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": "" + }, + "execution_count": 349, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the values in all the images. \n", + "# Flatten the image\n", + "data_to_plot = pd.DataFrame(X[0].reshape(-1))\n", + "data_to_plot.boxplot()\n", + "\n" + ] + }, + { + "cell_type": "code", + "outputs": [ + { + "data": { + "text/plain": "" + }, + "execution_count": 351, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": "
", + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "y_pd = pd.DataFrame(torch.tensor(y).int())\n", + "y_pd.value_counts().plot(kind='bar')" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2024-04-28T15:45:30.464473Z", + "start_time": "2024-04-28T15:45:30.370547Z" + } + }, + "id": "1752fd9dbaef6786", + "execution_count": 351 }, { "cell_type": "markdown", @@ -712,7 +851,177 @@ "id": "81addd51", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "def objective(trial):\n", + " batch = trial.suggest_int(\"batch_size\", 1, 12, log=True)\n", + " epochs = trial.suggest_int(\"epochs\", 1, 20)\n", + " model = Model(batch_size=2**batch, epochs=epochs)\n", + " model.fit(X_train, y_train)\n", + " pred = model.predict(X_test)\n", + " return -f1_score(y_test, pred, average='macro')\n", + "# Run optimization\n", + "# storage = optuna.storages.InMemoryStorage()\n", + "# study = optuna.create_study(storage=storage)\n", + "# study.optimize(objective, n_trials=10)\n", + "# \n", + "# best_score = study.best_value\n", + "# best_params = study.best_params\n", + "# \n", + "# print(best_score, best_params)\n" + ] + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "import numpy as np\n", + "import torch\n", + "import os\n", + "\n", + "from torch import nn\n", + "\n", + "with open('data.npy', 'rb') as f:\n", + " data = np.load(f, allow_pickle=True).item()\n", + " X = data['data']\n", + " y = data['label']\n", + "\n", + "from torch import nn\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "from torch import nn\n", + "import numpy as np\n", + "import torch\n", + "import os\n", + "from torchvision.transforms.functional import equalize\n", + "\n", + "class CNN3D(nn.Module):\n", + " def __init__(self, hidden_size=32, dropout=0.0):\n", + " super(CNN3D, self).__init__()\n", + " self.conv1 = nn.Conv3d(1, hidden_size, kernel_size=3, stride=1, padding=1)\n", + " self.batchnorm = nn.BatchNorm3d(hidden_size)\n", + " self.conv2 = nn.Conv3d(hidden_size, hidden_size*2, kernel_size=3, stride=1, padding=1)\n", + " self.relu = nn.ReLU()\n", + " self.maxpool = nn.MaxPool3d(kernel_size=2, stride=2)\n", + " self.fc1 = nn.Linear(hidden_size*32, 256) # Calculate input size based on output from conv3\n", + " self.fc2 = nn.Linear(256, 6)\n", + " # self.dropout = nn.Dropout(dropout)\n", + "\n", + " def forward(self, x):\n", + " x = self.conv1(x)\n", + " x = self.relu(x)\n", + " x = self.maxpool(x)\n", + " x = self.batchnorm(x)\n", + " x = self.conv2(x)\n", + " x = self.relu(x)\n", + " x = self.maxpool(x)\n", + " # x = self.dropout(x)\n", + "\n", + " x = x.view(x.size(0), -1) # Flatten features for fully connected layers\n", + " x = self.fc1(x)\n", + " x = self.relu(x)\n", + " x = self.fc2(x)\n", + " return x\n", + "\n", + "def train(model, criterion, optimizer, loader, epochs=5):\n", + " for epoch in range(epochs):\n", + " for idx, (inputs, labels) in enumerate(loader):\n", + " optimizer.zero_grad()\n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, labels)\n", + " loss.backward()\n", + " optimizer.step()\n", + " print(f'Epoch {epoch}, Loss: {loss.item()}')\n", + " return model\n", + "\n", + "class Model():\n", + " def __init__(self, batch_size=64,lr=0.001,epochs=10, dropout=0.0, hidden_size=32, n_samples=900):\n", + " print(batch_size, epochs, lr, dropout, hidden_size, n_samples)\n", + " self.batch_size = batch_size\n", + " self.lr = lr\n", + " self.epochs = epochs\n", + " self.model = CNN3D(dropout=dropout, hidden_size=hidden_size)\n", + " self.criterion = nn.CrossEntropyLoss()\n", + " self.optimizer = torch.optim.Adam(self.model.parameters(), lr=self.lr)\n", + " self.n_samples = n_samples\n", + "\n", + " def fit(self, X, y):\n", + " X, y = self.process_data(X, y)\n", + " train_dataset = torch.utils.data.TensorDataset(X, y)\n", + " train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=self.batch_size, shuffle=True)\n", + " train(self.model, self.criterion, self.optimizer, train_loader, self.epochs)\n", + "\n", + " def predict(self, X):\n", + " self.model.eval()\n", + " with torch.no_grad():\n", + " X = np.array([video[:6] for video in X])\n", + " tensor_videos = torch.tensor(X, dtype=torch.float32)\n", + " # Clip values to 0 and 255\n", + " tensor_videos = np.clip(tensor_videos, 0, 255)\n", + "\n", + " # Replace NaNs in each frame, with the average of the frame. This was generated with GPT\n", + " for i in range(tensor_videos.shape[0]):\n", + " for j in range(tensor_videos.shape[1]):\n", + " tensor_videos[i][j][torch.isnan(tensor_videos[i][j])] = torch.mean(\n", + " tensor_videos[i][j][~torch.isnan(tensor_videos[i][j])])\n", + " # tensor_videos = torch.Tensor(tensor_videos).to(torch.uint8).reshape(-1, 1, 16, 16)\n", + " # tensor_videos = equalize(tensor_videos).float().reshape(-1, 1, 6, 16, 16)\n", + " tensor_videos = torch.Tensor(tensor_videos).reshape(-1, 1, 6, 16, 16)\n", + " # some funky code to make the features more prominent\n", + "\n", + " result = self.model(tensor_videos)\n", + " return torch.max(result, dim=1)[1].numpy()\n", + " def process_data(self, X, y):\n", + " y = np.array(y)\n", + " X = np.array([video[:6] for video in X])\n", + " tensor_videos = torch.tensor(X, dtype=torch.float32)\n", + " # Clip values to 0 and 255\n", + " tensor_videos = np.clip(tensor_videos, 0, 255)\n", + "\n", + " # Replace NaNs in each frame, with the average of the frame. This was generated with GPT\n", + " for i in range(tensor_videos.shape[0]):\n", + " for j in range(tensor_videos.shape[1]):\n", + " tensor_videos[i][j][torch.isnan(tensor_videos[i][j])] = torch.mean(\n", + " tensor_videos[i][j][~torch.isnan(tensor_videos[i][j])])\n", + " # Undersample the data for each of the 6 classes. Select max of 300 samples for each class\n", + " # Very much generated with the assitance of chatGPT with some modifications\n", + " # Get the indices of each class\n", + " indices = [np.argwhere(y == i).squeeze(1) for i in range(6)]\n", + " # Get the number of samples to take for each class\n", + " # Get the indices of the samples to take\n", + " indices_to_take = [np.random.choice(indices[i], self.n_samples, replace=True) for i in range(6)]\n", + " # Concatenate the indices\n", + " indices_to_take = np.concatenate(indices_to_take)\n", + " # Select the samples\n", + " tensor_videos = tensor_videos[indices_to_take]\n", + "\n", + " tensor_videos = torch.Tensor(tensor_videos).reshape(-1, 1, 6, 16, 16)\n", + " # Reshape the tensor to int for image processing\n", + " # tensor_videos = torch.Tensor(tensor_videos).to(torch.uint8).reshape(-1, 1, 16, 16)\n", + " # tensor_videos = equalize(tensor_videos).float().reshape(-1, 1, 6, 16, 16)\n", + "\n", + " y = y[indices_to_take]\n", + " return tensor_videos, torch.Tensor(y).long()\n", + "\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)\n", + "\n", + "not_nan_indices = np.argwhere(~np.isnan(np.array(y_test))).squeeze()\n", + "y_test = [y_test[i] for i in not_nan_indices]\n", + "X_test = [X_test[i] for i in not_nan_indices]\n", + "\n", + "print(\"init model\")\n", + "model = Model()\n", + "model.fit(X_train, y_train)\n", + "\n", + "from sklearn.metrics import f1_score\n", + "\n", + "y_pred = model.predict(X_test)\n", + "print(\"F1 Score (macro): {0:.2f}\".format(f1_score(y_test, y_pred, average='macro'))) # You may encounter errors, you are expected to figure out what's the issue." + ], + "metadata": { + "collapsed": false + }, + "id": "a56142ab267bafaa" } ], "metadata": {