{"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":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport torch\nimport torchvision as tv\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optims\nimport torchvision.transforms as transforms\nfrom PIL import Image\nimport os\nfrom transformers import AutoImageProcessor, ResNetForImageClassification\nimport torchvision.transforms as T\nfrom PIL import Image\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"3d4c015f-53b8-4057-9cf4-20316977c544","_cell_guid":"8172d2de-fe68-45b0-a8f4-916f967c2092","scrolled":true,"execution":{"iopub.status.busy":"2023-06-13T04:09:30.887469Z","iopub.execute_input":"2023-06-13T04:09:30.887972Z","iopub.status.idle":"2023-06-13T04:09:30.897656Z","shell.execute_reply.started":"2023-06-13T04:09:30.887928Z","shell.execute_reply":"2023-06-13T04:09:30.895768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Домашняя работа\nЛимонов Алексей, 7 по списку, БИВ202","metadata":{}},{"cell_type":"markdown","source":"# Задание 1, ImageNet","metadata":{}},{"cell_type":"markdown","source":"Разработать программу, принимающую на вход изображение из категории Imagenet своего варианта и выдающее название категории изображенного объекта и вероятность соответствия его этой категории. ","metadata":{}},{"cell_type":"markdown","source":"вариант = 20 * 2 + 10 * 23 = 230 + 40 = 270","metadata":{}},{"cell_type":"markdown","source":"Сначала напишу функцию для правильного резайса изображения.","metadata":{}},{"cell_type":"code","source":"def resize_image(src, size=(128, 128), bgc=\"white\"):\n    src.thumbnail(size, Image.ANTIALIAS)\n    \n    new_image = Image.new(\"RGB\", size, bgc)\n    \n    new_image.paste(src, (int((size[0]-src.size[0]) / 2)), int((size[1] - src.size[1]) / 2))\n    \n    return new_image","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:09:30.901344Z","iopub.execute_input":"2023-06-13T04:09:30.902446Z","iopub.status.idle":"2023-06-13T04:09:30.919336Z","shell.execute_reply.started":"2023-06-13T04:09:30.902399Z","shell.execute_reply":"2023-06-13T04:09:30.918144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Для дообучения будут неоходимые различные трансформации над изображением для лучшего обучения. Это работает как регуляризация, чтобы модель могла лучше видеть в темноте или перевернутое изображение.\nДля первого задания пока закомментирую некоторые трансформации, чтобы было удобнее смотреть.","metadata":{}},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize([256, 256]),\n#     transforms.RandomHorizontalFlip(),\n#     transforms.RandomVerticalFlip(),\n#     transforms.ColorJitter(brightness=0.5, contrast=0),\n    transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])\n])","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:09:30.921098Z","iopub.execute_input":"2023-06-13T04:09:30.92164Z","iopub.status.idle":"2023-06-13T04:09:30.930407Z","shell.execute_reply.started":"2023-06-13T04:09:30.921567Z","shell.execute_reply":"2023-06-13T04:09:30.929066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Для дообучения понадобится даталодер. Разделю его на тренеровочную и тестовую, чтобы на одной обучать, а на другой тестировать. Дополнительно перемешаю их","metadata":{}},{"cell_type":"code","source":"def load(path, transform=None):\n    dataset = tv.datasets.ImageFolder(root=path,transform = transform)\n    \n    train_size = int(0.7 * len(dataset))\n    test_size = len(dataset) - train_size\n    \n    train_set, test_set = torch.utils.data.random_split(dataset, [train_size, test_size])\n    \n    train_loader = torch.utils.data.DataLoader(\n        train_set,\n        batch_size=50,\n        num_workers=0,\n        shuffle=False\n    )\n    \n    test_loader = torch.utils.data.DataLoader(\n        test_set,\n        batch_size=50,\n        num_workers=0,\n        shuffle=False\n    )\n\n    return train_loader, test_loader\n\ntrain_loader, test_loader = load('/kaggle/input/imagenetmini-1000/imagenet-mini/train', transform)\nprint(f\"train loaders: {train_loader}\")","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:09:30.933762Z","iopub.execute_input":"2023-06-13T04:09:30.934568Z","iopub.status.idle":"2023-06-13T04:09:49.45223Z","shell.execute_reply.started":"2023-06-13T04:09:30.934488Z","shell.execute_reply":"2023-06-13T04:09:49.45079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Функция для возвращения изображения определенного класса","metadata":{}},{"cell_type":"code","source":"def get_example_class(cl: int):\n    for test_images, test_labels in test_loader:\n        for image, label in zip(test_images, test_labels):\n            if label == cl:\n                return image","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:09:49.45431Z","iopub.execute_input":"2023-06-13T04:09:49.455113Z","iopub.status.idle":"2023-06-13T04:09:49.462991Z","shell.execute_reply.started":"2023-06-13T04:09:49.455059Z","shell.execute_reply":"2023-06-13T04:09:49.461799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Изображение моего класса","metadata":{}},{"cell_type":"code","source":"my_class = get_example_class(110)\nplt.imshow(np.dstack(my_class))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:09:49.464952Z","iopub.execute_input":"2023-06-13T04:09:49.466243Z","iopub.status.idle":"2023-06-13T04:10:35.869652Z","shell.execute_reply.started":"2023-06-13T04:09:49.466186Z","shell.execute_reply":"2023-06-13T04:10:35.868474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"И не моего класса","metadata":{}},{"cell_type":"code","source":"not_my_class = get_example_class(150)\nplt.imshow(np.dstack(not_my_class))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:10:35.871176Z","iopub.execute_input":"2023-06-13T04:10:35.871675Z","iopub.status.idle":"2023-06-13T04:10:42.843121Z","shell.execute_reply.started":"2023-06-13T04:10:35.871635Z","shell.execute_reply":"2023-06-13T04:10:42.841408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Импортирую предобученную модель https://huggingface.co/microsoft/resnet-50.","metadata":{}},{"cell_type":"code","source":"processor = AutoImageProcessor.from_pretrained(\"/kaggle/input/resnet-50\") # в kaggle нет доступа в сеть, поэтому используем скачанную модель\nmodel = ResNetForImageClassification.from_pretrained(\"/kaggle/input/resnet-50\")\n\ninputs_my = processor(my_class, return_tensors=\"pt\") # Преобразование изображений\ninputs_not_my = processor(not_my_class, return_tensors=\"pt\")\n\nwith torch.no_grad():\n    probs_my = F.softmax(model(**inputs_my).logits) # \n    probs_not_my = F.softmax(model(**inputs_not_my).logits)\n\n# далее выбираю argmax с наивысшей вероятностью и определяю класс\npredicted_label_my = probs_my.argmax(-1).item()\npredicted_label_not_my = probs_not_my.argmax(-1).item()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:10:42.845626Z","iopub.execute_input":"2023-06-13T04:10:42.846065Z","iopub.status.idle":"2023-06-13T04:10:45.255954Z","shell.execute_reply.started":"2023-06-13T04:10:42.846011Z","shell.execute_reply":"2023-06-13T04:10:45.254473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Класс и вероятность моего класса изображения","metadata":{}},{"cell_type":"code","source":"predicted_label_my, probs_my.max(-1).values.item()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:10:45.25783Z","iopub.execute_input":"2023-06-13T04:10:45.259172Z","iopub.status.idle":"2023-06-13T04:10:45.271364Z","shell.execute_reply.started":"2023-06-13T04:10:45.259115Z","shell.execute_reply":"2023-06-13T04:10:45.269757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"И не моего","metadata":{}},{"cell_type":"code","source":"predicted_label_not_my, probs_not_my.max(-1).values.item()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:10:45.305912Z","iopub.execute_input":"2023-06-13T04:10:45.30711Z","iopub.status.idle":"2023-06-13T04:10:45.317657Z","shell.execute_reply.started":"2023-06-13T04:10:45.307031Z","shell.execute_reply":"2023-06-13T04:10:45.315901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Модель успешно решила задание!","metadata":{}},{"cell_type":"markdown","source":"# Задание 2, День и ночь","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import DataLoader, Subset\n\nfrom torchvision import transforms\nfrom torchvision.models import resnet18 as resnet\nfrom torchvision.models import ResNet18_Weights as resnet_weights\n\nfrom tqdm import tqdm\n\nfrom torch.optim import AdamW\nfrom torch.nn import MSELoss\n\nimport numpy as np\n# from torchvision import datasets\n\nfrom matplotlib import pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:21:18.475923Z","iopub.execute_input":"2023-06-13T04:21:18.476377Z","iopub.status.idle":"2023-06-13T04:21:18.484328Z","shell.execute_reply.started":"2023-06-13T04:21:18.476333Z","shell.execute_reply":"2023-06-13T04:21:18.483142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weights = resnet_weights.IMAGENET1K_V1\n\npreprocess = weights.transforms()\ndataset = ImageFolder(root=\"/kaggle/input/daynight-cityview\")\ntrain_dataset, test_dataset = torch.utils.data.random_split(dataset, (0.7, 0.3))","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:22:30.813588Z","iopub.execute_input":"2023-06-13T04:22:30.814125Z","iopub.status.idle":"2023-06-13T04:22:30.927196Z","shell.execute_reply.started":"2023-06-13T04:22:30.81408Z","shell.execute_reply":"2023-06-13T04:22:30.926159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = resnet(weights=weights).train()\nmodel.fc = torch.nn.Linear(512, 1)\n\noptim = AdamW(model.parameters(), lr=0.001)\nmodel = model.to('cuda')\n\nloss = MSELoss()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"iterations = 100\nbatch_size = 8\n\nfor _ in tqdm(range(iterations)):\n  idx = np.random.randint(0, len(train_dataset), batch_size)\n  imgs = []\n  labels = []\n  \n  for id in idx:\n    imgs.append(preprocess(train_dataset[id][0]))\n    labels.append(train_dataset[id][1])\n  \n  imgs = torch.stack(imgs).to('cuda')\n  labels = torch.tensor(labels, dtype=torch.float).to('cuda')\n  optim.zero_grad()\n  preds = model(imgs)\n  pred_loss = loss(preds, labels.unsqueeze(1))\n  pred_loss.backward()\n  \n  optim.step()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T04:28:30.691368Z","iopub.execute_input":"2023-06-13T04:28:30.692574Z","iopub.status.idle":"2023-06-13T04:28:32.96093Z","shell.execute_reply.started":"2023-06-13T04:28:30.692524Z","shell.execute_reply":"2023-06-13T04:28:32.959165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\ntrain_preprocess = transforms.Compose([\n    transforms.Resize(224),\n    transforms.ToTensor()\n])\nim_num = 10\ncurr_count = 0\nwith torch.no_grad():\n  for test_img, _ in test_dataset:\n    pred = model(train_preprocess(test_img).to('cuda').unsqueeze(0))\n    # print(pred.item())\n    if pred > 0:\n      print('Night')\n    else:\n      print('Day')\n    plt.imshow(test_img)\n    plt.show()\n    curr_count += 1\n    if curr_count == im_num:\n      break","metadata":{},"execution_count":null,"outputs":[]}]}