{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Global Wheat CAE\n","metadata":{}},{"cell_type":"code","source":"\nimport os,platform\nimport numpy as np \n#import pandas as pd\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\nimport torch\nimport torch.nn as nn   \nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\n\n\nimport sklearn\nfrom sklearn.metrics import mean_absolute_error\nfrom sklearn.model_selection import train_test_split\nimport glob\n\nDEVICE = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(DEVICE)\n\nEPOCHS = 100\nBATCH = 64\nFN_FEATURE = 512\nLATENT_FEATURE = 64\n#!pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:03:52.916159Z","iopub.execute_input":"2023-05-11T14:03:52.916663Z","iopub.status.idle":"2023-05-11T14:03:57.859282Z","shell.execute_reply.started":"2023-05-11T14:03:52.916636Z","shell.execute_reply":"2023-05-11T14:03:57.858258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess","metadata":{}},{"cell_type":"code","source":"\ndef save_reshaped_memmap(source_dir,name):\n    \n    train_X= glob.glob(f\"{source_dir}/*\")\n    WORK_DIR = '/kaggle/working'\n    if os.path.isfile(f'{WORK_DIR}/{name}'):return\n    print(f'Creating {name} ...')\n    print(len(train_X))\n    fp = np.memmap(f'{name}', dtype='float32', mode='w+', shape=(len(train_X),3,256,256))\n    for i,path in enumerate(train_X) :\n        #name = str(path).split('/')[-1].split('.')[0]\n        X = Image.open(path)\n        X = X.resize((256,256))\n        X = np.asarray(X,dtype='float32')\n        X = X/255\n        X = X.transpose((2,0,1))\n        #print(X.shape,X.dtype)\n        fp[i] = X\n    \n    \n    del fp\n\n\ndef show_img(path):\n    img = Image.open(path)\n    img = img.resize((256,256))\n    img = np.array(img)\n    print(img.shape)\n    print(img.min(),img.max())\n    plt.imshow(img)\n    plt.show()\n\nsave_reshaped_memmap(\"/kaggle/input/global-wheat-detection/train\",'train.dat')\nsave_reshaped_memmap(\"/kaggle/input/global-wheat-detection/test\",'test.dat')\ntrain_X = 'train.dat'\ntest_X = 'test.dat'\n#show_img(train_X[0])","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:03:57.861630Z","iopub.execute_input":"2023-05-11T14:03:57.862969Z","iopub.status.idle":"2023-05-11T14:05:27.114545Z","shell.execute_reply.started":"2023-05-11T14:03:57.862935Z","shell.execute_reply":"2023-05-11T14:05:27.113620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create Dataset","metadata":{}},{"cell_type":"code","source":"\n\nclass TrainDataset(Dataset):\n    def __init__(self,name='train.dat') -> None:\n        super().__init__()\n        X = np.memmap(f'{name}', dtype='float32', mode='r+', shape=(3422,3,256,256)) \n        self.X = X\n        \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, index):\n        \n        X = self.X[index]\n\n        return X\n        \n    ","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:05:27.123509Z","iopub.execute_input":"2023-05-11T14:05:27.124506Z","iopub.status.idle":"2023-05-11T14:05:27.132490Z","shell.execute_reply.started":"2023-05-11T14:05:27.124472Z","shell.execute_reply":"2023-05-11T14:05:27.131565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create Model","metadata":{}},{"cell_type":"code","source":"VERBOSE = False\ndef print_if_verbose(s):\n    if VERBOSE:print(s)\n\nclass BottleNeck(nn.Module):\n        \"\"\"MobileNetv2-like layer\"\"\"\n        def __init__(self,in_c,out_c,t=1,stride=1) -> None:\n            super().__init__()\n            self.conv1 = nn.Conv2d(in_c,t*in_c,kernel_size=1,stride=stride)\n            self.conv2 = nn.Conv2d(in_c*t,in_c*t,kernel_size=3,groups=in_c*t,padding=1)\n            self.conv3 = nn.Conv2d(in_c*t,out_c,kernel_size=1)\n            if stride==1:\n                self.shortcut = nn.Conv2d(in_c,out_c,kernel_size=1,stride=stride)\n            \n\n        \n        def forward(self,x):\n            out = F.mish(self.conv1(x)) \n            out = self.conv2(out)\n            out = self.conv3(out)\n            out += self.shortcut(x)\n            return out\n\n\n\nclass AutoEncoder(nn.Module):\n    def __init__(self, latent_features) -> None:\n        super(AutoEncoder, self).__init__()  # 256,256\n        self.conv1 = nn.Conv2d(3,24,3,padding='same') # 256\n        self.pool1 = nn.MaxPool2d(2,2) # 128\n        self.bottle2 = BottleNeck(24,16,1) # 128\n        self.pool2 = nn.MaxPool2d(2,2) # 64\n        self.conv3 = nn.Conv2d(16,32,3,padding='same') #64\n        self.pool3 = nn.MaxPool2d(2,2) #32\n        self.conv4 = nn.Conv2d(32,64,3,padding='same')\n        self.pool4 = nn.MaxPool2d(2,2)#16\n\n        self.fc1 = nn.Linear(16*16*64, FN_FEATURE) \n        self.fc1_1 = nn.Linear(FN_FEATURE, latent_features)\n        # Decoder\n        self.fc2 = nn.Linear(latent_features, FN_FEATURE)  # 1\n        \n        self.deconv4 = nn.ConvTranspose2d(FN_FEATURE,64,8,stride=1) # 8\n        # interpolate 16\n        self.deconv3 = nn.ConvTranspose2d(64,32,3,padding=1)\n        # interpolate 32\n        self.deconv2 = nn.ConvTranspose2d(32,32,3,padding=1)\n        # interpolate 64\n        self.deconv1 = nn.ConvTranspose2d(32,16,3,padding=1)  \n        # interpolate 128\n        self.deconv1_1 = nn.ConvTranspose2d(16,12,3,padding=1)\n        # interpolate 256\n        self.deconv0 = nn.ConvTranspose2d(12,3,3,stride=1,padding=1)# 256\n        \n\n    def encode(self, x):\n        x = F.mish(self.conv1(x))\n        x = self.pool1(x)\n        #print_if_verbose(x.shape)\n        x = self.bottle2(x)\n        x = self.pool2(x)\n        \n        #print_if_verbose(x.shape)\n        x = F.mish(self.conv3(x))\n        x = self.pool3(x)\n        x = F.mish(self.conv4(x))\n        x = self.pool4(x)\n        x = x.view(-1, 16*16*64)\n        x = F.mish(self.fc1(x))\n        x = F.mish(self.fc1_1(x))\n\n        return x\n\n    def decode(self, x):\n        x = F.mish(self.fc2(x))\n        x = x.view(-1, FN_FEATURE, 1, 1)\n        x = self.deconv4(x)\n        x = F.interpolate(x,scale_factor=2)\n        x = F.mish(self.deconv3(x)) \n        x = F.interpolate(x, scale_factor=2)\n        x = F.mish(self.deconv2(x))\n        x = F.interpolate(x, scale_factor=2)\n        x = F.mish(self.deconv1(x)) \n        x = F.interpolate(x,scale_factor=2)\n        x = F.mish(self.deconv1_1(x)) \n        x = F.interpolate(x,scale_factor=2)\n        x = self.deconv0(x)\n        return x\n\n    def forward(self, x):\n        x = self.encode(x)\n        x = self.decode(x)\n        return x\n","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:05:27.133969Z","iopub.execute_input":"2023-05-11T14:05:27.134323Z","iopub.status.idle":"2023-05-11T14:05:27.159278Z","shell.execute_reply.started":"2023-05-11T14:05:27.134287Z","shell.execute_reply":"2023-05-11T14:05:27.158233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_loader(X,shuffle=True):\n    train_ds = TrainDataset(X)\n    train_loader = DataLoader(train_ds,BATCH,pin_memory=True,shuffle=shuffle,num_workers=2)\n    return train_loader\n\n\ndef get_model():\n    model = AutoEncoder(latent_features= LATENT_FEATURE)\n    model = model.to(DEVICE)\n    #model = torch.compile(model)\n    #print(model)\n    return model\n\n\ndef get_optim(model,lr):\n    params = model.parameters()\n    optimizer = torch.optim.Adam(params=params,lr=lr)\n    #optimizer = torch.optim.SGD(params,lr=lr,momentum=0.1)\n    return optimizer\n\ndef get_loss():\n    loss = nn.MSELoss()\n    return loss\n\n# sklearn-metrics\n# https://scikit-learn.org/stable/modules/classes.html#module-sklearn.metrics\n\ndef get_score(true_valid,pred_valid):\n    score = {}\n\n    score['mae'] = sklearn.metrics.mean_absolute_error(true_valid,pred_valid)\n    return score\nget_model()","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:05:27.160953Z","iopub.execute_input":"2023-05-11T14:05:27.161247Z","iopub.status.idle":"2023-05-11T14:05:30.272358Z","shell.execute_reply.started":"2023-05-11T14:05:27.161219Z","shell.execute_reply":"2023-05-11T14:05:30.271467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"from tqdm import tqdm   \n\n\n\ntrain_loader = get_loader(train_X)\n\ndef train(lr):\n    model = get_model()\n    optim = get_optim(model,lr)\n    loss = get_loss()\n    for epoch in range(EPOCHS):\n        total_loss = []\n        \n        model.train()\n        \n        for i,X_batch in tqdm(enumerate(train_loader),total=len(train_loader),leave=False):\n            # CPU -> GPU\n            X_batch = X_batch.to(DEVICE,non_blocking=True)\n            # Predict\n            X_pred_batch = model.forward(X_batch)\n            # Loss\n            losses = loss(X_batch,X_pred_batch)\n            # Back Propagation\n            optim.zero_grad()\n            losses.backward()\n            # Update Params\n            optim.step()\n            \n            total_loss.append(losses.detach().cpu().numpy())\n            \n        \n        #scores = get_score(true_labels,preds_labels)\n        print(F\"EPOCH{epoch}, loss={sum(total_loss)/len(total_loss)}\",end=\"\")\n        #torch.save(model.state_dict(), f'tmp/checkpoint{epoch}.pth')\n        \n        #validation\n    \n    return model\n\n\n\nmodel = train(1e-3)","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:05:30.273971Z","iopub.execute_input":"2023-05-11T14:05:30.274639Z","iopub.status.idle":"2023-05-11T14:16:11.852358Z","shell.execute_reply.started":"2023-05-11T14:05:30.274602Z","shell.execute_reply":"2023-05-11T14:16:11.851169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Output Visualization","metadata":{}},{"cell_type":"code","source":"model.eval()\n\n\ndef postprocess(X, index=0):\n    x = X.detach().cpu().numpy()\n    x = np.transpose(x[index], (1, 2, 0))\n    return x\n\ntest_loader = get_loader(train_X)\n\nwith torch.no_grad():\n    for X in test_loader:\n        X = X.to(DEVICE).float()\n        mid = model.encode(X)\n        Xd = model.forward(X)\n\n        # [Batch,RGB,X,Y]\n        \n        NROWS  =12\n        plt.tight_layout(pad=0.1)\n        fig, ax = plt.subplots(nrows=NROWS,ncols=3,figsize=(8,NROWS*2))\n        for j in range(NROWS):\n            x = postprocess(X,index=j)\n            xd = postprocess(Xd,index=j)\n            mi = mid.detach().cpu().numpy()\n            mi = mi[j].reshape((4, -1))\n            for i, item in enumerate([x, mi, xd]):\n                ax[j,i].axes.xaxis.set_visible(False)\n                ax[j,i].axes.yaxis.set_visible(False)\n                ax[j,i].imshow(item)\n            \n\n        print(Xd.shape)\n        #print(mid)\n\n        plt.show()\n\n        break\n","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:22:58.709725Z","iopub.execute_input":"2023-05-11T14:22:58.710881Z","iopub.status.idle":"2023-05-11T14:23:02.176518Z","shell.execute_reply.started":"2023-05-11T14:22:58.710835Z","shell.execute_reply":"2023-05-11T14:23:02.175486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\ndef check(num):\n    num = torch.tensor(num).float()\n    X = model.decode(num).detach().numpy()\n    X = X[0].reshape((28,28))\n    plt.imshow(X)\n\"\"\"\n#check([1,0,3,2])","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:16:15.176688Z","iopub.execute_input":"2023-05-11T14:16:15.177554Z","iopub.status.idle":"2023-05-11T14:16:15.184969Z","shell.execute_reply.started":"2023-05-11T14:16:15.177516Z","shell.execute_reply":"2023-05-11T14:16:15.183926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_model(model):\n    torch.save(model,'output.pth')\n\n#save_model(model)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-11T14:16:15.189155Z","iopub.execute_input":"2023-05-11T14:16:15.190030Z","iopub.status.idle":"2023-05-11T14:16:15.195328Z","shell.execute_reply.started":"2023-05-11T14:16:15.189998Z","shell.execute_reply":"2023-05-11T14:16:15.194261Z"},"trusted":true},"execution_count":null,"outputs":[]}]}