Skip to content

Instantly share code, notes, and snippets.

@mlaves
Last active November 1, 2020 13:08
Show Gist options
  • Save mlaves/77efca31e4fc76aed725cae3eb67c4cf to your computer and use it in GitHub Desktop.
Save mlaves/77efca31e4fc76aed725cae3eb67c4cf to your computer and use it in GitHub Desktop.
Unsupervised toy experiment on the "two moons" data set.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "1LwIMQaG7JtM"
},
"source": [
"# Self-Supervised Consistency Learning with Pseudo-Labeling from Bayesian Uncertainty\n",
"## A *Two Moons* Example"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "8rHBnKPzatqn"
},
"outputs": [],
"source": [
"import torch\n",
"from sklearn.datasets import make_moons\n",
"import matplotlib\n",
"from matplotlib import pyplot as plt\n",
"import numpy as np\n",
"import sys\n",
"from copy import deepcopy\n",
"import seaborn as sns\n",
"sns.set()\n",
"sns.set_context('paper')\n",
"\n",
"matplotlib.rcParams['text.usetex'] = True\n",
"matplotlib.rcParams['text.latex.preamble'] = [\n",
" r'\\usepackage{bm}']\n",
"\n",
"torch.manual_seed(0)\n",
"np.random.seed(0)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "ueq7DjJAoozH"
},
"outputs": [],
"source": [
"from torch.nn.functional import one_hot\n",
"\n",
"def mutual_information(z, zt, eps=sys.float_info.epsilon):\n",
" _, k = z.size()\n",
"\n",
" P = (z.unsqueeze(2) * zt.unsqueeze(1)).sum(dim=0)\n",
" P = ((P + P.t()) / 2) / P.sum()\n",
" P[(P < eps).data] = eps\n",
" assert (P.size() == (k, k))\n",
"\n",
" Pi = P.sum(dim=1).view(k, 1).expand(k, k)\n",
" Pj = P.sum(dim=0).view(1, k).expand(k, k)\n",
"\n",
" return (-P * (P.log() - Pi.log() - Pj.log())).sum()\n",
"\n",
"\n",
"def entropy(p):\n",
" return -(p*p.log()).sum(dim=1)\n",
"\n",
"\n",
"def batch_pl(p_B_C, eps=sys.float_info.epsilon):\n",
" p_B_C.add_(eps)\n",
" e = entropy(p_B_C)\n",
" marginal = p_B_C.mean(dim=0) # compute marginal\n",
" kld = (marginal*(marginal.log()-p_B_C.log())).sum(dim=1) # replace with nansum later\n",
" kld[kld != kld] = 0\n",
" return e - kld\n",
"\n",
"\n",
"def mixup(x1, x2, y1, y2, lamb=0.5, num_classes=None):\n",
" if not num_classes:\n",
" num_classes = y1.max()\n",
" x = lamb*x1 + (1-lamb)*x2\n",
" y = lamb*one_hot(y1, num_classes) + (1-lamb)*one_hot(y2, num_classes)\n",
"\n",
" return x, y\n",
"\n",
"\n",
"def extract_pseudo_labels(net, x, T):\n",
" y_p_a_mean = []\n",
" y_p_b_mean = []\n",
" for i in range(15):\n",
" y_p_a, y_p_b = net(x)\n",
" y_p_a_mean.append((T*y_p_a).softmax(1).detach().unsqueeze(0))\n",
" y_p_b_mean.append((y_p_b).softmax(1).detach().unsqueeze(0))\n",
" y_p_a_mean = torch.cat(y_p_a_mean, dim=0).mean(dim=0)\n",
" y_p_b_mean = torch.cat(y_p_b_mean, dim=0).mean(dim=0)\n",
" pseudo_targets = y_p_a_mean.argmax(dim=1)\n",
"\n",
" # get most uncertain\n",
" batchpl = batch_pl(y_p_a_mean)\n",
" uncert = x[torch.where(batchpl > 0.0)].detach()\n",
" conf = x[torch.where(batchpl < 0.0)].detach()\n",
" conf_target = y_p_a_mean[\n",
" torch.where(batchpl < 0.0)\n",
" ].detach().argmax(dim=1)\n",
"\n",
" return uncert, conf, pseudo_targets, conf_target\n",
"\n",
"\n",
"def extract_pseudo_labels_conf(net, x, T):\n",
" y_p_a_mean = []\n",
" y_p_b_mean = []\n",
" for i in range(15):\n",
" y_p_a, y_p_b = net(x)\n",
" y_p_a_mean.append((T*y_p_a).softmax(1).detach().unsqueeze(0))\n",
" y_p_b_mean.append((y_p_b).softmax(1).detach().unsqueeze(0))\n",
" y_p_a_mean = torch.cat(y_p_a_mean, dim=0).mean(dim=0)\n",
" y_p_b_mean = torch.cat(y_p_b_mean, dim=0).mean(dim=0)\n",
" pseudo_targets = y_p_a_mean.argmax(dim=1)\n",
"\n",
" # get most uncertain\n",
" uncert = x[torch.where((y_p_a_mean[:,0] > 0.1) & (y_p_a_mean[:,0] < 0.9))].detach()\n",
" conf = x[torch.where((y_p_a_mean[:,0] > 0.9) | (y_p_a_mean[:,0] < 0.1))].detach()\n",
" conf_target = y_p_a_mean[\n",
" torch.where((y_p_a_mean[:,0] > 0.9) | (y_p_a_mean[:,0] < 0.1))\n",
" ].detach().argmax(dim=1)\n",
"\n",
" return uncert, conf, pseudo_targets, conf_target\n",
"\n",
"\n",
"def create_plot_data(net, T):\n",
" xx = np.linspace(-2.2, 2.2, 100)\n",
" yy = np.linspace(-2.3, 2.3, 100)\n",
" XX, YY = np.meshgrid(xx, yy)\n",
"\n",
" inp = np.concatenate([XX.reshape(-1, 1), YY.reshape(-1, 1)], axis=1)\n",
"\n",
" with torch.no_grad():\n",
" y_p_test_n = []\n",
" for n in range(15):\n",
" y_p_test_n.append((T*net(torch.FloatTensor(inp))[0].detach()).softmax(1)[:,0].unsqueeze(0))\n",
" y_p_test = torch.cat(y_p_test_n, dim=0).mean(dim=0).cpu().numpy()\n",
"\n",
" return xx, yy, y_p_test.reshape(100, 100)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"x_moons, y_moons = make_moons(n_samples=1000, shuffle=True, noise=0.1, random_state=0)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"id": "DsXigrdha3Os"
},
"outputs": [],
"source": [
"x_moons_t = torch.FloatTensor(x_moons[np.where(y_moons == 0)].tolist() + x_moons[np.where(y_moons == 1)].tolist()[:400])\n",
"y_moons_t = torch.LongTensor(y_moons[np.where(y_moons == 0)].tolist() + y_moons[np.where(y_moons == 1)].tolist()[:400])\n",
"\n",
"x_moons_t -= x_moons_t.mean(axis=0)\n",
"x_moons_t /= x_moons_t.std(axis=0)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
},
"id": "gcNYdc_tbEye",
"outputId": "69bc70f9-3d95-480f-97c6-b8eaab457a7c"
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure()\n",
"plt.scatter(x_moons_t[:,0], x_moons_t[:,1])\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"id": "zk9ISmgzbHEW"
},
"outputs": [],
"source": [
"class NetBayes(torch.nn.Module):\n",
" def __init__(self):\n",
" super().__init__()\n",
"\n",
" self.base = net = torch.nn.Sequential(\n",
" torch.nn.Linear(2, 32),\n",
" torch.nn.ReLU(),\n",
" torch.nn.Linear(32, 32),\n",
" torch.nn.ReLU(),\n",
" torch.nn.Dropout(0.3)\n",
" )\n",
" \n",
" self.head_b = torch.nn.Linear(32,10)\n",
" self.head_a = torch.nn.Linear(32,2)\n",
" \n",
" def forward(self, x):\n",
" x = self.base(x)\n",
" return self.head_a(x), self.head_b(x)\n",
"\n",
"net_bayes = NetBayes()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 102
},
"id": "BvZDnWq-l9vi",
"outputId": "d6154bde-9b6b-44fd-b7f1-51693f856fda"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-3.281165845692158e-07\n",
"-0.0023017022758722305\n",
"-0.14624759554862976\n",
"-0.3479679822921753\n",
"-0.43934932351112366\n"
]
}
],
"source": [
"opt = torch.optim.Adam(net_bayes.parameters(), lr=1e-4, weight_decay=1e-6)\n",
"net_bayes.train()\n",
"\n",
"# bootstrap with IIC\n",
"for e in range(500):\n",
" opt.zero_grad()\n",
" _, y_p_b_1 = net_bayes(x_moons_t + torch.randn_like(x_moons_t)*0.05)\n",
" _, y_p_b_2 = net_bayes(x_moons_t + torch.randn_like(x_moons_t)*0.15)\n",
" \n",
" loss = mutual_information(y_p_b_1.softmax(1), y_p_b_2.softmax(1))\n",
" loss.backward()\n",
" opt.step()\n",
"\n",
" opt.zero_grad()\n",
" y_p_a_1, _ = net_bayes(x_moons_t + torch.randn_like(x_moons_t)*0.05)\n",
" y_p_a_2, _ = net_bayes(x_moons_t + torch.randn_like(x_moons_t)*0.15)\n",
" \n",
" loss = mutual_information(y_p_a_1.softmax(1), y_p_a_2.softmax(1))\n",
" loss.backward()\n",
" opt.step()\n",
" \n",
" if e % 100 == 0:\n",
" print(loss.item())"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"id": "-yWaUywOdAxl"
},
"outputs": [],
"source": [
"T = 0.35\n",
"net_cl = deepcopy(net_bayes)\n",
"net_conf = deepcopy(net_bayes)\n",
"net_ours = deepcopy(net_bayes)\n",
"\n",
"epochs = 4000"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 289
},
"id": "rkcILFrbmEYA",
"outputId": "4a45b096-76ca-4953-a927-bcdbbc6078ff"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 0.13111111521720886\n",
"-0.4840652346611023\n",
"500 0.13555555045604706\n",
"-0.5790530443191528\n"
]
}
],
"source": [
"opt_cl = torch.optim.Adam(net_cl.parameters(), lr=1e-2, weight_decay=1e-6)\n",
"\n",
"for e in range(epochs//4): # we need way less iterations here\n",
" # shuffle batch\n",
" N = x_moons_t.size(0)\n",
" batch = torch.randperm(N)\n",
"\n",
" opt_cl.zero_grad()\n",
" y_p_a_1, _ = net_cl(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.05)\n",
" y_p_a_2, _ = net_cl(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.15)\n",
" \n",
" loss = mutual_information(y_p_a_1.softmax(1), y_p_a_2.softmax(1))\n",
"\n",
" loss.backward()\n",
" opt_cl.step()\n",
"\n",
" if e % 500 == 0:\n",
" with torch.no_grad():\n",
" y = net_cl(x_moons_t)[0]\n",
" print(e, ((y.argmax(1) == y_moons_t).sum().float() / y_moons_t.size(0)).item())\n",
"\n",
" print(loss.item())"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"id": "cv1odwr3gPsv"
},
"outputs": [],
"source": [
"_, _, y_test_cl = create_plot_data(net_cl, T)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 289
},
"id": "iQy0Hzo9hr_J",
"outputId": "8460368e-d62f-4508-d7e4-a01c74a468c5"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 0.12999999523162842\n",
"298 323 0.03344118222594261\n",
"500 0.09777777642011642\n",
"344 391 0.0033677611500024796\n",
"1000 0.08666666597127914\n",
"340 428 -0.01942259818315506\n",
"1500 0.07666666805744171\n",
"340 435 0.013390600681304932\n",
"2000 0.07999999821186066\n",
"341 429 -0.022545505315065384\n",
"2500 0.06111111119389534\n",
"344 435 -0.028293190523982048\n",
"3000 0.07666666805744171\n",
"343 435 -0.028790870681405067\n",
"3500 0.052222222089767456\n",
"347 472 -0.008332509547472\n"
]
}
],
"source": [
"opt_conf = torch.optim.Adam(net_conf.parameters(), lr=1e-2, weight_decay=1e-6)\n",
"\n",
"for e in range(epochs):\n",
" # shuffle batch\n",
" N = x_moons_t.size(0)\n",
" batch = torch.randperm(N)\n",
"\n",
" uncert, conf, pseudo_targets, conf_target = extract_pseudo_labels(net_conf, x_moons_t, T)\n",
"\n",
" opt_conf.zero_grad()\n",
" y_p_a_1, _ = net_conf(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.05)\n",
" y_p_a_2, _ = net_conf(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.15)\n",
" \n",
" loss_mi2 = mutual_information(y_p_a_1.softmax(1), y_p_a_2.softmax(1))\n",
" \n",
" # mixup training\n",
" lamb = torch.rand(1)\n",
" x_mixup, y_mixup = mixup(x_moons_t[batch][:N//2], x_moons_t[batch][N//2:(N//2)*2],\n",
" pseudo_targets[batch][:N//2], pseudo_targets[batch][N//2:(N//2)*2],\n",
" lamb=lamb,\n",
" num_classes=2)\n",
" y_p_1 = net_conf(x_moons_t[batch][:N//2])[0].softmax(1)\n",
" y_p_2 = net_conf(x_moons_t[batch][N//2:(N//2)*2])[0].softmax(1)\n",
" y_p_mixup = net_conf(x_mixup)[0].softmax(1)\n",
"\n",
" y_p_mixup2 = lamb*y_p_1 + (1-lamb)*y_p_2\n",
" loss_mixup = torch.nn.functional.mse_loss(y_p_mixup, y_p_mixup2)\n",
"\n",
" # pseudo-label training\n",
" y_pseudo = net_conf(conf + torch.randn_like(conf)*0.15)[0]\n",
" loss_pseudo = torch.nn.functional.cross_entropy(y_pseudo, conf_target)\n",
"\n",
" loss = 0.07*loss_mi2 + np.cos(e/epochs)*loss_mixup + 1.0*loss_pseudo\n",
" loss.backward()\n",
" opt_conf.step()\n",
"\n",
" if e % 500 == 0:\n",
" with torch.no_grad():\n",
" y = net_conf(x_moons_t)[0]\n",
" print(e, ((y.argmax(1) == y_moons_t).sum().float() / y_moons_t.size(0)).item())\n",
"\n",
" N_0 = conf[torch.where(conf_target == 0)].size(0)\n",
" N_1 = conf[torch.where(conf_target == 1)].size(0)\n",
" print(N_0, N_1, loss.item())"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"id": "iDerX-4-h36p"
},
"outputs": [],
"source": [
"_, _, y_test_conf = create_plot_data(net_conf, T)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 289
},
"id": "8Y8KKkuPgQAO",
"outputId": "2a738beb-ec78-4691-847f-d5345da252ff"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 0.13111111521720886\n",
"297 326 0.012329605408012867\n",
"500 0.09222222119569778\n",
"345 396 -0.005128343589603901\n",
"1000 0.09444444626569748\n",
"346 398 0.007566150743514299\n",
"1500 0.08444444090127945\n",
"340 428 -0.0097690774127841\n",
"2000 0.08222222328186035\n",
"341 429 -0.020236210897564888\n",
"2500 0.07000000029802322\n",
"344 437 0.006941571831703186\n",
"3000 0.06888888776302338\n",
"344 436 -0.030865471810102463\n",
"3500 0.06333333253860474\n",
"343 473 -0.026111770421266556\n"
]
}
],
"source": [
"opt_ours = torch.optim.Adam(net_ours.parameters(), lr=1e-2, weight_decay=1e-6)\n",
"\n",
"for e in range(epochs):\n",
" # shuffle batch\n",
" N = x_moons_t.size(0)\n",
" batch = torch.randperm(N)\n",
"\n",
" uncert, conf, pseudo_targets, conf_target = extract_pseudo_labels(net_ours, x_moons_t, T)\n",
"\n",
" opt_ours.zero_grad()\n",
" y_p_a_1, _ = net_ours(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.05)\n",
" y_p_a_2, _ = net_ours(x_moons_t[batch] + torch.randn_like(x_moons_t)*0.15)\n",
" \n",
" loss_mi2 = mutual_information(y_p_a_1.softmax(1), y_p_a_2.softmax(1))\n",
" \n",
" # mixup training\n",
" lamb = torch.rand(1)\n",
" x_mixup, y_mixup = mixup(x_moons_t[batch][:N//2], x_moons_t[batch][N//2:(N//2)*2],\n",
" pseudo_targets[batch][:N//2], pseudo_targets[batch][N//2:(N//2)*2],\n",
" lamb=lamb,\n",
" num_classes=2)\n",
" y_p_1 = net_ours(x_moons_t[batch][:N//2])[0].softmax(1)\n",
" y_p_2 = net_ours(x_moons_t[batch][N//2:(N//2)*2])[0].softmax(1)\n",
" y_p_mixup = net_ours(x_mixup)[0].softmax(1)\n",
"\n",
" y_p_mixup2 = lamb*y_p_1 + (1-lamb)*y_p_2\n",
" loss_mixup = torch.nn.functional.mse_loss(y_p_mixup, y_p_mixup2)\n",
"\n",
" # pseudo-label training\n",
" y_pseudo = net_ours(conf + torch.randn_like(conf)*0.15)[0]\n",
" loss_pseudo = torch.nn.functional.cross_entropy(y_pseudo, conf_target)\n",
"\n",
" loss = 0.07*loss_mi2 + np.cos(e/epochs)*loss_mixup + 1.0*loss_pseudo\n",
" loss.backward()\n",
" opt_ours.step()\n",
"\n",
" if e % 500 == 0:\n",
" with torch.no_grad():\n",
" y = net_ours(x_moons_t)[0]\n",
" print(e, ((y.argmax(1) == y_moons_t).sum().float() / y_moons_t.size(0)).item())\n",
"\n",
" N_0 = conf[torch.where(conf_target == 0)].size(0)\n",
" N_1 = conf[torch.where(conf_target == 1)].size(0)\n",
" print(N_0, N_1, loss.item())"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"id": "5EyVK4KdgO2z"
},
"outputs": [],
"source": [
"xx, yy, y_test_ours = create_plot_data(net_ours, T)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 199
},
"id": "-RCwH7pCi3a0",
"outputId": "37962a2c-550a-4a69-ce4d-eba3b1e139ac"
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 504x162 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(1, 3, figsize=(7,2.25), sharey=True)\n",
"\n",
"cs0 = ax[0].contourf(xx, yy, y_test_cl, levels=np.linspace(0, 1, 11))\n",
"cs02 = ax[0].contour(cs0, levels=[0, 0.5, 1], colors='tab:green', linewidths=1.5)\n",
"ax[0].plot(np.nan, color='tab:green', label='decision boundary')\n",
"ax[0].scatter(x_moons_t[::2,0], x_moons_t[::2,1], s=8)\n",
"ax[0].set_title('Consistency Learning')\n",
"ax[0].set_xlabel('x')\n",
"\n",
"cs1 = ax[1].contourf(xx, yy, y_test_conf, levels=np.linspace(0, 1, 11))\n",
"cs12 = ax[1].contour(cs1, levels=[0, 0.5, 1], colors='tab:green', linewidths=1.5)\n",
"ax[1].plot(np.nan, color='tab:green', label='decision boundary')\n",
"ax[1].scatter(x_moons_t[::2,0], x_moons_t[::2,1], s=8)\n",
"ax[1].set_title('CL+ConfPL')\n",
"ax[1].set_xlabel('x')\n",
"\n",
"cs2 = ax[2].contourf(xx, yy, y_test_ours, levels=np.linspace(0, 1, 11))\n",
"cs22 = ax[2].contour(cs2, levels=[0, 0.5, 1], colors='tab:green', linewidths=1.5)\n",
"ax[2].plot(np.nan, color='tab:green', label='decision boundary')\n",
"ax[2].scatter(x_moons_t[::2,0], x_moons_t[::2,1], s=8)\n",
"ax[2].set_title('CL+BatchPL (ours)')\n",
"ax[2].set_xlabel('x')\n",
"\n",
"fig.subplots_adjust(wspace=0.1, hspace=0.1,right=0.8)\n",
"cbar_ax = fig.add_axes([0.82, 0.13, 0.02, 0.67])\n",
"cbar = fig.colorbar(cs2, cax=cbar_ax)\n",
"cbar_ax.set_title(r'$p(c=0 \\vert \\ldots)$', loc='left', fontsize=8)\n",
"cbar.add_lines(cs22)\n",
"\n",
"ax[0].set_ylabel('y')\n",
"ax[0].legend(prop={'size': 8})\n",
"\n",
"fig.savefig(\"self_supervised_opener.pdf\", bbox_inches='tight', pad_inches=0.01)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "rIHEWqRWkn6g"
},
"outputs": [],
"source": []
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "two_moons_create_opener.ipynb",
"provenance": [],
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"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.7.7"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment