SimCLR/feature_eval/mini_batch_logistic_regress...

444 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"kernelspec": {
"display_name": "pytorch",
"language": "python",
"name": "pytorch"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
},
"colab": {
"name": "mini-batch-logistic-regression-evaluator.ipynb",
"provenance": [],
"include_colab_link": true
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/sthalles/SimCLR/blob/master/feature_eval/mini_batch_logistic_regression_evaluator.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "YUemQib7ZE4D",
"colab_type": "code",
"colab": {}
},
"source": [
"import torch\n",
"import sys\n",
"import numpy as np\n",
"import os\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"import yaml\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn import preprocessing\n",
"import importlib.util"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "WSgRE1CcLqdS",
"colab_type": "code",
"colab": {}
},
"source": [
"!pip install gdown"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "NOIJEui1ZziV",
"colab_type": "code",
"colab": {}
},
"source": [
"def get_file_id_by_model(folder_name):\n",
" file_id = {'resnet-18_40-epochs': '1c4eVon0sUd-ChVhH6XMpF6nCngNJsAPk',\n",
" 'resnet-18_80-epochs': '1L0yoeY9i2mzDcj69P4slTWb-cfr3PyoT',\n",
" 'resnet-50_40-epochs': '1TZqBNTFCsO-mxAiR-zJeyupY-J2gA27Q',\n",
" 'resnet-50_80-epochs': '1is1wkBRccHdhSKQnPUTQoaFkVNSaCb35',\n",
" 'resnet-18_100-epochs':'1aZ12TITXnajZ6QWmS_SDm8Sp8gXNbeCQ'}\n",
" return file_id.get(folder_name, \"Model not found.\")"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "G7YMxsvEZMrX",
"colab_type": "code",
"colab": {}
},
"source": [
"folder_name = 'resnet-50_40-epochs'\n",
"file_id = get_file_id_by_model(folder_name)\n",
"print(folder_name, file_id)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "PWZ8fet_YoJm",
"colab_type": "code",
"colab": {}
},
"source": [
"# download and extract model files\n",
"os.system('gdown https://drive.google.com/uc?id={}'.format(file_id))\n",
"os.system('unzip {}'.format(folder_name))\n",
"!ls"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "3_nypQVEv-hn",
"colab_type": "code",
"colab": {}
},
"source": [
"from torch.utils.data import DataLoader\n",
"import torchvision.transforms as transforms\n",
"from torchvision import datasets"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "lDfbL3w_Z0Od",
"colab_type": "code",
"colab": {}
},
"source": [
"device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
"print(\"Using device:\", device)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "IQMIryc6LjQd",
"colab_type": "code",
"colab": {}
},
"source": [
"checkpoints_folder = os.path.join(folder_name, 'checkpoints')\n",
"config = yaml.load(open(os.path.join(checkpoints_folder, \"config.yaml\"), \"r\"))\n",
"config"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "BfIPl0G6_RrT",
"colab_type": "code",
"colab": {}
},
"source": [
"def get_stl10_data_loaders(download, shuffle=False, batch_size=128):\n",
" train_dataset = datasets.STL10('./data', split='train', download=download,\n",
" transform=transforms.ToTensor())\n",
"\n",
" train_loader = DataLoader(train_dataset, batch_size=batch_size,\n",
" num_workers=0, drop_last=False, shuffle=shuffle)\n",
" \n",
" test_dataset = datasets.STL10('./data', split='test', download=download,\n",
" transform=transforms.ToTensor())\n",
"\n",
" test_loader = DataLoader(test_dataset, batch_size=batch_size,\n",
" num_workers=0, drop_last=False, shuffle=shuffle)\n",
" return train_loader, test_loader"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "a18lPD-tIle6",
"colab_type": "code",
"colab": {}
},
"source": [
"def _load_resnet_model(checkpoints_folder):\n",
" # Load the neural net module\n",
" spec = importlib.util.spec_from_file_location(\"model\", os.path.join(checkpoints_folder, 'resnet_simclr.py'))\n",
" resnet_module = importlib.util.module_from_spec(spec)\n",
" spec.loader.exec_module(resnet_module)\n",
"\n",
" model = resnet_module.ResNetSimCLR(**config['model'])\n",
" model.eval()\n",
"\n",
" state_dict = torch.load(os.path.join(checkpoints_folder, 'model.pth'), map_location=torch.device('cpu'))\n",
" model.load_state_dict(state_dict)\n",
" model = model.to(device)\n",
" return model"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "5nf4rDtWLjRE",
"colab_type": "text"
},
"source": [
"## Protocol #2 Logisitc Regression"
]
},
{
"cell_type": "code",
"metadata": {
"id": "7jjSxmDnHNQz",
"colab_type": "code",
"colab": {}
},
"source": [
"class ResNetFeatureExtractor(object):\n",
" def __init__(self, checkpoints_folder):\n",
" self.checkpoints_folder = checkpoints_folder\n",
" self.model = _load_resnet_model(checkpoints_folder)\n",
"\n",
" def _inference(self, loader):\n",
" feature_vector = []\n",
" labels_vector = []\n",
" for batch_x, batch_y in loader:\n",
"\n",
" batch_x = batch_x.to(device)\n",
" labels_vector.extend(batch_y)\n",
"\n",
" features, _ = self.model(batch_x)\n",
" feature_vector.extend(features.cpu().detach().numpy())\n",
"\n",
" feature_vector = np.array(feature_vector)\n",
" labels_vector = np.array(labels_vector)\n",
"\n",
" print(\"Features shape {}\".format(feature_vector.shape))\n",
" return feature_vector, labels_vector\n",
"\n",
" def get_resnet_features(self):\n",
" train_loader, test_loader = get_stl10_data_loaders(download=True)\n",
" X_train_feature, y_train = self._inference(train_loader)\n",
" X_test_feature, y_test = self._inference(test_loader)\n",
"\n",
" return X_train_feature, y_train, X_test_feature, y_test"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "kghx1govJq5_",
"colab_type": "code",
"colab": {}
},
"source": [
"resnet_feature_extractor = ResNetFeatureExtractor(checkpoints_folder)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "S_JcznxVJ1Xj",
"colab_type": "code",
"colab": {}
},
"source": [
"X_train_feature, y_train, X_test_feature, y_test = resnet_feature_extractor.get_resnet_features()"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "oftbHXcdLjRM",
"colab_type": "code",
"colab": {}
},
"source": [
"import torch.nn as nn\n",
"\n",
"class LogisticRegression(nn.Module):\n",
" \n",
" def __init__(self, n_features, n_classes):\n",
" super(LogisticRegression, self).__init__()\n",
" self.model = nn.Linear(n_features, n_classes)\n",
"\n",
" def forward(self, x):\n",
" return self.model(x)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Ks73ePLtNWeV",
"colab_type": "code",
"colab": {}
},
"source": [
"class LogiticRegressionEvaluator(object):\n",
" def __init__(self, n_features, n_classes):\n",
" self.log_regression = LogisticRegression(n_features, n_classes).to(device)\n",
" self.scaler = preprocessing.StandardScaler()\n",
"\n",
" def _normalize_dataset(self, X_train, X_test):\n",
" print(\"Standard Scaling Normalizer\")\n",
" self.scaler.fit(X_train)\n",
" X_train = self.scaler.transform(X_train)\n",
" X_test = self.scaler.transform(X_test)\n",
" return X_train, X_test\n",
"\n",
" @staticmethod\n",
" def _sample_weight_decay():\n",
" # We selected the l2 regularization parameter from a range of 45 logarithmically spaced values between 106 and 105\n",
" weight_decay = np.logspace(-6, 5, num=45, base=10.0)\n",
" weight_decay = np.random.choice(weight_decay)\n",
" print(\"Sampled weight decay:\", weight_decay)\n",
" return weight_decay\n",
"\n",
" def eval(self, test_loader):\n",
" correct = 0\n",
" total = 0\n",
"\n",
" with torch.no_grad():\n",
" self.log_regression.eval()\n",
" for batch_x, batch_y in test_loader:\n",
" batch_x, batch_y = batch_x.to(device), batch_y.to(device)\n",
" logits = self.log_regression(batch_x)\n",
"\n",
" predicted = torch.argmax(logits, dim=1)\n",
" total += batch_y.size(0)\n",
" correct += (predicted == batch_y).sum().item()\n",
"\n",
" final_acc = 100 * correct / total\n",
" self.log_regression.train()\n",
" return final_acc\n",
"\n",
"\n",
" def create_data_loaders_from_arrays(self, X_train, y_train, X_test, y_test):\n",
" X_train, X_test = self._normalize_dataset(X_train, X_test)\n",
"\n",
" train = torch.utils.data.TensorDataset(torch.from_numpy(X_train), torch.from_numpy(y_train).type(torch.long))\n",
" train_loader = torch.utils.data.DataLoader(train, batch_size=396, shuffle=False)\n",
"\n",
" test = torch.utils.data.TensorDataset(torch.from_numpy(X_test), torch.from_numpy(y_test).type(torch.long))\n",
" test_loader = torch.utils.data.DataLoader(test, batch_size=512, shuffle=False)\n",
" return train_loader, test_loader\n",
"\n",
" def train(self, X_train, y_train, X_test, y_test):\n",
" \n",
" train_loader, test_loader = self.create_data_loaders_from_arrays(X_train, y_train, X_test, y_test)\n",
"\n",
" weight_decay = self._sample_weight_decay()\n",
"\n",
" optimizer = torch.optim.Adam(self.log_regression.parameters(), 3e-4, weight_decay=weight_decay)\n",
" criterion = torch.nn.CrossEntropyLoss()\n",
"\n",
" best_accuracy = 0\n",
"\n",
" for e in range(200):\n",
" \n",
" for batch_x, batch_y in train_loader:\n",
"\n",
" batch_x, batch_y = batch_x.to(device), batch_y.to(device)\n",
"\n",
" optimizer.zero_grad()\n",
"\n",
" logits = self.log_regression(batch_x)\n",
"\n",
" loss = criterion(logits, batch_y)\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" epoch_acc = self.eval(test_loader)\n",
" \n",
" if epoch_acc > best_accuracy:\n",
" #print(\"Saving new model with accuracy {}\".format(epoch_acc))\n",
" best_accuracy = epoch_acc\n",
" torch.save(self.log_regression.state_dict(), 'log_regression.pth')\n",
"\n",
" print(\"--------------\")\n",
" print(\"Done training\")\n",
" print(\"Best accuracy:\", best_accuracy)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "NE716m7SOkaK",
"colab_type": "code",
"colab": {}
},
"source": [
"log_regressor_evaluator = LogiticRegressionEvaluator(n_features=X_train_feature.shape[1], n_classes=10)\n",
"\n",
"log_regressor_evaluator.train(X_train_feature, y_train, X_test_feature, y_test)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "_GC0a14uWRr6",
"colab_type": "code",
"colab": {}
},
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}