{"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":"少しずつ更新していきます。","metadata":{}},{"cell_type":"markdown","source":"右側のNotebook optionsのACCELERATORからGPUを選択。","metadata":{}},{"cell_type":"code","source":"import os\n\n# 表示するファイル数の上限。\nDISPLAY_LIMIT = 10\n\ncount = 0\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        if count < DISPLAY_LIMIT:\n            print(os.path.join(dirname, filename))\n            count += 1\n        else:\n            break","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:35.695367Z","iopub.execute_input":"2023-10-05T13:17:35.695743Z","iopub.status.idle":"2023-10-05T13:17:47.119544Z","shell.execute_reply.started":"2023-10-05T13:17:35.695716Z","shell.execute_reply":"2023-10-05T13:17:47.118531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nimport pandas as pd\nimport numpy as np\nimport random\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nfrom torchvision import transforms\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torchvision import models \nfrom torch.optim import lr_scheduler\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.121295Z","iopub.execute_input":"2023-10-05T13:17:47.121842Z","iopub.status.idle":"2023-10-05T13:17:47.128558Z","shell.execute_reply.started":"2023-10-05T13:17:47.121801Z","shell.execute_reply":"2023-10-05T13:17:47.127523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Trueを返すことを確認\ntorch.cuda.is_available()","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.130184Z","iopub.execute_input":"2023-10-05T13:17:47.130725Z","iopub.status.idle":"2023-10-05T13:17:47.141331Z","shell.execute_reply.started":"2023-10-05T13:17:47.130696Z","shell.execute_reply":"2023-10-05T13:17:47.140311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(torch.version.cuda)\nprint(torch.backends.cudnn.version())","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.143911Z","iopub.execute_input":"2023-10-05T13:17:47.144850Z","iopub.status.idle":"2023-10-05T13:17:47.153353Z","shell.execute_reply.started":"2023-10-05T13:17:47.144809Z","shell.execute_reply":"2023-10-05T13:17:47.152396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_check = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv')\ndisplay(df_check)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.154739Z","iopub.execute_input":"2023-10-05T13:17:47.155301Z","iopub.status.idle":"2023-10-05T13:17:47.443408Z","shell.execute_reply.started":"2023-10-05T13:17:47.155272Z","shell.execute_reply":"2023-10-05T13:17:47.442489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = \"/kaggle/input/dog-breed-identification\"\nlabels_df = pd.read_csv(os.path.join(data_dir, 'labels.csv'))\nlabels_df","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.444901Z","iopub.execute_input":"2023-10-05T13:17:47.445481Z","iopub.status.idle":"2023-10-05T13:17:47.467406Z","shell.execute_reply.started":"2023-10-05T13:17:47.445445Z","shell.execute_reply":"2023-10-05T13:17:47.466387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# breedに対してユニークな要素数をカウント。 \nlen(labels_df.breed.unique())","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.468670Z","iopub.execute_input":"2023-10-05T13:17:47.469349Z","iopub.status.idle":"2023-10-05T13:17:47.477729Z","shell.execute_reply.started":"2023-10-05T13:17:47.469286Z","shell.execute_reply":"2023-10-05T13:17:47.476673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# データ数が多い順でsort。\nsorted_breed_count = labels_df.groupby('breed').count().sort_values(by='id', ascending=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.479159Z","iopub.execute_input":"2023-10-05T13:17:47.479878Z","iopub.status.idle":"2023-10-05T13:17:47.490561Z","shell.execute_reply.started":"2023-10-05T13:17:47.479837Z","shell.execute_reply":"2023-10-05T13:17:47.489630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 最もデータ数が多い犬種をチェック。\nsorted_breed_count.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.492154Z","iopub.execute_input":"2023-10-05T13:17:47.492833Z","iopub.status.idle":"2023-10-05T13:17:47.502984Z","shell.execute_reply.started":"2023-10-05T13:17:47.492799Z","shell.execute_reply":"2023-10-05T13:17:47.501797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# データセットのディレクトリを作成。\ntrain_dir = 'train'\nos.makedirs(train_dir, exist_ok=True)\n\nfor label in labels_df['breed'].unique():\n    os.makedirs(os.path.join(train_dir, label), exist_ok=True)\n\n# 画像ファイルを対応するディレクトリにコピー。\nfor idx, row in labels_df.iterrows():\n    img_file = f\"{row['id']}.jpg\"\n    label = row['breed']\n    shutil.copyfile(os.path.join(data_dir, 'train', img_file), os.path.join(train_dir, label, img_file))","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:17:47.507718Z","iopub.execute_input":"2023-10-05T13:17:47.507967Z","iopub.status.idle":"2023-10-05T13:18:01.983172Z","shell.execute_reply.started":"2023-10-05T13:17:47.507947Z","shell.execute_reply":"2023-10-05T13:18:01.982220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 画像の前処理を設定。\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),  # 画像を指定のサイズにリサイズ。\n    transforms.ToTensor(),          # 画像をテンソルに変換。\n])\n\n# ImageFolderを使用してデータセットを読み込む。\ndataset = ImageFolder('train', transform=transform)\n\n# クラス名（ラベル）のリストを取得。\nclass_names = dataset.classes\n\n# データセットからランダムにサンプルを取得して可視化。\nnum_samples_to_display = 5\n\nplt.figure(figsize=(15, 10))\nfor i in range(num_samples_to_display):\n    # ランダムにサンプルを選択。\n    sample_idx = np.random.randint(len(dataset))\n    sample_image, sample_label = dataset[sample_idx]\n\n    # 画像を表示。\n    plt.subplot(1, num_samples_to_display, i + 1)\n    plt.imshow(sample_image.permute(1, 2, 0))  # チャネルの次元を最後に変更。\n    plt.title(f\"Label: {class_names[sample_label]}\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:01.984743Z","iopub.execute_input":"2023-10-05T13:18:01.985311Z","iopub.status.idle":"2023-10-05T13:18:02.815758Z","shell.execute_reply.started":"2023-10-05T13:18:01.985279Z","shell.execute_reply":"2023-10-05T13:18:02.814916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# データセットの前処理とデータ拡張。\ntransform = transforms.Compose([\n    transforms.RandomResizedCrop(180),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n# データセットの読み込み。\nbatch_size = 32\ndataset = ImageFolder(train_dir, transform=transform)\nnum_classes = len(dataset.classes)\n\n# データセットをトレーニングデータと検証データに分割。\nvalid_size = 0.2\nnum_train = len(dataset)\nindices = list(range(num_train))\nsplit = int(valid_size * num_train)\ntrain_indices, valid_indices = indices[split:], indices[:split]\n\ntrain_sampler = SubsetRandomSampler(train_indices)\nvalid_sampler = SubsetRandomSampler(valid_indices)\n\ntrain_loader = DataLoader(dataset, batch_size=batch_size, sampler=train_sampler)\nvalid_loader = DataLoader(dataset, batch_size=batch_size, sampler=valid_sampler)\n\n# モデルの定義 (ResNet18を使用)\nmodel = models.resnet18(pretrained=True)  # 事前学習済みのResNet-18をロード。\n\n# 最終層をカスタマイズ。\nnum_ftrs = model.fc.in_features\nmodel.fc = nn.Linear(num_ftrs, num_classes)\n\n# GPUを使用するためのデバイスの設定。\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n# モデルの初期化。\nmodel.to(device)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:02.816995Z","iopub.execute_input":"2023-10-05T13:18:02.817979Z","iopub.status.idle":"2023-10-05T13:18:03.084542Z","shell.execute_reply.started":"2023-10-05T13:18:02.817945Z","shell.execute_reply":"2023-10-05T13:18:03.083677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install torchviz","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:03.086031Z","iopub.execute_input":"2023-10-05T13:18:03.086376Z","iopub.status.idle":"2023-10-05T13:18:11.040421Z","shell.execute_reply.started":"2023-10-05T13:18:03.086345Z","shell.execute_reply":"2023-10-05T13:18:11.039023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchviz\nfrom torch.autograd import Variable\n\n# ダミーのバッチを生成。\ndummy_batch = next(iter(train_loader))  # トレーニングデータローダーから1つのバッチを取得。\n\n# モデルを可視化。\nimages, labels = dummy_batch\nimages, labels = images.to(device), labels.to(device)\ntorchviz.make_dot(model(images), params=dict(model.named_parameters())).render(\"resnet18_model_batch\", format=\"png\")","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:11.042594Z","iopub.execute_input":"2023-10-05T13:18:11.043005Z","iopub.status.idle":"2023-10-05T13:18:12.074715Z","shell.execute_reply.started":"2023-10-05T13:18:11.042973Z","shell.execute_reply":"2023-10-05T13:18:12.073787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_path = 'resnet18_model_batch.png'\nimage = Image.open(image_path)\n\nwidth, height = 2400, 1800\n\nfig = plt.figure(figsize=(width / 100, height / 100))\n\n# 画像を表示\nplt.imshow(image)\nplt.axis('off')  # 軸を非表示。\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:12.075928Z","iopub.execute_input":"2023-10-05T13:18:12.076831Z","iopub.status.idle":"2023-10-05T13:18:13.526818Z","shell.execute_reply.started":"2023-10-05T13:18:12.076799Z","shell.execute_reply":"2023-10-05T13:18:13.525973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# モデルのトレーニング。\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.0001)\n# 学習率を減衰させるスケジューラを作成。\nscheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)  # 5エポックごとに学習率を0.1倍にする\n\nnum_epochs = 10\nfor epoch in range(num_epochs):\n    model.train()\n    scheduler.step()  # 学習率を更新。\n    running_loss = 0.0\n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n\n    model.eval()\n    accuracy = 0.0\n    with torch.no_grad():\n        for images, labels in valid_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            _, predicted = torch.max(outputs, 1)\n            accuracy += (predicted == labels).sum().item() / len(labels)\n\n    print(f\"Epoch {epoch + 1}/{num_epochs}, Loss: {running_loss / len(train_loader)}, Accuracy: {accuracy / len(valid_loader)}\")\n\n# テストデータの読み込みと予測。\ntest_transform = transforms.Compose([\n    transforms.Resize(180),\n    transforms.CenterCrop(180),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:18:13.527990Z","iopub.execute_input":"2023-10-05T13:18:13.528794Z","iopub.status.idle":"2023-10-05T13:26:42.971408Z","shell.execute_reply.started":"2023-10-05T13:18:13.528763Z","shell.execute_reply":"2023-10-05T13:26:42.970467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 画像のリサイズサイズを設定。\nimg_height = 180\nimg_width = 180\n\n# テストデータのディレクトリパス。\ntest_data_dir = \"/kaggle/input/dog-breed-identification/test\"\n\n# テストデータ用のデータセットクラスを定義。\nclass TestDataset(torch.utils.data.Dataset):\n    def __init__(self, data_dir, transform=None):\n        self.data_dir = data_dir\n        self.transform = transform\n        self.image_paths = [os.path.join(data_dir, img) for img in os.listdir(data_dir)]\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image_path = self.image_paths[idx]\n        image = Image.open(image_path).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image\n\n# データ変換とデータローダーの設定。\ntransform = transforms.Compose([\n    transforms.Resize((img_height, img_width)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\ntest_dataset = TestDataset(test_data_dir, transform=transform)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:26:42.972924Z","iopub.execute_input":"2023-10-05T13:26:42.973882Z","iopub.status.idle":"2023-10-05T13:26:43.002661Z","shell.execute_reply.started":"2023-10-05T13:26:42.973840Z","shell.execute_reply":"2023-10-05T13:26:43.001876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\npredictions = []\n\nwith torch.no_grad():\n    for batch in test_loader:\n        inputs = batch.to(device)\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        predictions.extend(predicted.cpu().numpy())","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:26:43.004041Z","iopub.execute_input":"2023-10-05T13:26:43.004365Z","iopub.status.idle":"2023-10-05T13:27:42.236197Z","shell.execute_reply.started":"2023-10-05T13:26:43.004327Z","shell.execute_reply":"2023-10-05T13:27:42.235174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = ImageFolder(train_dir, transform=transform)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:42.237464Z","iopub.execute_input":"2023-10-05T13:27:42.237794Z","iopub.status.idle":"2023-10-05T13:27:42.276297Z","shell.execute_reply.started":"2023-10-05T13:27:42.237766Z","shell.execute_reply":"2023-10-05T13:27:42.275416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 予測結果をDataFrameに変換。\nclass_names = train_ds.classes  # クラス名リストを取得。\ntest_predict = pd.DataFrame(predictions, columns=[\"predicted_class\"])\ntest_predict[\"predicted_breed\"] = [class_names[i] for i in predictions]","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:42.277894Z","iopub.execute_input":"2023-10-05T13:27:42.278508Z","iopub.status.idle":"2023-10-05T13:27:42.309557Z","shell.execute_reply.started":"2023-10-05T13:27:42.278477Z","shell.execute_reply":"2023-10-05T13:27:42.308752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predict","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:42.310988Z","iopub.execute_input":"2023-10-05T13:27:42.311594Z","iopub.status.idle":"2023-10-05T13:27:42.323533Z","shell.execute_reply.started":"2023-10-05T13:27:42.311561Z","shell.execute_reply":"2023-10-05T13:27:42.322286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# テストデータ、予測されたクラスをランダムに選択。\nnum_samples = 5\nsample_indices = random.sample(range(len(test_dataset)), num_samples)\n\nfor idx in sample_indices:\n    image = test_dataset[idx]  \n    predicted_class = test_predict.at[idx, \"predicted_class\"]  \n\n    plt.figure()\n    plt.imshow(image.permute(1, 2, 0)) \n    plt.title(f\"Predicted: {class_names[predicted_class]}\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:42.325345Z","iopub.execute_input":"2023-10-05T13:27:42.325719Z","iopub.status.idle":"2023-10-05T13:27:43.853730Z","shell.execute_reply.started":"2023-10-05T13:27:42.325686Z","shell.execute_reply":"2023-10-05T13:27:43.852776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ファイル名からidを取得。\ntest_predict[\"id\"] = [os.path.splitext(os.path.basename(path))[0] for path in test_dataset.image_paths]\n\n# pivotを使用してpredicted_breed列を横持ちに変換。\ntest_predict_wide = test_predict.pivot(index=\"id\", columns=\"predicted_breed\", values=\"predicted_class\").reset_index()\n\n# NaNを0に変換。\ntest_predict_wide = test_predict_wide.fillna(0)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:43.855166Z","iopub.execute_input":"2023-10-05T13:27:43.855714Z","iopub.status.idle":"2023-10-05T13:27:43.913628Z","shell.execute_reply.started":"2023-10-05T13:27:43.855682Z","shell.execute_reply":"2023-10-05T13:27:43.912666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predict_wide","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:43.915053Z","iopub.execute_input":"2023-10-05T13:27:43.915393Z","iopub.status.idle":"2023-10-05T13:27:43.955530Z","shell.execute_reply.started":"2023-10-05T13:27:43.915361Z","shell.execute_reply":"2023-10-05T13:27:43.954663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 各行の和が1になるように値を変換。\n# id列を一時的に別の変数に保存。\nid_column = test_predict_wide[\"id\"]\n\n# id列を除いて、各行の和が1になるように値を変換。\ntest_predict_wide = test_predict_wide.drop(columns=[\"id\"])\ntest_predict_wide = test_predict_wide.div(test_predict_wide.sum(axis=1), axis=0)\n\n# id列を再度結合。\ntest_predict_wide[\"id\"] = id_column\ntest_predict_wide","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:43.957103Z","iopub.execute_input":"2023-10-05T13:27:43.957439Z","iopub.status.idle":"2023-10-05T13:27:43.999063Z","shell.execute_reply.started":"2023-10-05T13:27:43.957410Z","shell.execute_reply":"2023-10-05T13:27:43.998134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predict_wide.to_csv('test_predict_wide.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T13:27:44.000300Z","iopub.execute_input":"2023-10-05T13:27:44.001195Z","iopub.status.idle":"2023-10-05T13:27:44.405036Z","shell.execute_reply.started":"2023-10-05T13:27:44.001162Z","shell.execute_reply":"2023-10-05T13:27:44.404072Z"},"trusted":true},"execution_count":null,"outputs":[]}]}