# Fashion-MNIST & CIFAR-10 Classification ## 先閱讀 [CNN 筆記](https://hackmd.io/@wilson920430/SJK5mHwtp) ## Fashion-MNIST ([Keras Example](https://www.tensorflow.org/tutorials/keras/classification)) ### 資料集說明 ![Screenshot_20240205_112208](https://hackmd.io/_uploads/r115N065T.png) 70000 張 28x28 黑白圖片(1 channel),可分類成 10 個類別 ### Load Datasets ```python= fashion_mnist = tf.keras.datasets.fashion_mnist (train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data() ``` ### Map values to [0,1] ```python= train_images = train_images / 255.0 test_images = test_images / 255.0 ``` ### Define the Network Structure ```python= model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), # flatten to (28 * 28 = 784 pixels) tf.keras.layers.Dense(256, activation='relu'), # Fully connected with 256 neurons tf.keras.layers.BatchNormalization(), tf.keras.layers.Dropout(0.6), tf.keras.layers.Dense(10) ]) ``` ### Compile Model, Specify Optimizer and Loss Function ```python= model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) ``` ### Fit the model to the Training Data & Test Accuracy ```python= model.fit(train_images, train_labels, epochs=10, batch_size=600) test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2, batch_size=10) print('\nTest accuracy:', test_acc) ``` ### Making Predictions ```python= probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()]) predictions = probability_model.predict(test_images) ``` ## Fashion-MNIST (Pytorch) ### Define Some Hyper Parameters ```python= # hyper-params batch_size = 100 lr = 0.001 epoch = 10 seed = 12345 ``` ### Load Data ```python= # load data train_data = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transforms.ToTensor()) test_data = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transforms.ToTensor()) train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False) ``` 與 Keras 稍微不同 在 PyTorch 中,```transform=transforms.ToTensor()```就會將數值範圍 Map 到 0~1 之間 ### Fix Seed ```python= def same_seeds(seed): torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.benchmark = False torch.backends.cudnn.deterministic = True same_seeds(seed) ``` ### Define Network ```python= class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.net = nn.Sequential( nn.Flatten(), nn.BatchNorm1d(784), nn.Linear(784, 64), nn.BatchNorm1d(64), nn.ReLU(), nn.Linear(64, 32), nn.BatchNorm1d(32), nn.ReLU(), nn.Linear(32, 10) ) def forward(self, x): x = self.net(x) return x ``` ### Start Training and Evaluating Accuracy ```python= model = Net().to(device) # loss function and optimizer criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr) best_acc = 0 for e in range(epoch): print(f"\nepoch: {e + 1}") # training model.train() for batch, (X, y) in enumerate(train_loader): pred = model(X) batch_loss = criterion(pred, y) optimizer.zero_grad() batch_loss.backward() optimizer.step() if (batch+1) % 10 == 0: print(f"\rloss: {batch_loss.item()} [{batch_size * (batch+1)}/{len(train_loader.dataset)}]", end='') # evaluating model.eval() test_loss, correct = 0, 0 with torch.no_grad(): for X, y in test_loader: pred = model(X) pred_label = pred.argmax(dim=1) # _, pred_label = torch.max(pred, dim=1) test_loss += criterion(pred, y).item() correct += (pred_label == y).sum().item() test_loss /= (len(test_loader.dataset) / batch_size) correct /= len(test_loader.dataset) print(f"\nTest Error: Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f}") if correct > best_acc: best_acc = correct torch.save(model.state_dict(), "model.pth") print("Best Model Saved") print(f"\nBest Model: Accuracy: {(100 * best_acc):>0.1f}% \n") ``` 選擇將 Test Accuracy 最高的 Model 儲存 最後最高的 Accuracy 可以達到 89% 因為圖片不複雜,用這樣多層 Linear 即可達到不錯效果,且運算效率高 也有嘗試用 CNN 做,效果差不多,但 CNN 要耗費較高的運算資源 ## CIFAR-10 (Pytorch) ### 資料集說明 ![Screenshot_20240205_111024](https://hackmd.io/_uploads/rklhWRpcp.png) 60000 張 32x32 彩色圖片(3 channels),可分類成 10 個類別 50000 張 For training,10000 張 For testing > Briefly, they are 18% test error without data augmentation and 11% with. 文件表示:沒有 Data Augmentation 時,可達 82% 正確率;而有 Data Augmentation 時,可達 89% 程式與 [Fashion-MNIST (Pytorch)](#Fashion-MNIST-Pytorch) 相似,以下僅說明新增或不同的部份 ### Transform Methods ```python= train_trans_method = transforms.Compose([ transforms.RandomCrop(32, padding=4), transforms.RandomHorizontalFlip(p=0.5), transforms.ToTensor(), # This will map the pixels to 0~1 transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]), # map the pixels to -1~1 ]) test_trans_method = transforms.Compose([ transforms.ToTensor(), # This will map the pixels to 0~1 transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]), # map the pixels to -1~1 ]) ``` ### Load Data and Inspect ```python= # load data train_data = datasets.CIFAR10(root='./data', train=True, download=True, transform=train_trans_method) test_data = datasets.CIFAR10(root='./data', train=False, download=True, transform=test_trans_method) train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False) print(f"Train Data Shape: {np.shape(train_data.data)}") print(f"Test Data Shape: {np.shape(test_data.data)}") class_names = train_data.classes # 10 item array ``` ### Network ```python= class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.net = nn.Sequential( # 32*32, 3 nn.Conv2d(3, 100, kernel_size=3), nn.BatchNorm2d(100), nn.ReLU(), nn.MaxPool2d(2), # 15*15, 100 nn.Conv2d(100, 50, kernel_size=4), nn.BatchNorm2d(50), nn.ReLU(), nn.MaxPool2d(2), # 6*6, 50 nn.Conv2d(50, 30, kernel_size=3), nn.BatchNorm2d(30), nn.ReLU(), nn.MaxPool2d(2), # 2*2, 30 nn.Flatten(), nn.Linear(120, 10) ) def forward(self, x): x = self.net(x) return x ``` ### 結果 Test Accuacy: 77.0% Correct 測試時可加上以下 Code 查看辨識錯誤的圖片 ```python= saved_model.eval() with torch.no_grad(): for X, y in test_loader: pred = saved_model(X) pred_label = pred.argmax(dim=1) for i, identical in enumerate(pred_label == y): if not identical: plt.figure() plt.imshow(X[i].squeeze().T * .5 + .5, cmap=plt.cm.binary) plt.grid(False) plt.xlabel(f"pred: {class_names[pred_label[i]]} / ans: {class_names[y[i]]}") plt.show() os.system("pause") ```