├── .gitignore ├── .ipynb_checkpoints └── ThermometerEncoding-checkpoint.ipynb ├── LSPGA.py ├── README.md ├── ThermometerEncoding.ipynb ├── encoder.py ├── models ├── __init__.py ├── __init__.pyc ├── densenet.py ├── densenet.pyc ├── dpn.py ├── dpn.pyc ├── googlenet.py ├── googlenet.pyc ├── lenet.py ├── lenet.pyc ├── mobilenet.py ├── mobilenet.pyc ├── preact_resnet.py ├── preact_resnet.pyc ├── resnet.py ├── resnet.pyc ├── resnext.py ├── resnext.pyc ├── senet.py ├── senet.pyc ├── shufflenet.py ├── shufflenet.pyc ├── vgg.py ├── vgg.pyc └── wide_resnet.py ├── test.py ├── train.py └── util.py /.gitignore: -------------------------------------------------------------------------------- 1 | /data 2 | *.pyc 3 | *.t7 4 | /checkpoint 5 | /.idea 6 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/ThermometerEncoding-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Thermometer encoding\n", 8 | "## Some util functions for convert a normal image to a one-hot way coded image\n", 9 | "\n", 10 | "### discription of a one-hot coded image:\n", 11 | "* n:batch size\n", 12 | "* w:width of a image\n", 13 | "* h:height of a image\n", 14 | "* k:k-level discretization of a image" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": { 21 | "collapsed": true 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "import numpy as np\n", 26 | "from sklearn.preprocessing import OneHotEncoder\n", 27 | "\"\"\"\n", 28 | "input:natural image arr:n*w*h*c\n", 29 | "return: quantisized image n*w*h*c\n", 30 | "\"\"\"\n", 31 | "def quantization(arr,k):\n", 32 | " quant = np.zeros(arr.shape)\n", 33 | " for i in range(1,k):\n", 34 | " quant[arr>1.0*i/k]+=1\n", 35 | " return quant\n", 36 | "\n", 37 | "\"\"\"\n", 38 | "input:quantisized img shape:n*w*h*c\n", 39 | "retun:one-hot coded image shape:n*w*h*c*k\n", 40 | "\"\"\"\n", 41 | "def onehot(arr,k):\n", 42 | " n,w,h = arr.shape\n", 43 | " arr = arr.reshape(n,-1)\n", 44 | " enc=OneHotEncoder(n_values=k,sparse=False)\n", 45 | " arr = enc.fit_transform(arr)\n", 46 | " arr = arr.reshape(n,w,h,k)\n", 47 | " arr = arr.transpose(0,3,1,2)\n", 48 | " return arr\n", 49 | "\n", 50 | "\"\"\"\n", 51 | "input:one-hot coded img shape:n*w*h*c*k\n", 52 | "retun:trmp coded image shape:n*w*h*c*k\n", 53 | "\"\"\"\n", 54 | "def tempcode(arr,k):\n", 55 | " tempcode = np.zeros(arr.shape)\n", 56 | " for i in range(k):\n", 57 | " tempcode[:,i,:,:] = np.sum(arr[:,:i+1,:,:],axis=1)\n", 58 | " return tempcode\n", 59 | " \n", 60 | "\"\"\"\n", 61 | "from a thermometerencoding image to a mormally coded image, for some visulization usage\n", 62 | "\"\"\"\n", 63 | "def temp2img(tempimg,k):\n", 64 | " img = np.sum(tempimg,axis=1)\n", 65 | " img = np.ones(img.shape)*(k+1)-img\n", 66 | " img = img*1.0/k\n", 67 | " return img\n" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### Test util functions" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 2, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [ 84 | { 85 | "name": "stdout", 86 | "output_type": "stream", 87 | "text": [ 88 | "[[[ 0.79451513 0.08269887]\n", 89 | " [ 0.31621181 0.62802222]]\n", 90 | "\n", 91 | " [[ 0.33544049 0.68535259]\n", 92 | " [ 0.97273507 0.12748406]]]\n", 93 | "(2, 2, 2)\n", 94 | "[[[ 3. 0.]\n", 95 | " [ 1. 2.]]\n", 96 | "\n", 97 | " [[ 1. 2.]\n", 98 | " [ 3. 0.]]]\n", 99 | "[[[ 0. 1.]\n", 100 | " [ 0. 0.]]\n", 101 | "\n", 102 | " [[ 0. 0.]\n", 103 | " [ 1. 0.]]\n", 104 | "\n", 105 | " [[ 0. 0.]\n", 106 | " [ 0. 1.]]\n", 107 | "\n", 108 | " [[ 1. 0.]\n", 109 | " [ 0. 0.]]]\n", 110 | "[[[ 0. 1.]\n", 111 | " [ 0. 0.]]\n", 112 | "\n", 113 | " [[ 0. 1.]\n", 114 | " [ 1. 0.]]\n", 115 | "\n", 116 | " [[ 0. 1.]\n", 117 | " [ 1. 1.]]\n", 118 | "\n", 119 | " [[ 1. 1.]\n", 120 | " [ 1. 1.]]]\n", 121 | "[[[ 1. 0.25]\n", 122 | " [ 0.5 0.75]]\n", 123 | "\n", 124 | " [[ 0.5 0.75]\n", 125 | " [ 1. 0.25]]]\n" 126 | ] 127 | } 128 | ], 129 | "source": [ 130 | "img = np.random.random((2, 2, 2))\n", 131 | "print img\n", 132 | "print img.shape\n", 133 | "quant = quantization(img,4)\n", 134 | "print quant\n", 135 | "onehotimg=onehot(quant,4)\n", 136 | "print onehotimg[0]\n", 137 | "tempcod = tempcode(onehotimg.copy(),4)\n", 138 | "print tempcod[0]\n", 139 | "recoverimg = temp2img(tempcod,4)\n", 140 | "print recoverimg" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "## Function with attacks\n", 148 | "### getmask\n", 149 | "input image x, random perbutation $\\epsilon$, get a mask for {$x-\\epsilon$,$x+\\epsilon$}" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 3, 155 | "metadata": { 156 | "collapsed": true 157 | }, 158 | "outputs": [], 159 | "source": [ 160 | "def getMask(x,epsilon,k):\n", 161 | " n,w,h = x.shape\n", 162 | " mask = np.zeros((n,k,w,h))\n", 163 | " low = x - epsilon\n", 164 | " low[low < 0] = 0\n", 165 | " high = x + epsilon\n", 166 | " high[high > 1] = 1\n", 167 | " for i in range(k+1):\n", 168 | " interimg = (i*1./k)*low + (1-i*1./k)*high\n", 169 | " mask+=onehot(quantization(interimg,k),k)\n", 170 | " mask[mask>1] = 1\n", 171 | " return mask" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 4, 177 | "metadata": { 178 | "collapsed": false 179 | }, 180 | "outputs": [ 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "[[[ 0.79451513 0.08269887]\n", 186 | " [ 0.31621181 0.62802222]]\n", 187 | "\n", 188 | " [[ 0.33544049 0.68535259]\n", 189 | " [ 0.97273507 0.12748406]]]\n", 190 | "[[[[ 0. 1.]\n", 191 | " [ 0. 0.]]\n", 192 | "\n", 193 | " [[ 0. 0.]\n", 194 | " [ 1. 0.]]\n", 195 | "\n", 196 | " [[ 0. 0.]\n", 197 | " [ 0. 1.]]\n", 198 | "\n", 199 | " [[ 1. 0.]\n", 200 | " [ 0. 0.]]]\n", 201 | "\n", 202 | "\n", 203 | " [[[ 0. 0.]\n", 204 | " [ 0. 1.]]\n", 205 | "\n", 206 | " [[ 1. 0.]\n", 207 | " [ 0. 0.]]\n", 208 | "\n", 209 | " [[ 0. 1.]\n", 210 | " [ 0. 0.]]\n", 211 | "\n", 212 | " [[ 0. 0.]\n", 213 | " [ 1. 0.]]]]\n", 214 | "[[[[ 0. 1.]\n", 215 | " [ 1. 0.]]\n", 216 | "\n", 217 | " [[ 1. 0.]\n", 218 | " [ 1. 0.]]\n", 219 | "\n", 220 | " [[ 1. 0.]\n", 221 | " [ 1. 1.]]\n", 222 | "\n", 223 | " [[ 1. 0.]\n", 224 | " [ 1. 0.]]]\n", 225 | "\n", 226 | "\n", 227 | " [[[ 1. 0.]\n", 228 | " [ 0. 1.]]\n", 229 | "\n", 230 | " [[ 1. 1.]\n", 231 | " [ 0. 1.]]\n", 232 | "\n", 233 | " [[ 1. 1.]\n", 234 | " [ 1. 1.]]\n", 235 | "\n", 236 | " [[ 0. 1.]\n", 237 | " [ 1. 0.]]]]\n" 238 | ] 239 | } 240 | ], 241 | "source": [ 242 | "print img\n", 243 | "print onehot(quantization(img,4),4)\n", 244 | "print getMask(img,np.random.random(img.shape)*0.5,4)" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 5, 250 | "metadata": { 251 | "collapsed": true 252 | }, 253 | "outputs": [], 254 | "source": [ 255 | "import torch\n", 256 | "import torch.nn as nn\n", 257 | "import torch.nn.functional as F\n", 258 | "import torch.optim as optim\n", 259 | "from torchvision import datasets, transforms\n", 260 | "from torch.autograd import Variable\n", 261 | "train_loader = torch.utils.data.DataLoader(\n", 262 | " datasets.MNIST('../data', train=True, download=True,\n", 263 | " transform=transforms.Compose([\n", 264 | " transforms.ToTensor(),\n", 265 | " ])),\n", 266 | " batch_size=100, shuffle=True)\n", 267 | "test_loader = torch.utils.data.DataLoader(\n", 268 | " datasets.MNIST('../data', train=False, transform=transforms.Compose([\n", 269 | " transforms.ToTensor(),\n", 270 | " ])),\n", 271 | " batch_size=100, shuffle=True)\n", 272 | "\n", 273 | "class Net(nn.Module):\n", 274 | " def __init__(self):\n", 275 | " super(Net, self).__init__()\n", 276 | " self.conv1 = nn.Conv2d(15, 32, kernel_size=5)\n", 277 | " self.conv2 = nn.Conv2d(32, 64, kernel_size=5)\n", 278 | " self.conv2_drop = nn.Dropout2d()\n", 279 | " self.fc1 = nn.Linear(4*4*64, 1024)\n", 280 | " self.fc2 = nn.Linear(1024, 10)\n", 281 | "\n", 282 | " def forward(self, x):\n", 283 | " x = F.relu(F.max_pool2d(self.conv1(x), 2))\n", 284 | " x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n", 285 | " x = x.view(-1, 4*4*64)\n", 286 | " x = F.relu(self.fc1(x))\n", 287 | " x = F.dropout(x, training=self.training)\n", 288 | " x = self.fc2(x)\n", 289 | " return x\n", 290 | "\n", 291 | "model = Net()\n", 292 | "model = model.cuda()" 293 | ] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": {}, 298 | "source": [ 299 | "### LS-PGD attack" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 11, 305 | "metadata": { 306 | "collapsed": true 307 | }, 308 | "outputs": [], 309 | "source": [ 310 | "def LSPGDonechannel(data,target,epsilon,k,delta,xi,step,criterion):\n", 311 | " datanumpy = data.numpy()\n", 312 | " data0 = datanumpy[:,0,:,:]\n", 313 | " mask = getMask(data0,epsilon,k)\n", 314 | " u = np.random.random(mask.shape)-(1-mask)*1e10\n", 315 | " T = 1.0\n", 316 | " u = Variable(torch.Tensor(u).cuda(),requires_grad=True)\n", 317 | " z = F.softmax(u/T,dim=1)\n", 318 | " z = torch.cumsum(z,dim=1)\n", 319 | " for t in range(step):\n", 320 | " out = model(z)\n", 321 | " loss = criterion(out,target)\n", 322 | " if u.grad!=None:\n", 323 | " u.grad.data._zero()\n", 324 | " loss.backward()\n", 325 | " grad = u.grad\n", 326 | " u = xi*torch.sign(grad) + u\n", 327 | " u = Variable(u.data,requires_grad=True)\n", 328 | " z = F.softmax(u/T,dim=1)\n", 329 | " z = torch.cumsum(z,dim=1)\n", 330 | " T = T*delta\n", 331 | " attackimg = np.argmax(u.data.cpu().numpy(),axis=1)\n", 332 | " themattackimg = tempcode(onehot(attackimg,k),k)\n", 333 | " return themattackimg" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "## Try on MNIST" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": 7, 346 | "metadata": { 347 | "collapsed": true 348 | }, 349 | "outputs": [], 350 | "source": [ 351 | "criterion = nn.CrossEntropyLoss()\n", 352 | "level=15\n", 353 | "optimizer = optim.Adam(model.parameters(), lr=1e-4)\n", 354 | "def trainnat(epoch):\n", 355 | " model.train()\n", 356 | " for batch_idx, (data, target) in enumerate(train_loader):\n", 357 | " target = Variable(target)\n", 358 | " data = data.numpy()[:,0,:,:]\n", 359 | " data = Variable(torch.Tensor(tempcode(onehot(quantization(data,level),level),level)))\n", 360 | " data, target = data.cuda(), target.cuda()\n", 361 | " optimizer.zero_grad()\n", 362 | " output = model(data)\n", 363 | " loss = criterion(output, target)\n", 364 | " loss.backward()\n", 365 | " optimizer.step()\n", 366 | " if batch_idx % 10 == 0:\n", 367 | " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", 368 | " epoch, batch_idx * len(data), len(train_loader.dataset),\n", 369 | " 100. * batch_idx / len(train_loader), loss.data[0]))\n", 370 | "\n", 371 | "def test():\n", 372 | " model.eval()\n", 373 | " test_loss = 0\n", 374 | " correct = 0\n", 375 | " for data, target in test_loader:\n", 376 | " target = Variable(target)\n", 377 | " data = data.numpy()[:,0,:,:]\n", 378 | " data = Variable(torch.Tensor(tempcode(onehot(quantization(data,level),level),level)))\n", 379 | " data, target = data.cuda(), target.cuda()\n", 380 | " output = model(data)\n", 381 | " test_loss += criterion(output, target).data[0] # sum up batch loss\n", 382 | " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", 383 | " correct += pred.eq(target.data.view_as(pred)).cpu().sum()\n", 384 | "\n", 385 | " test_loss /= len(test_loader.dataset)\n", 386 | " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", 387 | " test_loss, correct, len(test_loader.dataset),\n", 388 | " 100. * correct / len(test_loader.dataset)))\n", 389 | " \n", 390 | "def trainadv(epoch):\n", 391 | " model.train()\n", 392 | " for batch_idx, (data, target) in enumerate(train_loader):\n", 393 | " target = Variable(target.cuda())\n", 394 | " data = LSPGDonechannel(data=data,target=target,epsilon=0.3,k=level,delta=1.2,xi=1.0,step=2,criterion=criterion)\n", 395 | " data = Variable(torch.Tensor(data).cuda())\n", 396 | " optimizer.zero_grad()\n", 397 | " output = model(data)\n", 398 | " loss = criterion(output, target)\n", 399 | " loss.backward()\n", 400 | " optimizer.step()\n", 401 | " if batch_idx % 10 == 0:\n", 402 | " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", 403 | " epoch, batch_idx * len(data), len(train_loader.dataset),\n", 404 | " 100. * batch_idx / len(train_loader), loss.data[0]))\n", 405 | " \n", 406 | "def testadv():\n", 407 | " model.eval()\n", 408 | " test_loss = 0\n", 409 | " correct = 0\n", 410 | " for data, target in test_loader:\n", 411 | " target = target.cuda()\n", 412 | " target = Variable(target)\n", 413 | " data = LSPGDonechannel(data=data,target=target,epsilon=0.3,k=level,delta=1.2,xi=1.0,step=7,criterion=criterion)\n", 414 | " data = Variable(torch.Tensor(data).cuda())\n", 415 | " output = model(data)\n", 416 | " test_loss += criterion(output, target).data[0] # sum up batch loss\n", 417 | " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", 418 | " correct += pred.eq(target.data.view_as(pred)).cpu().sum()\n", 419 | "\n", 420 | " test_loss /= len(test_loader.dataset)\n", 421 | " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", 422 | " test_loss, correct, len(test_loader.dataset),\n", 423 | " 100. * correct / len(test_loader.dataset)))\n", 424 | "\n" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": {}, 430 | "source": [ 431 | "train for 1 epoh" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": 8, 437 | "metadata": { 438 | "collapsed": false, 439 | "scrolled": true 440 | }, 441 | "outputs": [ 442 | { 443 | "name": "stdout", 444 | "output_type": "stream", 445 | "text": [ 446 | "Train Epoch: 0 [0/60000 (0%)]\tLoss: 2.296473\n", 447 | "Train Epoch: 0 [1000/60000 (2%)]\tLoss: 2.281995\n", 448 | "Train Epoch: 0 [2000/60000 (3%)]\tLoss: 2.249601\n", 449 | "Train Epoch: 0 [3000/60000 (5%)]\tLoss: 2.161287\n", 450 | "Train Epoch: 0 [4000/60000 (7%)]\tLoss: 2.055316\n", 451 | "Train Epoch: 0 [5000/60000 (8%)]\tLoss: 1.854571\n", 452 | "Train Epoch: 0 [6000/60000 (10%)]\tLoss: 1.619478\n", 453 | "Train Epoch: 0 [7000/60000 (12%)]\tLoss: 1.428817\n", 454 | "Train Epoch: 0 [8000/60000 (13%)]\tLoss: 1.021998\n", 455 | "Train Epoch: 0 [9000/60000 (15%)]\tLoss: 0.984555\n", 456 | "Train Epoch: 0 [10000/60000 (17%)]\tLoss: 0.621356\n", 457 | "Train Epoch: 0 [11000/60000 (18%)]\tLoss: 0.534129\n", 458 | "Train Epoch: 0 [12000/60000 (20%)]\tLoss: 0.520464\n", 459 | "Train Epoch: 0 [13000/60000 (22%)]\tLoss: 0.535510\n", 460 | "Train Epoch: 0 [14000/60000 (23%)]\tLoss: 0.535267\n", 461 | "Train Epoch: 0 [15000/60000 (25%)]\tLoss: 0.529476\n", 462 | "Train Epoch: 0 [16000/60000 (27%)]\tLoss: 0.418255\n", 463 | "Train Epoch: 0 [17000/60000 (28%)]\tLoss: 0.605231\n", 464 | "Train Epoch: 0 [18000/60000 (30%)]\tLoss: 0.403791\n", 465 | "Train Epoch: 0 [19000/60000 (32%)]\tLoss: 0.362958\n", 466 | "Train Epoch: 0 [20000/60000 (33%)]\tLoss: 0.425205\n", 467 | "Train Epoch: 0 [21000/60000 (35%)]\tLoss: 0.441716\n", 468 | "Train Epoch: 0 [22000/60000 (37%)]\tLoss: 0.314216\n", 469 | "Train Epoch: 0 [23000/60000 (38%)]\tLoss: 0.407162\n", 470 | "Train Epoch: 0 [24000/60000 (40%)]\tLoss: 0.417334\n", 471 | "Train Epoch: 0 [25000/60000 (42%)]\tLoss: 0.464954\n", 472 | "Train Epoch: 0 [26000/60000 (43%)]\tLoss: 0.395768\n", 473 | "Train Epoch: 0 [27000/60000 (45%)]\tLoss: 0.471428\n", 474 | "Train Epoch: 0 [28000/60000 (47%)]\tLoss: 0.384233\n", 475 | "Train Epoch: 0 [29000/60000 (48%)]\tLoss: 0.237195\n", 476 | "Train Epoch: 0 [30000/60000 (50%)]\tLoss: 0.230448\n", 477 | "Train Epoch: 0 [31000/60000 (52%)]\tLoss: 0.482738\n", 478 | "Train Epoch: 0 [32000/60000 (53%)]\tLoss: 0.280180\n", 479 | "Train Epoch: 0 [33000/60000 (55%)]\tLoss: 0.340350\n", 480 | "Train Epoch: 0 [34000/60000 (57%)]\tLoss: 0.230954\n", 481 | "Train Epoch: 0 [35000/60000 (58%)]\tLoss: 0.359263\n", 482 | "Train Epoch: 0 [36000/60000 (60%)]\tLoss: 0.282059\n", 483 | "Train Epoch: 0 [37000/60000 (62%)]\tLoss: 0.229961\n", 484 | "Train Epoch: 0 [38000/60000 (63%)]\tLoss: 0.195395\n", 485 | "Train Epoch: 0 [39000/60000 (65%)]\tLoss: 0.273387\n", 486 | "Train Epoch: 0 [40000/60000 (67%)]\tLoss: 0.280653\n", 487 | "Train Epoch: 0 [41000/60000 (68%)]\tLoss: 0.202795\n", 488 | "Train Epoch: 0 [42000/60000 (70%)]\tLoss: 0.323157\n", 489 | "Train Epoch: 0 [43000/60000 (72%)]\tLoss: 0.339500\n", 490 | "Train Epoch: 0 [44000/60000 (73%)]\tLoss: 0.319159\n", 491 | "Train Epoch: 0 [45000/60000 (75%)]\tLoss: 0.285635\n", 492 | "Train Epoch: 0 [46000/60000 (77%)]\tLoss: 0.215550\n", 493 | "Train Epoch: 0 [47000/60000 (78%)]\tLoss: 0.241237\n", 494 | "Train Epoch: 0 [48000/60000 (80%)]\tLoss: 0.217412\n", 495 | "Train Epoch: 0 [49000/60000 (82%)]\tLoss: 0.194460\n", 496 | "Train Epoch: 0 [50000/60000 (83%)]\tLoss: 0.184959\n", 497 | "Train Epoch: 0 [51000/60000 (85%)]\tLoss: 0.240396\n", 498 | "Train Epoch: 0 [52000/60000 (87%)]\tLoss: 0.319755\n", 499 | "Train Epoch: 0 [53000/60000 (88%)]\tLoss: 0.239770\n", 500 | "Train Epoch: 0 [54000/60000 (90%)]\tLoss: 0.099248\n", 501 | "Train Epoch: 0 [55000/60000 (92%)]\tLoss: 0.292660\n", 502 | "Train Epoch: 0 [56000/60000 (93%)]\tLoss: 0.163331\n", 503 | "Train Epoch: 0 [57000/60000 (95%)]\tLoss: 0.180359\n", 504 | "Train Epoch: 0 [58000/60000 (97%)]\tLoss: 0.293773\n", 505 | "Train Epoch: 0 [59000/60000 (98%)]\tLoss: 0.280835\n" 506 | ] 507 | } 508 | ], 509 | "source": [ 510 | "trainnat(0)" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | "test on natral" 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 9, 523 | "metadata": { 524 | "collapsed": false 525 | }, 526 | "outputs": [ 527 | { 528 | "name": "stdout", 529 | "output_type": "stream", 530 | "text": [ 531 | "\n", 532 | "Test set: Average loss: 0.0013, Accuracy: 9603/10000 (96%)\n", 533 | "\n" 534 | ] 535 | } 536 | ], 537 | "source": [ 538 | "test()" 539 | ] 540 | }, 541 | { 542 | "cell_type": "markdown", 543 | "metadata": { 544 | "collapsed": true 545 | }, 546 | "source": [ 547 | "test on LS-PGD attack" 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "execution_count": 12, 553 | "metadata": { 554 | "collapsed": false 555 | }, 556 | "outputs": [ 557 | { 558 | "name": "stdout", 559 | "output_type": "stream", 560 | "text": [ 561 | "\n", 562 | "Test set: Average loss: 0.0783, Accuracy: 26/10000 (0%)\n", 563 | "\n" 564 | ] 565 | } 566 | ], 567 | "source": [ 568 | "testadv()" 569 | ] 570 | }, 571 | { 572 | "cell_type": "markdown", 573 | "metadata": {}, 574 | "source": [ 575 | "advtrain on LS-PGD attack " 576 | ] 577 | }, 578 | { 579 | "cell_type": "code", 580 | "execution_count": 13, 581 | "metadata": { 582 | "collapsed": false 583 | }, 584 | "outputs": [ 585 | { 586 | "name": "stdout", 587 | "output_type": "stream", 588 | "text": [ 589 | "Train Epoch: 0 [0/60000 (0%)]\tLoss: 4.778333\n", 590 | "Train Epoch: 0 [1000/60000 (2%)]\tLoss: 2.234309\n", 591 | "Train Epoch: 0 [2000/60000 (3%)]\tLoss: 1.926022\n", 592 | "Train Epoch: 0 [3000/60000 (5%)]\tLoss: 1.505311\n", 593 | "Train Epoch: 0 [4000/60000 (7%)]\tLoss: 1.499077\n", 594 | "Train Epoch: 0 [5000/60000 (8%)]\tLoss: 1.308034\n", 595 | "Train Epoch: 0 [6000/60000 (10%)]\tLoss: 1.426866\n", 596 | "Train Epoch: 0 [7000/60000 (12%)]\tLoss: 1.118608\n", 597 | "Train Epoch: 0 [8000/60000 (13%)]\tLoss: 1.097754\n", 598 | "Train Epoch: 0 [9000/60000 (15%)]\tLoss: 1.017607\n", 599 | "Train Epoch: 0 [10000/60000 (17%)]\tLoss: 1.128312\n", 600 | "Train Epoch: 0 [11000/60000 (18%)]\tLoss: 0.909971\n", 601 | "Train Epoch: 0 [12000/60000 (20%)]\tLoss: 0.858213\n", 602 | "Train Epoch: 0 [13000/60000 (22%)]\tLoss: 0.842452\n", 603 | "Train Epoch: 0 [14000/60000 (23%)]\tLoss: 0.828172\n", 604 | "Train Epoch: 0 [15000/60000 (25%)]\tLoss: 1.056247\n", 605 | "Train Epoch: 0 [16000/60000 (27%)]\tLoss: 0.659280\n", 606 | "Train Epoch: 0 [17000/60000 (28%)]\tLoss: 0.791528\n", 607 | "Train Epoch: 0 [18000/60000 (30%)]\tLoss: 0.825837\n", 608 | "Train Epoch: 0 [19000/60000 (32%)]\tLoss: 0.876002\n", 609 | "Train Epoch: 0 [20000/60000 (33%)]\tLoss: 0.781835\n", 610 | "Train Epoch: 0 [21000/60000 (35%)]\tLoss: 0.713966\n", 611 | "Train Epoch: 0 [22000/60000 (37%)]\tLoss: 0.578799\n", 612 | "Train Epoch: 0 [23000/60000 (38%)]\tLoss: 0.698011\n", 613 | "Train Epoch: 0 [24000/60000 (40%)]\tLoss: 0.876671\n", 614 | "Train Epoch: 0 [25000/60000 (42%)]\tLoss: 0.567656\n", 615 | "Train Epoch: 0 [26000/60000 (43%)]\tLoss: 0.512513\n", 616 | "Train Epoch: 0 [27000/60000 (45%)]\tLoss: 0.701109\n", 617 | "Train Epoch: 0 [28000/60000 (47%)]\tLoss: 0.562018\n", 618 | "Train Epoch: 0 [29000/60000 (48%)]\tLoss: 0.596192\n", 619 | "Train Epoch: 0 [30000/60000 (50%)]\tLoss: 0.703907\n", 620 | "Train Epoch: 0 [31000/60000 (52%)]\tLoss: 0.649177\n", 621 | "Train Epoch: 0 [32000/60000 (53%)]\tLoss: 0.605773\n", 622 | "Train Epoch: 0 [33000/60000 (55%)]\tLoss: 0.493994\n", 623 | "Train Epoch: 0 [34000/60000 (57%)]\tLoss: 0.691156\n", 624 | "Train Epoch: 0 [35000/60000 (58%)]\tLoss: 0.777433\n", 625 | "Train Epoch: 0 [36000/60000 (60%)]\tLoss: 0.816369\n", 626 | "Train Epoch: 0 [37000/60000 (62%)]\tLoss: 0.566725\n", 627 | "Train Epoch: 0 [38000/60000 (63%)]\tLoss: 0.738298\n", 628 | "Train Epoch: 0 [39000/60000 (65%)]\tLoss: 0.537736\n", 629 | "Train Epoch: 0 [40000/60000 (67%)]\tLoss: 0.648210\n", 630 | "Train Epoch: 0 [41000/60000 (68%)]\tLoss: 0.642458\n", 631 | "Train Epoch: 0 [42000/60000 (70%)]\tLoss: 0.632553\n", 632 | "Train Epoch: 0 [43000/60000 (72%)]\tLoss: 0.582097\n", 633 | "Train Epoch: 0 [44000/60000 (73%)]\tLoss: 0.750218\n", 634 | "Train Epoch: 0 [45000/60000 (75%)]\tLoss: 0.437618\n", 635 | "Train Epoch: 0 [46000/60000 (77%)]\tLoss: 0.482472\n", 636 | "Train Epoch: 0 [47000/60000 (78%)]\tLoss: 0.524253\n", 637 | "Train Epoch: 0 [48000/60000 (80%)]\tLoss: 0.463634\n", 638 | "Train Epoch: 0 [49000/60000 (82%)]\tLoss: 0.587060\n", 639 | "Train Epoch: 0 [50000/60000 (83%)]\tLoss: 0.584792\n", 640 | "Train Epoch: 0 [51000/60000 (85%)]\tLoss: 0.620650\n", 641 | "Train Epoch: 0 [52000/60000 (87%)]\tLoss: 0.370396\n", 642 | "Train Epoch: 0 [53000/60000 (88%)]\tLoss: 0.503538\n", 643 | "Train Epoch: 0 [54000/60000 (90%)]\tLoss: 0.430511\n", 644 | "Train Epoch: 0 [55000/60000 (92%)]\tLoss: 0.426360\n", 645 | "Train Epoch: 0 [56000/60000 (93%)]\tLoss: 0.434016\n", 646 | "Train Epoch: 0 [57000/60000 (95%)]\tLoss: 0.404179\n", 647 | "Train Epoch: 0 [58000/60000 (97%)]\tLoss: 0.497083\n", 648 | "Train Epoch: 0 [59000/60000 (98%)]\tLoss: 0.422729\n" 649 | ] 650 | } 651 | ], 652 | "source": [ 653 | "trainadv(0)" 654 | ] 655 | }, 656 | { 657 | "cell_type": "markdown", 658 | "metadata": {}, 659 | "source": [ 660 | "test after advtrain" 661 | ] 662 | }, 663 | { 664 | "cell_type": "code", 665 | "execution_count": 14, 666 | "metadata": { 667 | "collapsed": false 668 | }, 669 | "outputs": [ 670 | { 671 | "name": "stdout", 672 | "output_type": "stream", 673 | "text": [ 674 | "\n", 675 | "Test set: Average loss: 0.0069, Accuracy: 7547/10000 (75%)\n", 676 | "\n" 677 | ] 678 | } 679 | ], 680 | "source": [ 681 | "testadv()" 682 | ] 683 | }, 684 | { 685 | "cell_type": "code", 686 | "execution_count": null, 687 | "metadata": { 688 | "collapsed": true 689 | }, 690 | "outputs": [], 691 | "source": [] 692 | } 693 | ], 694 | "metadata": { 695 | "kernelspec": { 696 | "display_name": "Python 2", 697 | "language": "python", 698 | "name": "python2" 699 | }, 700 | "language_info": { 701 | "codemirror_mode": { 702 | "name": "ipython", 703 | "version": 2 704 | }, 705 | "file_extension": ".py", 706 | "mimetype": "text/x-python", 707 | "name": "python", 708 | "nbconvert_exporter": "python", 709 | "pygments_lexer": "ipython2", 710 | "version": "2.7.13" 711 | } 712 | }, 713 | "nbformat": 4, 714 | "nbformat_minor": 2 715 | } 716 | -------------------------------------------------------------------------------- /LSPGA.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import torch.nn.functional as F 4 | from torch.autograd import Variable 5 | 6 | 7 | class LSPGA(object): 8 | def __init__(self,model,epsilon,k,delta,xi,step,criterion,encoder): 9 | self.model = model 10 | self.epsilon = epsilon # l-inf norm bound of image 11 | self.k=k # k-level quantization 12 | self.delta = delta # annealing factor 13 | self.xi = xi # step-size of attack 14 | self.step = step # attack steps 15 | self.criterion = criterion # loss func 16 | self.encoder = encoder # temp encoder 17 | 18 | def getMask(self,x): 19 | n,w,h = x.shape 20 | mask = np.zeros((n,self.k,w,h)) 21 | low = x - self.epsilon 22 | low[low < 0] = 0 23 | high = x + self.epsilon 24 | high[high > 1] = 1 25 | for i in range(self.k+1): 26 | interimg = (i*1./self.k)*low + (1-i*1./self.k)*high 27 | mask+=self.encoder.onehotencoding(interimg) 28 | mask[mask>1] = 1 29 | return mask 30 | 31 | def attackthreechannel(self, data, target): 32 | target = Variable(target.cuda()) 33 | datanumpy = data.numpy() 34 | channel0, channel1, channel2 = (datanumpy[:, i, :, :] for i in range(3)) 35 | mask0, mask1, mask2 = (self.getMask(channel) for channel in [channel0, channel1, channel2]) 36 | u0, u1, u2 = (np.random.random(mask.shape) - (1 - mask) * 1e10 for mask in [mask0, mask1, mask2]) 37 | T = 1.0 38 | u0, u1, u2 = (Variable(torch.Tensor(u).cuda(), requires_grad=True) for u in [u0, u1, u2]) 39 | z0, z1, z2 = (F.softmax(u / T, dim=1) for u in [u0, u1, u2]) 40 | z0, z1, z2 = (torch.cumsum(z, dim=1) for z in [z0, z1, z2]) 41 | for t in range(self.step): 42 | out = self.model(z0, z1, z2) 43 | loss = self.criterion(out, target) 44 | for u in [u0, u1, u2]: 45 | if u.grad != None: 46 | u.grad.data._zero() 47 | loss.backward() 48 | grad0, grad1, grad2 = (u.grad for u in [u0, u1, u2]) 49 | u0, u1, u2 = (self.xi * torch.sign(grad) + u for (grad, u) in zip([grad0, grad1, grad2], [u0, u1,u2])) 50 | u0, u1, u2 = (Variable(u.data, requires_grad=True) for u in [u0, u1, u2]) 51 | z0, z1, z2 = (F.softmax(u / T, dim=1) for u in [u0, u1, u2]) 52 | z0, z1, z2 = (torch.cumsum(z, dim=1) for z in [z0, z1, z2]) 53 | T = T * self.delta 54 | c0, c1, c2 = (np.argmax(u.data.cpu().numpy(), axis=1) for u in [u0, u1, u2]) 55 | them0, them1, them2 = (self.encoder.tempcode(self.encoder.onehot(c)) for c in [c0, c1, c2]) 56 | return them0, them1, them2 57 | 58 | 59 | def attackonechannel(self, data, target): 60 | target = Variable(target.cuda()) 61 | datanumpy = data.numpy() 62 | data0 = datanumpy[:, 0, :, :] 63 | mask = self.getMask(data0) 64 | u = np.random.random(mask.shape) - (1 - mask) * 1e10 65 | T = 1.0 66 | u = Variable(torch.Tensor(u).cuda(), requires_grad=True) 67 | z = F.softmax(u / T, dim=1) 68 | z = torch.cumsum(z, dim=1) 69 | for t in range(self.step): 70 | out = self.model(z) 71 | loss = self.criterion(out, target) 72 | if u.grad != None: 73 | u.grad.data._zero() 74 | loss.backward() 75 | grad = u.grad 76 | u = self.xi * torch.sign(grad) + u 77 | u = Variable(u.data, requires_grad=True) 78 | z = F.softmax(u / T, dim=1) 79 | z = torch.cumsum(z, dim=1) 80 | T = T * self.delta 81 | attackimg = np.argmax(u.data.cpu().numpy(), axis=1) 82 | themattackimg = self.encoder.tempcode(self.encoder.onehot(attackimg)) 83 | return themattackimg 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ThermometerEncoding 2 | This is a repo trying to reproduce [Thermometer Encoding: One Hot Way To Resist Adversarial Examples](https://openreview.net/forum?id=S18Su--CW) in pytorch. 3 | 4 | ### Results on CIFAR10 5 | 6 | I use ResNet-50 to reproduce the experiment instead of a Wide-ResNet. All LS-PGA attack is 7-step iterative white-box attack. However, I find that if I increase the attack step-size, attack failure rate will drop dramatically. 7 | 8 | | | clean | LS-PGA $$\xi=0.01$$ | LS-PGA $$\xi=0.1$$ | LS-PGA $$\xi=1$$ | results on the paper(LS-PGA) | results on the paper(clean) | 9 | | ------------- | ------ | ------------------- | ------------------ | ---------------- | ---------------------------- | --------------------------- | 10 | | clean trained | 91.52% | 43.27% | 3.14% | 0.12% | 50.50% | 94.22% | 11 | | adv trained | 89.75% | 74.00% | 27.44% | 15.02% | 79.16% | 89.88% | -------------------------------------------------------------------------------- /ThermometerEncoding.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Thermometer encoding\n", 8 | "## Some util functions for convert a normal image to a one-hot way coded image\n", 9 | "\n", 10 | "### discription of a one-hot coded image:\n", 11 | "* n:batch size\n", 12 | "* w:width of a image\n", 13 | "* h:height of a image\n", 14 | "* k:k-level discretization of a image" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": { 21 | "collapsed": true 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "import numpy as np\n", 26 | "from sklearn.preprocessing import OneHotEncoder\n", 27 | "\"\"\"\n", 28 | "input:natural image arr:n*w*h*c\n", 29 | "return: quantisized image n*w*h*c\n", 30 | "\"\"\"\n", 31 | "def quantization(arr,k):\n", 32 | " quant = np.zeros(arr.shape)\n", 33 | " for i in range(1,k):\n", 34 | " quant[arr>1.0*i/k]+=1\n", 35 | " return quant\n", 36 | "\n", 37 | "\"\"\"\n", 38 | "input:quantisized img shape:n*w*h*c\n", 39 | "retun:one-hot coded image shape:n*w*h*c*k\n", 40 | "\"\"\"\n", 41 | "def onehot(arr,k):\n", 42 | " n,w,h = arr.shape\n", 43 | " arr = arr.reshape(n,-1)\n", 44 | " enc=OneHotEncoder(n_values=k,sparse=False)\n", 45 | " arr = enc.fit_transform(arr)\n", 46 | " arr = arr.reshape(n,w,h,k)\n", 47 | " arr = arr.transpose(0,3,1,2)\n", 48 | " return arr\n", 49 | "\n", 50 | "\"\"\"\n", 51 | "input:one-hot coded img shape:n*w*h*c*k\n", 52 | "retun:trmp coded image shape:n*w*h*c*k\n", 53 | "\"\"\"\n", 54 | "def tempcode(arr,k):\n", 55 | " tempcode = np.zeros(arr.shape)\n", 56 | " for i in range(k):\n", 57 | " tempcode[:,i,:,:] = np.sum(arr[:,:i+1,:,:],axis=1)\n", 58 | " return tempcode\n", 59 | " \n", 60 | "\"\"\"\n", 61 | "from a thermometerencoding image to a mormally coded image, for some visulization usage\n", 62 | "\"\"\"\n", 63 | "def temp2img(tempimg,k):\n", 64 | " img = np.sum(tempimg,axis=1)\n", 65 | " img = np.ones(img.shape)*(k+1)-img\n", 66 | " img = img*1.0/k\n", 67 | " return img" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### Test util functions" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 2, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "name": "stdout", 84 | "output_type": "stream", 85 | "text": [ 86 | "[[[ 0.79451513 0.08269887]\n", 87 | " [ 0.31621181 0.62802222]]\n", 88 | "\n", 89 | " [[ 0.33544049 0.68535259]\n", 90 | " [ 0.97273507 0.12748406]]]\n", 91 | "(2, 2, 2)\n", 92 | "[[[ 3. 0.]\n", 93 | " [ 1. 2.]]\n", 94 | "\n", 95 | " [[ 1. 2.]\n", 96 | " [ 3. 0.]]]\n", 97 | "[[[ 0. 1.]\n", 98 | " [ 0. 0.]]\n", 99 | "\n", 100 | " [[ 0. 0.]\n", 101 | " [ 1. 0.]]\n", 102 | "\n", 103 | " [[ 0. 0.]\n", 104 | " [ 0. 1.]]\n", 105 | "\n", 106 | " [[ 1. 0.]\n", 107 | " [ 0. 0.]]]\n", 108 | "[[[ 0. 1.]\n", 109 | " [ 0. 0.]]\n", 110 | "\n", 111 | " [[ 0. 1.]\n", 112 | " [ 1. 0.]]\n", 113 | "\n", 114 | " [[ 0. 1.]\n", 115 | " [ 1. 1.]]\n", 116 | "\n", 117 | " [[ 1. 1.]\n", 118 | " [ 1. 1.]]]\n", 119 | "[[[ 1. 0.25]\n", 120 | " [ 0.5 0.75]]\n", 121 | "\n", 122 | " [[ 0.5 0.75]\n", 123 | " [ 1. 0.25]]]\n" 124 | ] 125 | } 126 | ], 127 | "source": [ 128 | "img = np.random.random((2, 2, 2))\n", 129 | "print img\n", 130 | "print img.shape\n", 131 | "quant = quantization(img,4)\n", 132 | "print quant\n", 133 | "onehotimg=onehot(quant,4)\n", 134 | "print onehotimg[0]\n", 135 | "tempcod = tempcode(onehotimg.copy(),4)\n", 136 | "print tempcod[0]\n", 137 | "recoverimg = temp2img(tempcod,4)\n", 138 | "print recoverimg" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "## Function with attacks\n", 146 | "### getmask\n", 147 | "input image x, random perbutation $\\epsilon$, get a mask for {$x-\\epsilon$,$x+\\epsilon$}" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 3, 153 | "metadata": { 154 | "collapsed": true 155 | }, 156 | "outputs": [], 157 | "source": [ 158 | "def getMask(x,epsilon,k):\n", 159 | " n,w,h = x.shape\n", 160 | " mask = np.zeros((n,k,w,h))\n", 161 | " low = x - epsilon\n", 162 | " low[low < 0] = 0\n", 163 | " high = x + epsilon\n", 164 | " high[high > 1] = 1\n", 165 | " for i in range(k+1):\n", 166 | " interimg = (i*1./k)*low + (1-i*1./k)*high\n", 167 | " mask+=onehot(quantization(interimg,k),k)\n", 168 | " mask[mask>1] = 1\n", 169 | " return mask" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 4, 175 | "metadata": {}, 176 | "outputs": [ 177 | { 178 | "name": "stdout", 179 | "output_type": "stream", 180 | "text": [ 181 | "[[[ 0.79451513 0.08269887]\n", 182 | " [ 0.31621181 0.62802222]]\n", 183 | "\n", 184 | " [[ 0.33544049 0.68535259]\n", 185 | " [ 0.97273507 0.12748406]]]\n", 186 | "[[[[ 0. 1.]\n", 187 | " [ 0. 0.]]\n", 188 | "\n", 189 | " [[ 0. 0.]\n", 190 | " [ 1. 0.]]\n", 191 | "\n", 192 | " [[ 0. 0.]\n", 193 | " [ 0. 1.]]\n", 194 | "\n", 195 | " [[ 1. 0.]\n", 196 | " [ 0. 0.]]]\n", 197 | "\n", 198 | "\n", 199 | " [[[ 0. 0.]\n", 200 | " [ 0. 1.]]\n", 201 | "\n", 202 | " [[ 1. 0.]\n", 203 | " [ 0. 0.]]\n", 204 | "\n", 205 | " [[ 0. 1.]\n", 206 | " [ 0. 0.]]\n", 207 | "\n", 208 | " [[ 0. 0.]\n", 209 | " [ 1. 0.]]]]\n", 210 | "[[[[ 0. 1.]\n", 211 | " [ 1. 0.]]\n", 212 | "\n", 213 | " [[ 1. 0.]\n", 214 | " [ 1. 0.]]\n", 215 | "\n", 216 | " [[ 1. 0.]\n", 217 | " [ 1. 1.]]\n", 218 | "\n", 219 | " [[ 1. 0.]\n", 220 | " [ 1. 0.]]]\n", 221 | "\n", 222 | "\n", 223 | " [[[ 1. 0.]\n", 224 | " [ 0. 1.]]\n", 225 | "\n", 226 | " [[ 1. 1.]\n", 227 | " [ 0. 1.]]\n", 228 | "\n", 229 | " [[ 1. 1.]\n", 230 | " [ 1. 1.]]\n", 231 | "\n", 232 | " [[ 0. 1.]\n", 233 | " [ 1. 0.]]]]\n" 234 | ] 235 | } 236 | ], 237 | "source": [ 238 | "print img\n", 239 | "print onehot(quantization(img,4),4)\n", 240 | "print getMask(img,np.random.random(img.shape)*0.5,4)" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": 5, 246 | "metadata": { 247 | "collapsed": true 248 | }, 249 | "outputs": [], 250 | "source": [ 251 | "import torch\n", 252 | "import torch.nn as nn\n", 253 | "import torch.nn.functional as F\n", 254 | "import torch.optim as optim\n", 255 | "from torchvision import datasets, transforms\n", 256 | "from torch.autograd import Variable\n", 257 | "train_loader = torch.utils.data.DataLoader(\n", 258 | " datasets.MNIST('../data', train=True, download=True,\n", 259 | " transform=transforms.Compose([\n", 260 | " transforms.ToTensor(),\n", 261 | " ])),\n", 262 | " batch_size=100, shuffle=True)\n", 263 | "test_loader = torch.utils.data.DataLoader(\n", 264 | " datasets.MNIST('../data', train=False, transform=transforms.Compose([\n", 265 | " transforms.ToTensor(),\n", 266 | " ])),\n", 267 | " batch_size=100, shuffle=True)\n", 268 | "\n", 269 | "class Net(nn.Module):\n", 270 | " def __init__(self):\n", 271 | " super(Net, self).__init__()\n", 272 | " self.conv1 = nn.Conv2d(15, 32, kernel_size=5)\n", 273 | " self.conv2 = nn.Conv2d(32, 64, kernel_size=5)\n", 274 | " self.conv2_drop = nn.Dropout2d()\n", 275 | " self.fc1 = nn.Linear(4*4*64, 1024)\n", 276 | " self.fc2 = nn.Linear(1024, 10)\n", 277 | "\n", 278 | " def forward(self, x):\n", 279 | " x = F.relu(F.max_pool2d(self.conv1(x), 2))\n", 280 | " x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n", 281 | " x = x.view(-1, 4*4*64)\n", 282 | " x = F.relu(self.fc1(x))\n", 283 | " x = F.dropout(x, training=self.training)\n", 284 | " x = self.fc2(x)\n", 285 | " return x\n", 286 | "\n", 287 | "model = Net()\n", 288 | "model = model.cuda()" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "### LS-PGD attack" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 11, 301 | "metadata": { 302 | "collapsed": true 303 | }, 304 | "outputs": [], 305 | "source": [ 306 | "def LSPGDonechannel(data,target,epsilon,k,delta,xi,step,criterion):\n", 307 | " datanumpy = data.numpy()\n", 308 | " data0 = datanumpy[:,0,:,:]\n", 309 | " mask = getMask(data0,epsilon,k)\n", 310 | " u = np.random.random(mask.shape)-(1-mask)*1e10\n", 311 | " T = 1.0\n", 312 | " u = Variable(torch.Tensor(u).cuda(),requires_grad=True)\n", 313 | " z = F.softmax(u/T,dim=1)\n", 314 | " z = torch.cumsum(z,dim=1)\n", 315 | " for t in range(step):\n", 316 | " out = model(z)\n", 317 | " loss = criterion(out,target)\n", 318 | " if u.grad!=None:\n", 319 | " u.grad.data._zero()\n", 320 | " loss.backward()\n", 321 | " grad = u.grad\n", 322 | " u = xi*torch.sign(grad) + u\n", 323 | " u = Variable(u.data,requires_grad=True)\n", 324 | " z = F.softmax(u/T,dim=1)\n", 325 | " z = torch.cumsum(z,dim=1)\n", 326 | " T = T*delta\n", 327 | " attackimg = np.argmax(u.data.cpu().numpy(),axis=1)\n", 328 | " themattackimg = tempcode(onehot(attackimg,k),k)\n", 329 | " return themattackimg" 330 | ] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": {}, 335 | "source": [ 336 | "## Try on MNIST" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": 7, 342 | "metadata": { 343 | "collapsed": true 344 | }, 345 | "outputs": [], 346 | "source": [ 347 | "criterion = nn.CrossEntropyLoss()\n", 348 | "level=15\n", 349 | "optimizer = optim.Adam(model.parameters(), lr=1e-4)\n", 350 | "def trainnat(epoch):\n", 351 | " model.train()\n", 352 | " for batch_idx, (data, target) in enumerate(train_loader):\n", 353 | " target = Variable(target)\n", 354 | " data = data.numpy()[:,0,:,:]\n", 355 | " data = Variable(torch.Tensor(tempcode(onehot(quantization(data,level),level),level)))\n", 356 | " data, target = data.cuda(), target.cuda()\n", 357 | " optimizer.zero_grad()\n", 358 | " output = model(data)\n", 359 | " loss = criterion(output, target)\n", 360 | " loss.backward()\n", 361 | " optimizer.step()\n", 362 | " if batch_idx % 10 == 0:\n", 363 | " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", 364 | " epoch, batch_idx * len(data), len(train_loader.dataset),\n", 365 | " 100. * batch_idx / len(train_loader), loss.data[0]))\n", 366 | "\n", 367 | "def test():\n", 368 | " model.eval()\n", 369 | " test_loss = 0\n", 370 | " correct = 0\n", 371 | " for data, target in test_loader:\n", 372 | " target = Variable(target)\n", 373 | " data = data.numpy()[:,0,:,:]\n", 374 | " data = Variable(torch.Tensor(tempcode(onehot(quantization(data,level),level),level)))\n", 375 | " data, target = data.cuda(), target.cuda()\n", 376 | " output = model(data)\n", 377 | " test_loss += criterion(output, target).data[0] # sum up batch loss\n", 378 | " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", 379 | " correct += pred.eq(target.data.view_as(pred)).cpu().sum()\n", 380 | "\n", 381 | " test_loss /= len(test_loader.dataset)\n", 382 | " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", 383 | " test_loss, correct, len(test_loader.dataset),\n", 384 | " 100. * correct / len(test_loader.dataset)))\n", 385 | " \n", 386 | "def trainadv(epoch):\n", 387 | " model.train()\n", 388 | " for batch_idx, (data, target) in enumerate(train_loader):\n", 389 | " target = Variable(target.cuda())\n", 390 | " data = LSPGDonechannel(data=data,target=target,epsilon=0.3,k=level,delta=1.2,xi=1.0,step=2,criterion=criterion)\n", 391 | " data = Variable(torch.Tensor(data).cuda())\n", 392 | " optimizer.zero_grad()\n", 393 | " output = model(data)\n", 394 | " loss = criterion(output, target)\n", 395 | " loss.backward()\n", 396 | " optimizer.step()\n", 397 | " if batch_idx % 10 == 0:\n", 398 | " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", 399 | " epoch, batch_idx * len(data), len(train_loader.dataset),\n", 400 | " 100. * batch_idx / len(train_loader), loss.data[0]))\n", 401 | " \n", 402 | "def testadv():\n", 403 | " model.eval()\n", 404 | " test_loss = 0\n", 405 | " correct = 0\n", 406 | " for data, target in test_loader:\n", 407 | " target = target.cuda()\n", 408 | " target = Variable(target)\n", 409 | " data = LSPGDonechannel(data=data,target=target,epsilon=0.3,k=level,delta=1.2,xi=1.0,step=7,criterion=criterion)\n", 410 | " data = Variable(torch.Tensor(data).cuda())\n", 411 | " output = model(data)\n", 412 | " test_loss += criterion(output, target).data[0] # sum up batch loss\n", 413 | " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", 414 | " correct += pred.eq(target.data.view_as(pred)).cpu().sum()\n", 415 | "\n", 416 | " test_loss /= len(test_loader.dataset)\n", 417 | " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", 418 | " test_loss, correct, len(test_loader.dataset),\n", 419 | " 100. * correct / len(test_loader.dataset)))" 420 | ] 421 | }, 422 | { 423 | "cell_type": "markdown", 424 | "metadata": {}, 425 | "source": [ 426 | "train for 1 epoh" 427 | ] 428 | }, 429 | { 430 | "cell_type": "code", 431 | "execution_count": 8, 432 | "metadata": { 433 | "scrolled": true 434 | }, 435 | "outputs": [ 436 | { 437 | "name": "stdout", 438 | "output_type": "stream", 439 | "text": [ 440 | "Train Epoch: 0 [0/60000 (0%)]\tLoss: 2.296473\n", 441 | "Train Epoch: 0 [1000/60000 (2%)]\tLoss: 2.281995\n", 442 | "Train Epoch: 0 [2000/60000 (3%)]\tLoss: 2.249601\n", 443 | "Train Epoch: 0 [3000/60000 (5%)]\tLoss: 2.161287\n", 444 | "Train Epoch: 0 [4000/60000 (7%)]\tLoss: 2.055316\n", 445 | "Train Epoch: 0 [5000/60000 (8%)]\tLoss: 1.854571\n", 446 | "Train Epoch: 0 [6000/60000 (10%)]\tLoss: 1.619478\n", 447 | "Train Epoch: 0 [7000/60000 (12%)]\tLoss: 1.428817\n", 448 | "Train Epoch: 0 [8000/60000 (13%)]\tLoss: 1.021998\n", 449 | "Train Epoch: 0 [9000/60000 (15%)]\tLoss: 0.984555\n", 450 | "Train Epoch: 0 [10000/60000 (17%)]\tLoss: 0.621356\n", 451 | "Train Epoch: 0 [11000/60000 (18%)]\tLoss: 0.534129\n", 452 | "Train Epoch: 0 [12000/60000 (20%)]\tLoss: 0.520464\n", 453 | "Train Epoch: 0 [13000/60000 (22%)]\tLoss: 0.535510\n", 454 | "Train Epoch: 0 [14000/60000 (23%)]\tLoss: 0.535267\n", 455 | "Train Epoch: 0 [15000/60000 (25%)]\tLoss: 0.529476\n", 456 | "Train Epoch: 0 [16000/60000 (27%)]\tLoss: 0.418255\n", 457 | "Train Epoch: 0 [17000/60000 (28%)]\tLoss: 0.605231\n", 458 | "Train Epoch: 0 [18000/60000 (30%)]\tLoss: 0.403791\n", 459 | "Train Epoch: 0 [19000/60000 (32%)]\tLoss: 0.362958\n", 460 | "Train Epoch: 0 [20000/60000 (33%)]\tLoss: 0.425205\n", 461 | "Train Epoch: 0 [21000/60000 (35%)]\tLoss: 0.441716\n", 462 | "Train Epoch: 0 [22000/60000 (37%)]\tLoss: 0.314216\n", 463 | "Train Epoch: 0 [23000/60000 (38%)]\tLoss: 0.407162\n", 464 | "Train Epoch: 0 [24000/60000 (40%)]\tLoss: 0.417334\n", 465 | "Train Epoch: 0 [25000/60000 (42%)]\tLoss: 0.464954\n", 466 | "Train Epoch: 0 [26000/60000 (43%)]\tLoss: 0.395768\n", 467 | "Train Epoch: 0 [27000/60000 (45%)]\tLoss: 0.471428\n", 468 | "Train Epoch: 0 [28000/60000 (47%)]\tLoss: 0.384233\n", 469 | "Train Epoch: 0 [29000/60000 (48%)]\tLoss: 0.237195\n", 470 | "Train Epoch: 0 [30000/60000 (50%)]\tLoss: 0.230448\n", 471 | "Train Epoch: 0 [31000/60000 (52%)]\tLoss: 0.482738\n", 472 | "Train Epoch: 0 [32000/60000 (53%)]\tLoss: 0.280180\n", 473 | "Train Epoch: 0 [33000/60000 (55%)]\tLoss: 0.340350\n", 474 | "Train Epoch: 0 [34000/60000 (57%)]\tLoss: 0.230954\n", 475 | "Train Epoch: 0 [35000/60000 (58%)]\tLoss: 0.359263\n", 476 | "Train Epoch: 0 [36000/60000 (60%)]\tLoss: 0.282059\n", 477 | "Train Epoch: 0 [37000/60000 (62%)]\tLoss: 0.229961\n", 478 | "Train Epoch: 0 [38000/60000 (63%)]\tLoss: 0.195395\n", 479 | "Train Epoch: 0 [39000/60000 (65%)]\tLoss: 0.273387\n", 480 | "Train Epoch: 0 [40000/60000 (67%)]\tLoss: 0.280653\n", 481 | "Train Epoch: 0 [41000/60000 (68%)]\tLoss: 0.202795\n", 482 | "Train Epoch: 0 [42000/60000 (70%)]\tLoss: 0.323157\n", 483 | "Train Epoch: 0 [43000/60000 (72%)]\tLoss: 0.339500\n", 484 | "Train Epoch: 0 [44000/60000 (73%)]\tLoss: 0.319159\n", 485 | "Train Epoch: 0 [45000/60000 (75%)]\tLoss: 0.285635\n", 486 | "Train Epoch: 0 [46000/60000 (77%)]\tLoss: 0.215550\n", 487 | "Train Epoch: 0 [47000/60000 (78%)]\tLoss: 0.241237\n", 488 | "Train Epoch: 0 [48000/60000 (80%)]\tLoss: 0.217412\n", 489 | "Train Epoch: 0 [49000/60000 (82%)]\tLoss: 0.194460\n", 490 | "Train Epoch: 0 [50000/60000 (83%)]\tLoss: 0.184959\n", 491 | "Train Epoch: 0 [51000/60000 (85%)]\tLoss: 0.240396\n", 492 | "Train Epoch: 0 [52000/60000 (87%)]\tLoss: 0.319755\n", 493 | "Train Epoch: 0 [53000/60000 (88%)]\tLoss: 0.239770\n", 494 | "Train Epoch: 0 [54000/60000 (90%)]\tLoss: 0.099248\n", 495 | "Train Epoch: 0 [55000/60000 (92%)]\tLoss: 0.292660\n", 496 | "Train Epoch: 0 [56000/60000 (93%)]\tLoss: 0.163331\n", 497 | "Train Epoch: 0 [57000/60000 (95%)]\tLoss: 0.180359\n", 498 | "Train Epoch: 0 [58000/60000 (97%)]\tLoss: 0.293773\n", 499 | "Train Epoch: 0 [59000/60000 (98%)]\tLoss: 0.280835\n" 500 | ] 501 | } 502 | ], 503 | "source": [ 504 | "trainnat(0)" 505 | ] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "metadata": {}, 510 | "source": [ 511 | "test on natral" 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": 9, 517 | "metadata": {}, 518 | "outputs": [ 519 | { 520 | "name": "stdout", 521 | "output_type": "stream", 522 | "text": [ 523 | "\n", 524 | "Test set: Average loss: 0.0013, Accuracy: 9603/10000 (96%)\n", 525 | "\n" 526 | ] 527 | } 528 | ], 529 | "source": [ 530 | "test()" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": { 536 | "collapsed": true 537 | }, 538 | "source": [ 539 | "test on LS-PGD attack" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "execution_count": 12, 545 | "metadata": {}, 546 | "outputs": [ 547 | { 548 | "name": "stdout", 549 | "output_type": "stream", 550 | "text": [ 551 | "\n", 552 | "Test set: Average loss: 0.0783, Accuracy: 26/10000 (0%)\n", 553 | "\n" 554 | ] 555 | } 556 | ], 557 | "source": [ 558 | "testadv()" 559 | ] 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": {}, 564 | "source": [ 565 | "advtrain on LS-PGD attack " 566 | ] 567 | }, 568 | { 569 | "cell_type": "code", 570 | "execution_count": 13, 571 | "metadata": {}, 572 | "outputs": [ 573 | { 574 | "name": "stdout", 575 | "output_type": "stream", 576 | "text": [ 577 | "Train Epoch: 0 [0/60000 (0%)]\tLoss: 4.778333\n", 578 | "Train Epoch: 0 [1000/60000 (2%)]\tLoss: 2.234309\n", 579 | "Train Epoch: 0 [2000/60000 (3%)]\tLoss: 1.926022\n", 580 | "Train Epoch: 0 [3000/60000 (5%)]\tLoss: 1.505311\n", 581 | "Train Epoch: 0 [4000/60000 (7%)]\tLoss: 1.499077\n", 582 | "Train Epoch: 0 [5000/60000 (8%)]\tLoss: 1.308034\n", 583 | "Train Epoch: 0 [6000/60000 (10%)]\tLoss: 1.426866\n", 584 | "Train Epoch: 0 [7000/60000 (12%)]\tLoss: 1.118608\n", 585 | "Train Epoch: 0 [8000/60000 (13%)]\tLoss: 1.097754\n", 586 | "Train Epoch: 0 [9000/60000 (15%)]\tLoss: 1.017607\n", 587 | "Train Epoch: 0 [10000/60000 (17%)]\tLoss: 1.128312\n", 588 | "Train Epoch: 0 [11000/60000 (18%)]\tLoss: 0.909971\n", 589 | "Train Epoch: 0 [12000/60000 (20%)]\tLoss: 0.858213\n", 590 | "Train Epoch: 0 [13000/60000 (22%)]\tLoss: 0.842452\n", 591 | "Train Epoch: 0 [14000/60000 (23%)]\tLoss: 0.828172\n", 592 | "Train Epoch: 0 [15000/60000 (25%)]\tLoss: 1.056247\n", 593 | "Train Epoch: 0 [16000/60000 (27%)]\tLoss: 0.659280\n", 594 | "Train Epoch: 0 [17000/60000 (28%)]\tLoss: 0.791528\n", 595 | "Train Epoch: 0 [18000/60000 (30%)]\tLoss: 0.825837\n", 596 | "Train Epoch: 0 [19000/60000 (32%)]\tLoss: 0.876002\n", 597 | "Train Epoch: 0 [20000/60000 (33%)]\tLoss: 0.781835\n", 598 | "Train Epoch: 0 [21000/60000 (35%)]\tLoss: 0.713966\n", 599 | "Train Epoch: 0 [22000/60000 (37%)]\tLoss: 0.578799\n", 600 | "Train Epoch: 0 [23000/60000 (38%)]\tLoss: 0.698011\n", 601 | "Train Epoch: 0 [24000/60000 (40%)]\tLoss: 0.876671\n", 602 | "Train Epoch: 0 [25000/60000 (42%)]\tLoss: 0.567656\n", 603 | "Train Epoch: 0 [26000/60000 (43%)]\tLoss: 0.512513\n", 604 | "Train Epoch: 0 [27000/60000 (45%)]\tLoss: 0.701109\n", 605 | "Train Epoch: 0 [28000/60000 (47%)]\tLoss: 0.562018\n", 606 | "Train Epoch: 0 [29000/60000 (48%)]\tLoss: 0.596192\n", 607 | "Train Epoch: 0 [30000/60000 (50%)]\tLoss: 0.703907\n", 608 | "Train Epoch: 0 [31000/60000 (52%)]\tLoss: 0.649177\n", 609 | "Train Epoch: 0 [32000/60000 (53%)]\tLoss: 0.605773\n", 610 | "Train Epoch: 0 [33000/60000 (55%)]\tLoss: 0.493994\n", 611 | "Train Epoch: 0 [34000/60000 (57%)]\tLoss: 0.691156\n", 612 | "Train Epoch: 0 [35000/60000 (58%)]\tLoss: 0.777433\n", 613 | "Train Epoch: 0 [36000/60000 (60%)]\tLoss: 0.816369\n", 614 | "Train Epoch: 0 [37000/60000 (62%)]\tLoss: 0.566725\n", 615 | "Train Epoch: 0 [38000/60000 (63%)]\tLoss: 0.738298\n", 616 | "Train Epoch: 0 [39000/60000 (65%)]\tLoss: 0.537736\n", 617 | "Train Epoch: 0 [40000/60000 (67%)]\tLoss: 0.648210\n", 618 | "Train Epoch: 0 [41000/60000 (68%)]\tLoss: 0.642458\n", 619 | "Train Epoch: 0 [42000/60000 (70%)]\tLoss: 0.632553\n", 620 | "Train Epoch: 0 [43000/60000 (72%)]\tLoss: 0.582097\n", 621 | "Train Epoch: 0 [44000/60000 (73%)]\tLoss: 0.750218\n", 622 | "Train Epoch: 0 [45000/60000 (75%)]\tLoss: 0.437618\n", 623 | "Train Epoch: 0 [46000/60000 (77%)]\tLoss: 0.482472\n", 624 | "Train Epoch: 0 [47000/60000 (78%)]\tLoss: 0.524253\n", 625 | "Train Epoch: 0 [48000/60000 (80%)]\tLoss: 0.463634\n", 626 | "Train Epoch: 0 [49000/60000 (82%)]\tLoss: 0.587060\n", 627 | "Train Epoch: 0 [50000/60000 (83%)]\tLoss: 0.584792\n", 628 | "Train Epoch: 0 [51000/60000 (85%)]\tLoss: 0.620650\n", 629 | "Train Epoch: 0 [52000/60000 (87%)]\tLoss: 0.370396\n", 630 | "Train Epoch: 0 [53000/60000 (88%)]\tLoss: 0.503538\n", 631 | "Train Epoch: 0 [54000/60000 (90%)]\tLoss: 0.430511\n", 632 | "Train Epoch: 0 [55000/60000 (92%)]\tLoss: 0.426360\n", 633 | "Train Epoch: 0 [56000/60000 (93%)]\tLoss: 0.434016\n", 634 | "Train Epoch: 0 [57000/60000 (95%)]\tLoss: 0.404179\n", 635 | "Train Epoch: 0 [58000/60000 (97%)]\tLoss: 0.497083\n", 636 | "Train Epoch: 0 [59000/60000 (98%)]\tLoss: 0.422729\n" 637 | ] 638 | } 639 | ], 640 | "source": [ 641 | "trainadv(0)" 642 | ] 643 | }, 644 | { 645 | "cell_type": "markdown", 646 | "metadata": {}, 647 | "source": [ 648 | "test after advtrain" 649 | ] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "execution_count": 14, 654 | "metadata": {}, 655 | "outputs": [ 656 | { 657 | "name": "stdout", 658 | "output_type": "stream", 659 | "text": [ 660 | "\n", 661 | "Test set: Average loss: 0.0069, Accuracy: 7547/10000 (75%)\n", 662 | "\n" 663 | ] 664 | } 665 | ], 666 | "source": [ 667 | "testadv()" 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": null, 673 | "metadata": { 674 | "collapsed": true 675 | }, 676 | "outputs": [], 677 | "source": [ 678 | "" 679 | ] 680 | } 681 | ], 682 | "metadata": { 683 | "kernelspec": { 684 | "display_name": "Python 2", 685 | "language": "python", 686 | "name": "python2" 687 | }, 688 | "language_info": { 689 | "codemirror_mode": { 690 | "name": "ipython", 691 | "version": 2.0 692 | }, 693 | "file_extension": ".py", 694 | "mimetype": "text/x-python", 695 | "name": "python", 696 | "nbconvert_exporter": "python", 697 | "pygments_lexer": "ipython2", 698 | "version": "2.7.14" 699 | } 700 | }, 701 | "nbformat": 4, 702 | "nbformat_minor": 0 703 | } -------------------------------------------------------------------------------- /encoder.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.preprocessing import OneHotEncoder 3 | 4 | 5 | class encoder(object): 6 | def __init__(self,level): 7 | self.k = level 8 | self.onehotencoder = OneHotEncoder(n_values=self.k, sparse=False) 9 | 10 | """ 11 | input:natural image arr:n*w*h*c 12 | return: quantisized image n*w*h*c 13 | """ 14 | 15 | def quantization(self,arr): 16 | quant = np.zeros(arr.shape) 17 | for i in range(1, self.k): 18 | quant[arr > 1.0 * i / self.k] += 1 19 | return quant 20 | 21 | """ 22 | input:quantisized img shape:n*w*h*c 23 | retun:one-hot coded image shape:n*w*h*c*k 24 | """ 25 | 26 | def onehot(self,arr): 27 | n, w, h = arr.shape 28 | arr = arr.reshape(n, -1) 29 | arr = self.onehotencoder.fit_transform(arr) 30 | arr = arr.reshape(n, w, h, self.k) 31 | arr = arr.transpose(0, 3, 1, 2) 32 | return arr 33 | 34 | """ 35 | input:one-hot coded img shape:n*w*h*c*k 36 | retun:trmp coded image shape:n*w*h*c*k 37 | """ 38 | 39 | def tempcode(self, arr): 40 | tempcode = np.zeros(arr.shape) 41 | for i in range(self.k): 42 | tempcode[:, i, :, :] = np.sum(arr[:, :i + 1, :, :], axis=1) 43 | return tempcode 44 | 45 | def tempencoding(self,arr): 46 | return self.tempcode(self.onehot(self.quantization(arr))) 47 | 48 | def onehotencoding(self,arr): 49 | return self.onehot(self.quantization(arr)) 50 | 51 | 52 | """ 53 | from a thermometerencoding image to a normally coded image, for some visualization usage 54 | """ 55 | 56 | def temp2img(self,tempimg): 57 | img = np.sum(tempimg, axis=1) 58 | img = np.ones(img.shape) * (self.k + 1) - img 59 | img = img * 1.0 / self.k 60 | return img 61 | -------------------------------------------------------------------------------- /models/__init__.py: -------------------------------------------------------------------------------- 1 | from .vgg import * 2 | from .dpn import * 3 | from .lenet import * 4 | from .senet import * 5 | from .resnet import * 6 | from .resnext import * 7 | from .densenet import * 8 | from .googlenet import * 9 | from .mobilenet import * 10 | from .shufflenet import * 11 | from .preact_resnet import * 12 | from .wide_resnet import * 13 | -------------------------------------------------------------------------------- /models/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/__init__.pyc -------------------------------------------------------------------------------- /models/densenet.py: -------------------------------------------------------------------------------- 1 | '''DenseNet in PyTorch.''' 2 | import math 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | 8 | from torch.autograd import Variable 9 | 10 | 11 | class Bottleneck(nn.Module): 12 | def __init__(self, in_planes, growth_rate): 13 | super(Bottleneck, self).__init__() 14 | self.bn1 = nn.BatchNorm2d(in_planes) 15 | self.conv1 = nn.Conv2d(in_planes, 4*growth_rate, kernel_size=1, bias=False) 16 | self.bn2 = nn.BatchNorm2d(4*growth_rate) 17 | self.conv2 = nn.Conv2d(4*growth_rate, growth_rate, kernel_size=3, padding=1, bias=False) 18 | 19 | def forward(self, x): 20 | out = self.conv1(F.relu(self.bn1(x))) 21 | out = self.conv2(F.relu(self.bn2(out))) 22 | out = torch.cat([out,x], 1) 23 | return out 24 | 25 | 26 | class Transition(nn.Module): 27 | def __init__(self, in_planes, out_planes): 28 | super(Transition, self).__init__() 29 | self.bn = nn.BatchNorm2d(in_planes) 30 | self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, bias=False) 31 | 32 | def forward(self, x): 33 | out = self.conv(F.relu(self.bn(x))) 34 | out = F.avg_pool2d(out, 2) 35 | return out 36 | 37 | 38 | class DenseNet(nn.Module): 39 | def __init__(self, block, nblocks, growth_rate=12, reduction=0.5, num_classes=10): 40 | super(DenseNet, self).__init__() 41 | self.growth_rate = growth_rate 42 | 43 | num_planes = 2*growth_rate 44 | self.conv1 = nn.Conv2d(3, num_planes, kernel_size=3, padding=1, bias=False) 45 | 46 | self.dense1 = self._make_dense_layers(block, num_planes, nblocks[0]) 47 | num_planes += nblocks[0]*growth_rate 48 | out_planes = int(math.floor(num_planes*reduction)) 49 | self.trans1 = Transition(num_planes, out_planes) 50 | num_planes = out_planes 51 | 52 | self.dense2 = self._make_dense_layers(block, num_planes, nblocks[1]) 53 | num_planes += nblocks[1]*growth_rate 54 | out_planes = int(math.floor(num_planes*reduction)) 55 | self.trans2 = Transition(num_planes, out_planes) 56 | num_planes = out_planes 57 | 58 | self.dense3 = self._make_dense_layers(block, num_planes, nblocks[2]) 59 | num_planes += nblocks[2]*growth_rate 60 | out_planes = int(math.floor(num_planes*reduction)) 61 | self.trans3 = Transition(num_planes, out_planes) 62 | num_planes = out_planes 63 | 64 | self.dense4 = self._make_dense_layers(block, num_planes, nblocks[3]) 65 | num_planes += nblocks[3]*growth_rate 66 | 67 | self.bn = nn.BatchNorm2d(num_planes) 68 | self.linear = nn.Linear(num_planes, num_classes) 69 | 70 | def _make_dense_layers(self, block, in_planes, nblock): 71 | layers = [] 72 | for i in range(nblock): 73 | layers.append(block(in_planes, self.growth_rate)) 74 | in_planes += self.growth_rate 75 | return nn.Sequential(*layers) 76 | 77 | def forward(self, x): 78 | out = self.conv1(x) 79 | out = self.trans1(self.dense1(out)) 80 | out = self.trans2(self.dense2(out)) 81 | out = self.trans3(self.dense3(out)) 82 | out = self.dense4(out) 83 | out = F.avg_pool2d(F.relu(self.bn(out)), 4) 84 | out = out.view(out.size(0), -1) 85 | out = self.linear(out) 86 | return out 87 | 88 | def DenseNet121(): 89 | return DenseNet(Bottleneck, [6,12,24,16], growth_rate=32) 90 | 91 | def DenseNet169(): 92 | return DenseNet(Bottleneck, [6,12,32,32], growth_rate=32) 93 | 94 | def DenseNet201(): 95 | return DenseNet(Bottleneck, [6,12,48,32], growth_rate=32) 96 | 97 | def DenseNet161(): 98 | return DenseNet(Bottleneck, [6,12,36,24], growth_rate=48) 99 | 100 | def densenet_cifar(): 101 | return DenseNet(Bottleneck, [6,12,24,16], growth_rate=12) 102 | 103 | def test_densenet(): 104 | net = densenet_cifar() 105 | x = torch.randn(1,3,32,32) 106 | y = net(Variable(x)) 107 | print(y) 108 | 109 | # test_densenet() 110 | -------------------------------------------------------------------------------- /models/densenet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/densenet.pyc -------------------------------------------------------------------------------- /models/dpn.py: -------------------------------------------------------------------------------- 1 | '''Dual Path Networks in PyTorch.''' 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | 6 | from torch.autograd import Variable 7 | 8 | 9 | class Bottleneck(nn.Module): 10 | def __init__(self, last_planes, in_planes, out_planes, dense_depth, stride, first_layer): 11 | super(Bottleneck, self).__init__() 12 | self.out_planes = out_planes 13 | self.dense_depth = dense_depth 14 | 15 | self.conv1 = nn.Conv2d(last_planes, in_planes, kernel_size=1, bias=False) 16 | self.bn1 = nn.BatchNorm2d(in_planes) 17 | self.conv2 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=32, bias=False) 18 | self.bn2 = nn.BatchNorm2d(in_planes) 19 | self.conv3 = nn.Conv2d(in_planes, out_planes+dense_depth, kernel_size=1, bias=False) 20 | self.bn3 = nn.BatchNorm2d(out_planes+dense_depth) 21 | 22 | self.shortcut = nn.Sequential() 23 | if first_layer: 24 | self.shortcut = nn.Sequential( 25 | nn.Conv2d(last_planes, out_planes+dense_depth, kernel_size=1, stride=stride, bias=False), 26 | nn.BatchNorm2d(out_planes+dense_depth) 27 | ) 28 | 29 | def forward(self, x): 30 | out = F.relu(self.bn1(self.conv1(x))) 31 | out = F.relu(self.bn2(self.conv2(out))) 32 | out = self.bn3(self.conv3(out)) 33 | x = self.shortcut(x) 34 | d = self.out_planes 35 | out = torch.cat([x[:,:d,:,:]+out[:,:d,:,:], x[:,d:,:,:], out[:,d:,:,:]], 1) 36 | out = F.relu(out) 37 | return out 38 | 39 | 40 | class DPN(nn.Module): 41 | def __init__(self, cfg): 42 | super(DPN, self).__init__() 43 | in_planes, out_planes = cfg['in_planes'], cfg['out_planes'] 44 | num_blocks, dense_depth = cfg['num_blocks'], cfg['dense_depth'] 45 | 46 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) 47 | self.bn1 = nn.BatchNorm2d(64) 48 | self.last_planes = 64 49 | self.layer1 = self._make_layer(in_planes[0], out_planes[0], num_blocks[0], dense_depth[0], stride=1) 50 | self.layer2 = self._make_layer(in_planes[1], out_planes[1], num_blocks[1], dense_depth[1], stride=2) 51 | self.layer3 = self._make_layer(in_planes[2], out_planes[2], num_blocks[2], dense_depth[2], stride=2) 52 | self.layer4 = self._make_layer(in_planes[3], out_planes[3], num_blocks[3], dense_depth[3], stride=2) 53 | self.linear = nn.Linear(out_planes[3]+(num_blocks[3]+1)*dense_depth[3], 10) 54 | 55 | def _make_layer(self, in_planes, out_planes, num_blocks, dense_depth, stride): 56 | strides = [stride] + [1]*(num_blocks-1) 57 | layers = [] 58 | for i,stride in enumerate(strides): 59 | layers.append(Bottleneck(self.last_planes, in_planes, out_planes, dense_depth, stride, i==0)) 60 | self.last_planes = out_planes + (i+2) * dense_depth 61 | return nn.Sequential(*layers) 62 | 63 | def forward(self, x): 64 | out = F.relu(self.bn1(self.conv1(x))) 65 | out = self.layer1(out) 66 | out = self.layer2(out) 67 | out = self.layer3(out) 68 | out = self.layer4(out) 69 | out = F.avg_pool2d(out, 4) 70 | out = out.view(out.size(0), -1) 71 | out = self.linear(out) 72 | return out 73 | 74 | 75 | def DPN26(): 76 | cfg = { 77 | 'in_planes': (96,192,384,768), 78 | 'out_planes': (256,512,1024,2048), 79 | 'num_blocks': (2,2,2,2), 80 | 'dense_depth': (16,32,24,128) 81 | } 82 | return DPN(cfg) 83 | 84 | def DPN92(): 85 | cfg = { 86 | 'in_planes': (96,192,384,768), 87 | 'out_planes': (256,512,1024,2048), 88 | 'num_blocks': (3,4,20,3), 89 | 'dense_depth': (16,32,24,128) 90 | } 91 | return DPN(cfg) 92 | 93 | 94 | def test(): 95 | net = DPN92() 96 | x = Variable(torch.randn(1,3,32,32)) 97 | y = net(x) 98 | print(y) 99 | 100 | # test() 101 | -------------------------------------------------------------------------------- /models/dpn.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/dpn.pyc -------------------------------------------------------------------------------- /models/googlenet.py: -------------------------------------------------------------------------------- 1 | '''GoogLeNet with PyTorch.''' 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | 6 | from torch.autograd import Variable 7 | 8 | 9 | class Inception(nn.Module): 10 | def __init__(self, in_planes, n1x1, n3x3red, n3x3, n5x5red, n5x5, pool_planes): 11 | super(Inception, self).__init__() 12 | # 1x1 conv branch 13 | self.b1 = nn.Sequential( 14 | nn.Conv2d(in_planes, n1x1, kernel_size=1), 15 | nn.BatchNorm2d(n1x1), 16 | nn.ReLU(True), 17 | ) 18 | 19 | # 1x1 conv -> 3x3 conv branch 20 | self.b2 = nn.Sequential( 21 | nn.Conv2d(in_planes, n3x3red, kernel_size=1), 22 | nn.BatchNorm2d(n3x3red), 23 | nn.ReLU(True), 24 | nn.Conv2d(n3x3red, n3x3, kernel_size=3, padding=1), 25 | nn.BatchNorm2d(n3x3), 26 | nn.ReLU(True), 27 | ) 28 | 29 | # 1x1 conv -> 5x5 conv branch 30 | self.b3 = nn.Sequential( 31 | nn.Conv2d(in_planes, n5x5red, kernel_size=1), 32 | nn.BatchNorm2d(n5x5red), 33 | nn.ReLU(True), 34 | nn.Conv2d(n5x5red, n5x5, kernel_size=3, padding=1), 35 | nn.BatchNorm2d(n5x5), 36 | nn.ReLU(True), 37 | nn.Conv2d(n5x5, n5x5, kernel_size=3, padding=1), 38 | nn.BatchNorm2d(n5x5), 39 | nn.ReLU(True), 40 | ) 41 | 42 | # 3x3 pool -> 1x1 conv branch 43 | self.b4 = nn.Sequential( 44 | nn.MaxPool2d(3, stride=1, padding=1), 45 | nn.Conv2d(in_planes, pool_planes, kernel_size=1), 46 | nn.BatchNorm2d(pool_planes), 47 | nn.ReLU(True), 48 | ) 49 | 50 | def forward(self, x): 51 | y1 = self.b1(x) 52 | y2 = self.b2(x) 53 | y3 = self.b3(x) 54 | y4 = self.b4(x) 55 | return torch.cat([y1,y2,y3,y4], 1) 56 | 57 | 58 | class GoogLeNet(nn.Module): 59 | def __init__(self): 60 | super(GoogLeNet, self).__init__() 61 | self.pre_layers = nn.Sequential( 62 | nn.Conv2d(3, 192, kernel_size=3, padding=1), 63 | nn.BatchNorm2d(192), 64 | nn.ReLU(True), 65 | ) 66 | 67 | self.a3 = Inception(192, 64, 96, 128, 16, 32, 32) 68 | self.b3 = Inception(256, 128, 128, 192, 32, 96, 64) 69 | 70 | self.maxpool = nn.MaxPool2d(3, stride=2, padding=1) 71 | 72 | self.a4 = Inception(480, 192, 96, 208, 16, 48, 64) 73 | self.b4 = Inception(512, 160, 112, 224, 24, 64, 64) 74 | self.c4 = Inception(512, 128, 128, 256, 24, 64, 64) 75 | self.d4 = Inception(512, 112, 144, 288, 32, 64, 64) 76 | self.e4 = Inception(528, 256, 160, 320, 32, 128, 128) 77 | 78 | self.a5 = Inception(832, 256, 160, 320, 32, 128, 128) 79 | self.b5 = Inception(832, 384, 192, 384, 48, 128, 128) 80 | 81 | self.avgpool = nn.AvgPool2d(8, stride=1) 82 | self.linear = nn.Linear(1024, 10) 83 | 84 | def forward(self, x): 85 | out = self.pre_layers(x) 86 | out = self.a3(out) 87 | out = self.b3(out) 88 | out = self.maxpool(out) 89 | out = self.a4(out) 90 | out = self.b4(out) 91 | out = self.c4(out) 92 | out = self.d4(out) 93 | out = self.e4(out) 94 | out = self.maxpool(out) 95 | out = self.a5(out) 96 | out = self.b5(out) 97 | out = self.avgpool(out) 98 | out = out.view(out.size(0), -1) 99 | out = self.linear(out) 100 | return out 101 | 102 | # net = GoogLeNet() 103 | # x = torch.randn(1,3,32,32) 104 | # y = net(Variable(x)) 105 | # print(y.size()) 106 | -------------------------------------------------------------------------------- /models/googlenet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/googlenet.pyc -------------------------------------------------------------------------------- /models/lenet.py: -------------------------------------------------------------------------------- 1 | '''LeNet in PyTorch.''' 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | class LeNet(nn.Module): 6 | def __init__(self): 7 | super(LeNet, self).__init__() 8 | self.conv1 = nn.Conv2d(3, 6, 5) 9 | self.conv2 = nn.Conv2d(6, 16, 5) 10 | self.fc1 = nn.Linear(16*5*5, 120) 11 | self.fc2 = nn.Linear(120, 84) 12 | self.fc3 = nn.Linear(84, 10) 13 | 14 | def forward(self, x): 15 | out = F.relu(self.conv1(x)) 16 | out = F.max_pool2d(out, 2) 17 | out = F.relu(self.conv2(out)) 18 | out = F.max_pool2d(out, 2) 19 | out = out.view(out.size(0), -1) 20 | out = F.relu(self.fc1(out)) 21 | out = F.relu(self.fc2(out)) 22 | out = self.fc3(out) 23 | return out 24 | -------------------------------------------------------------------------------- /models/lenet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/lenet.pyc -------------------------------------------------------------------------------- /models/mobilenet.py: -------------------------------------------------------------------------------- 1 | '''MobileNet in PyTorch. 2 | 3 | See the paper "MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications" 4 | for more details. 5 | ''' 6 | import torch 7 | import torch.nn as nn 8 | import torch.nn.functional as F 9 | 10 | from torch.autograd import Variable 11 | 12 | 13 | class Block(nn.Module): 14 | '''Depthwise conv + Pointwise conv''' 15 | def __init__(self, in_planes, out_planes, stride=1): 16 | super(Block, self).__init__() 17 | self.conv1 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=in_planes, bias=False) 18 | self.bn1 = nn.BatchNorm2d(in_planes) 19 | self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=1, padding=0, bias=False) 20 | self.bn2 = nn.BatchNorm2d(out_planes) 21 | 22 | def forward(self, x): 23 | out = F.relu(self.bn1(self.conv1(x))) 24 | out = F.relu(self.bn2(self.conv2(out))) 25 | return out 26 | 27 | 28 | class MobileNet(nn.Module): 29 | # (128,2) means conv planes=128, conv stride=2, by default conv stride=1 30 | cfg = [64, (128,2), 128, (256,2), 256, (512,2), 512, 512, 512, 512, 512, (1024,2), 1024] 31 | 32 | def __init__(self, num_classes=10): 33 | super(MobileNet, self).__init__() 34 | self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False) 35 | self.bn1 = nn.BatchNorm2d(32) 36 | self.layers = self._make_layers(in_planes=32) 37 | self.linear = nn.Linear(1024, num_classes) 38 | 39 | def _make_layers(self, in_planes): 40 | layers = [] 41 | for x in self.cfg: 42 | out_planes = x if isinstance(x, int) else x[0] 43 | stride = 1 if isinstance(x, int) else x[1] 44 | layers.append(Block(in_planes, out_planes, stride)) 45 | in_planes = out_planes 46 | return nn.Sequential(*layers) 47 | 48 | def forward(self, x): 49 | out = F.relu(self.bn1(self.conv1(x))) 50 | out = self.layers(out) 51 | out = F.avg_pool2d(out, 2) 52 | out = out.view(out.size(0), -1) 53 | out = self.linear(out) 54 | return out 55 | 56 | 57 | def test(): 58 | net = MobileNet() 59 | x = torch.randn(1,3,32,32) 60 | y = net(Variable(x)) 61 | print(y.size()) 62 | 63 | # test() 64 | -------------------------------------------------------------------------------- /models/mobilenet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/mobilenet.pyc -------------------------------------------------------------------------------- /models/preact_resnet.py: -------------------------------------------------------------------------------- 1 | '''Pre-activation ResNet in PyTorch. 2 | 3 | Reference: 4 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun 5 | Identity Mappings in Deep Residual Networks. arXiv:1603.05027 6 | ''' 7 | import torch 8 | import torch.nn as nn 9 | import torch.nn.functional as F 10 | 11 | from torch.autograd import Variable 12 | 13 | 14 | class PreActBlock(nn.Module): 15 | '''Pre-activation version of the BasicBlock.''' 16 | expansion = 1 17 | 18 | def __init__(self, in_planes, planes, stride=1): 19 | super(PreActBlock, self).__init__() 20 | self.bn1 = nn.BatchNorm2d(in_planes) 21 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 22 | self.bn2 = nn.BatchNorm2d(planes) 23 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) 24 | 25 | if stride != 1 or in_planes != self.expansion*planes: 26 | self.shortcut = nn.Sequential( 27 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False) 28 | ) 29 | 30 | def forward(self, x): 31 | out = F.relu(self.bn1(x)) 32 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x 33 | out = self.conv1(out) 34 | out = self.conv2(F.relu(self.bn2(out))) 35 | out += shortcut 36 | return out 37 | 38 | 39 | class PreActBottleneck(nn.Module): 40 | '''Pre-activation version of the original Bottleneck module.''' 41 | expansion = 4 42 | 43 | def __init__(self, in_planes, planes, stride=1): 44 | super(PreActBottleneck, self).__init__() 45 | self.bn1 = nn.BatchNorm2d(in_planes) 46 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False) 47 | self.bn2 = nn.BatchNorm2d(planes) 48 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 49 | self.bn3 = nn.BatchNorm2d(planes) 50 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False) 51 | 52 | if stride != 1 or in_planes != self.expansion*planes: 53 | self.shortcut = nn.Sequential( 54 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False) 55 | ) 56 | 57 | def forward(self, x): 58 | out = F.relu(self.bn1(x)) 59 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x 60 | out = self.conv1(out) 61 | out = self.conv2(F.relu(self.bn2(out))) 62 | out = self.conv3(F.relu(self.bn3(out))) 63 | out += shortcut 64 | return out 65 | 66 | 67 | class PreActResNet(nn.Module): 68 | def __init__(self, block, num_blocks, num_classes=10): 69 | super(PreActResNet, self).__init__() 70 | self.in_planes = 64 71 | 72 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) 73 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) 74 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) 75 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) 76 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) 77 | self.linear = nn.Linear(512*block.expansion, num_classes) 78 | 79 | def _make_layer(self, block, planes, num_blocks, stride): 80 | strides = [stride] + [1]*(num_blocks-1) 81 | layers = [] 82 | for stride in strides: 83 | layers.append(block(self.in_planes, planes, stride)) 84 | self.in_planes = planes * block.expansion 85 | return nn.Sequential(*layers) 86 | 87 | def forward(self, x): 88 | out = self.conv1(x) 89 | out = self.layer1(out) 90 | out = self.layer2(out) 91 | out = self.layer3(out) 92 | out = self.layer4(out) 93 | out = F.avg_pool2d(out, 4) 94 | out = out.view(out.size(0), -1) 95 | out = self.linear(out) 96 | return out 97 | 98 | 99 | def PreActResNet18(): 100 | return PreActResNet(PreActBlock, [2,2,2,2]) 101 | 102 | def PreActResNet34(): 103 | return PreActResNet(PreActBlock, [3,4,6,3]) 104 | 105 | def PreActResNet50(): 106 | return PreActResNet(PreActBottleneck, [3,4,6,3]) 107 | 108 | def PreActResNet101(): 109 | return PreActResNet(PreActBottleneck, [3,4,23,3]) 110 | 111 | def PreActResNet152(): 112 | return PreActResNet(PreActBottleneck, [3,8,36,3]) 113 | 114 | 115 | def test(): 116 | net = PreActResNet18() 117 | y = net(Variable(torch.randn(1,3,32,32))) 118 | print(y.size()) 119 | 120 | # test() 121 | -------------------------------------------------------------------------------- /models/preact_resnet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/preact_resnet.pyc -------------------------------------------------------------------------------- /models/resnet.py: -------------------------------------------------------------------------------- 1 | '''ResNet in PyTorch. 2 | 3 | For Pre-activation ResNet, see 'preact_resnet.py'. 4 | 5 | Reference: 6 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun 7 | Deep Residual Learning for Image Recognition. arXiv:1512.03385 8 | ''' 9 | import torch 10 | import torch.nn as nn 11 | import torch.nn.functional as F 12 | 13 | from torch.autograd import Variable 14 | 15 | 16 | class BasicBlock(nn.Module): 17 | expansion = 1 18 | 19 | def __init__(self, in_planes, planes, stride=1): 20 | super(BasicBlock, self).__init__() 21 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 22 | self.bn1 = nn.BatchNorm2d(planes) 23 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) 24 | self.bn2 = nn.BatchNorm2d(planes) 25 | 26 | self.shortcut = nn.Sequential() 27 | if stride != 1 or in_planes != self.expansion*planes: 28 | self.shortcut = nn.Sequential( 29 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False), 30 | nn.BatchNorm2d(self.expansion*planes) 31 | ) 32 | 33 | def forward(self, x): 34 | out = F.relu(self.bn1(self.conv1(x))) 35 | out = self.bn2(self.conv2(out)) 36 | out += self.shortcut(x) 37 | out = F.relu(out) 38 | return out 39 | 40 | 41 | class Bottleneck(nn.Module): 42 | expansion = 4 43 | 44 | def __init__(self, in_planes, planes, stride=1): 45 | super(Bottleneck, self).__init__() 46 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False) 47 | self.bn1 = nn.BatchNorm2d(planes) 48 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 49 | self.bn2 = nn.BatchNorm2d(planes) 50 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False) 51 | self.bn3 = nn.BatchNorm2d(self.expansion*planes) 52 | 53 | self.shortcut = nn.Sequential() 54 | if stride != 1 or in_planes != self.expansion*planes: 55 | self.shortcut = nn.Sequential( 56 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False), 57 | nn.BatchNorm2d(self.expansion*planes) 58 | ) 59 | 60 | def forward(self, x): 61 | out = F.relu(self.bn1(self.conv1(x))) 62 | out = F.relu(self.bn2(self.conv2(out))) 63 | out = self.bn3(self.conv3(out)) 64 | out += self.shortcut(x) 65 | out = F.relu(out) 66 | return out 67 | 68 | 69 | class ResNet(nn.Module): 70 | def __init__(self, block, num_blocks, level, num_classes=10): 71 | super(ResNet, self).__init__() 72 | self.in_planes = 64 73 | 74 | self.conv1 = nn.Conv2d(3*level, 64, kernel_size=3, stride=1, padding=1, bias=False) 75 | self.bn1 = nn.BatchNorm2d(64) 76 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) 77 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) 78 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) 79 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) 80 | self.linear = nn.Linear(512*block.expansion, num_classes) 81 | 82 | def _make_layer(self, block, planes, num_blocks, stride): 83 | strides = [stride] + [1]*(num_blocks-1) 84 | layers = [] 85 | for stride in strides: 86 | layers.append(block(self.in_planes, planes, stride)) 87 | self.in_planes = planes * block.expansion 88 | return nn.Sequential(*layers) 89 | 90 | def forward(self, channel0,channel1,channel2): 91 | x = torch.cat((channel0,channel1,channel2),dim=1) 92 | out = F.relu(self.bn1(self.conv1(x))) 93 | out = self.layer1(out) 94 | out = self.layer2(out) 95 | out = self.layer3(out) 96 | out = self.layer4(out) 97 | out = F.avg_pool2d(out, 4) 98 | out = out.view(out.size(0), -1) 99 | out = self.linear(out) 100 | return out 101 | 102 | 103 | def ResNet18(level): 104 | return ResNet(BasicBlock, [2,2,2,2],level) 105 | 106 | def ResNet34(level): 107 | return ResNet(BasicBlock, [3,4,6,3],level) 108 | 109 | def ResNet50(level): 110 | return ResNet(Bottleneck, [3,4,6,3],level) 111 | 112 | def ResNet101(level): 113 | return ResNet(Bottleneck, [3,4,23,3],level) 114 | 115 | def ResNet152(level): 116 | return ResNet(Bottleneck, [3,8,36,3],level) 117 | 118 | 119 | def test(): 120 | net = ResNet18(level=15) 121 | y = net(Variable(torch.randn(1,15,32,32)),Variable(torch.randn(1,15,32,32)),Variable(torch.randn(1,15,32,32))) 122 | print(y.size()) 123 | 124 | # if __name__ == '__main__': 125 | # test() 126 | -------------------------------------------------------------------------------- /models/resnet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/resnet.pyc -------------------------------------------------------------------------------- /models/resnext.py: -------------------------------------------------------------------------------- 1 | '''ResNeXt in PyTorch. 2 | 3 | See the paper "Aggregated Residual Transformations for Deep Neural Networks" for more details. 4 | ''' 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | 9 | from torch.autograd import Variable 10 | 11 | 12 | class Block(nn.Module): 13 | '''Grouped convolution block.''' 14 | expansion = 2 15 | 16 | def __init__(self, in_planes, cardinality=32, bottleneck_width=4, stride=1): 17 | super(Block, self).__init__() 18 | group_width = cardinality * bottleneck_width 19 | self.conv1 = nn.Conv2d(in_planes, group_width, kernel_size=1, bias=False) 20 | self.bn1 = nn.BatchNorm2d(group_width) 21 | self.conv2 = nn.Conv2d(group_width, group_width, kernel_size=3, stride=stride, padding=1, groups=cardinality, bias=False) 22 | self.bn2 = nn.BatchNorm2d(group_width) 23 | self.conv3 = nn.Conv2d(group_width, self.expansion*group_width, kernel_size=1, bias=False) 24 | self.bn3 = nn.BatchNorm2d(self.expansion*group_width) 25 | 26 | self.shortcut = nn.Sequential() 27 | if stride != 1 or in_planes != self.expansion*group_width: 28 | self.shortcut = nn.Sequential( 29 | nn.Conv2d(in_planes, self.expansion*group_width, kernel_size=1, stride=stride, bias=False), 30 | nn.BatchNorm2d(self.expansion*group_width) 31 | ) 32 | 33 | def forward(self, x): 34 | out = F.relu(self.bn1(self.conv1(x))) 35 | out = F.relu(self.bn2(self.conv2(out))) 36 | out = self.bn3(self.conv3(out)) 37 | out += self.shortcut(x) 38 | out = F.relu(out) 39 | return out 40 | 41 | 42 | class ResNeXt(nn.Module): 43 | def __init__(self, num_blocks, cardinality, bottleneck_width, num_classes=10): 44 | super(ResNeXt, self).__init__() 45 | self.cardinality = cardinality 46 | self.bottleneck_width = bottleneck_width 47 | self.in_planes = 64 48 | 49 | self.conv1 = nn.Conv2d(3, 64, kernel_size=1, bias=False) 50 | self.bn1 = nn.BatchNorm2d(64) 51 | self.layer1 = self._make_layer(num_blocks[0], 1) 52 | self.layer2 = self._make_layer(num_blocks[1], 2) 53 | self.layer3 = self._make_layer(num_blocks[2], 2) 54 | # self.layer4 = self._make_layer(num_blocks[3], 2) 55 | self.linear = nn.Linear(cardinality*bottleneck_width*8, num_classes) 56 | 57 | def _make_layer(self, num_blocks, stride): 58 | strides = [stride] + [1]*(num_blocks-1) 59 | layers = [] 60 | for stride in strides: 61 | layers.append(Block(self.in_planes, self.cardinality, self.bottleneck_width, stride)) 62 | self.in_planes = Block.expansion * self.cardinality * self.bottleneck_width 63 | # Increase bottleneck_width by 2 after each stage. 64 | self.bottleneck_width *= 2 65 | return nn.Sequential(*layers) 66 | 67 | def forward(self, x): 68 | out = F.relu(self.bn1(self.conv1(x))) 69 | out = self.layer1(out) 70 | out = self.layer2(out) 71 | out = self.layer3(out) 72 | # out = self.layer4(out) 73 | out = F.avg_pool2d(out, 8) 74 | out = out.view(out.size(0), -1) 75 | out = self.linear(out) 76 | return out 77 | 78 | 79 | def ResNeXt29_2x64d(): 80 | return ResNeXt(num_blocks=[3,3,3], cardinality=2, bottleneck_width=64) 81 | 82 | def ResNeXt29_4x64d(): 83 | return ResNeXt(num_blocks=[3,3,3], cardinality=4, bottleneck_width=64) 84 | 85 | def ResNeXt29_8x64d(): 86 | return ResNeXt(num_blocks=[3,3,3], cardinality=8, bottleneck_width=64) 87 | 88 | def ResNeXt29_32x4d(): 89 | return ResNeXt(num_blocks=[3,3,3], cardinality=32, bottleneck_width=4) 90 | 91 | def test_resnext(): 92 | net = ResNeXt29_2x64d() 93 | x = torch.randn(1,3,32,32) 94 | y = net(Variable(x)) 95 | print(y.size()) 96 | 97 | # test_resnext() 98 | -------------------------------------------------------------------------------- /models/resnext.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/resnext.pyc -------------------------------------------------------------------------------- /models/senet.py: -------------------------------------------------------------------------------- 1 | '''SENet in PyTorch. 2 | 3 | SENet is the winner of ImageNet-2017. The paper is not released yet. 4 | ''' 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | 9 | from torch.autograd import Variable 10 | 11 | 12 | class BasicBlock(nn.Module): 13 | def __init__(self, in_planes, planes, stride=1): 14 | super(BasicBlock, self).__init__() 15 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 16 | self.bn1 = nn.BatchNorm2d(planes) 17 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) 18 | self.bn2 = nn.BatchNorm2d(planes) 19 | 20 | self.shortcut = nn.Sequential() 21 | if stride != 1 or in_planes != planes: 22 | self.shortcut = nn.Sequential( 23 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=False), 24 | nn.BatchNorm2d(planes) 25 | ) 26 | 27 | # SE layers 28 | self.fc1 = nn.Conv2d(planes, planes//16, kernel_size=1) # Use nn.Conv2d instead of nn.Linear 29 | self.fc2 = nn.Conv2d(planes//16, planes, kernel_size=1) 30 | 31 | def forward(self, x): 32 | out = F.relu(self.bn1(self.conv1(x))) 33 | out = self.bn2(self.conv2(out)) 34 | 35 | # Squeeze 36 | w = F.avg_pool2d(out, out.size(2)) 37 | w = F.relu(self.fc1(w)) 38 | w = F.sigmoid(self.fc2(w)) 39 | # Excitation 40 | out = out * w # New broadcasting feature from v0.2! 41 | 42 | out += self.shortcut(x) 43 | out = F.relu(out) 44 | return out 45 | 46 | 47 | class PreActBlock(nn.Module): 48 | def __init__(self, in_planes, planes, stride=1): 49 | super(PreActBlock, self).__init__() 50 | self.bn1 = nn.BatchNorm2d(in_planes) 51 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) 52 | self.bn2 = nn.BatchNorm2d(planes) 53 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) 54 | 55 | if stride != 1 or in_planes != planes: 56 | self.shortcut = nn.Sequential( 57 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=False) 58 | ) 59 | 60 | # SE layers 61 | self.fc1 = nn.Conv2d(planes, planes//16, kernel_size=1) 62 | self.fc2 = nn.Conv2d(planes//16, planes, kernel_size=1) 63 | 64 | def forward(self, x): 65 | out = F.relu(self.bn1(x)) 66 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x 67 | out = self.conv1(out) 68 | out = self.conv2(F.relu(self.bn2(out))) 69 | 70 | # Squeeze 71 | w = F.avg_pool2d(out, out.size(2)) 72 | w = F.relu(self.fc1(w)) 73 | w = F.sigmoid(self.fc2(w)) 74 | # Excitation 75 | out = out * w 76 | 77 | out += shortcut 78 | return out 79 | 80 | 81 | class SENet(nn.Module): 82 | def __init__(self, block, num_blocks, num_classes=10): 83 | super(SENet, self).__init__() 84 | self.in_planes = 64 85 | 86 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) 87 | self.bn1 = nn.BatchNorm2d(64) 88 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) 89 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) 90 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) 91 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) 92 | self.linear = nn.Linear(512, num_classes) 93 | 94 | def _make_layer(self, block, planes, num_blocks, stride): 95 | strides = [stride] + [1]*(num_blocks-1) 96 | layers = [] 97 | for stride in strides: 98 | layers.append(block(self.in_planes, planes, stride)) 99 | self.in_planes = planes 100 | return nn.Sequential(*layers) 101 | 102 | def forward(self, x): 103 | out = F.relu(self.bn1(self.conv1(x))) 104 | out = self.layer1(out) 105 | out = self.layer2(out) 106 | out = self.layer3(out) 107 | out = self.layer4(out) 108 | out = F.avg_pool2d(out, 4) 109 | out = out.view(out.size(0), -1) 110 | out = self.linear(out) 111 | return out 112 | 113 | 114 | def SENet18(): 115 | return SENet(PreActBlock, [2,2,2,2]) 116 | 117 | 118 | def test(): 119 | net = SENet18() 120 | y = net(Variable(torch.randn(1,3,32,32))) 121 | print(y.size()) 122 | 123 | # test() 124 | -------------------------------------------------------------------------------- /models/senet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/senet.pyc -------------------------------------------------------------------------------- /models/shufflenet.py: -------------------------------------------------------------------------------- 1 | '''ShuffleNet in PyTorch. 2 | 3 | See the paper "ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices" for more details. 4 | ''' 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | 9 | from torch.autograd import Variable 10 | 11 | 12 | class ShuffleBlock(nn.Module): 13 | def __init__(self, groups): 14 | super(ShuffleBlock, self).__init__() 15 | self.groups = groups 16 | 17 | def forward(self, x): 18 | '''Channel shuffle: [N,C,H,W] -> [N,g,C/g,H,W] -> [N,C/g,g,H,w] -> [N,C,H,W]''' 19 | N,C,H,W = x.size() 20 | g = self.groups 21 | return x.view(N,g,C/g,H,W).permute(0,2,1,3,4).contiguous().view(N,C,H,W) 22 | 23 | 24 | class Bottleneck(nn.Module): 25 | def __init__(self, in_planes, out_planes, stride, groups): 26 | super(Bottleneck, self).__init__() 27 | self.stride = stride 28 | 29 | mid_planes = out_planes/4 30 | g = 1 if in_planes==24 else groups 31 | self.conv1 = nn.Conv2d(in_planes, mid_planes, kernel_size=1, groups=g, bias=False) 32 | self.bn1 = nn.BatchNorm2d(mid_planes) 33 | self.shuffle1 = ShuffleBlock(groups=g) 34 | self.conv2 = nn.Conv2d(mid_planes, mid_planes, kernel_size=3, stride=stride, padding=1, groups=mid_planes, bias=False) 35 | self.bn2 = nn.BatchNorm2d(mid_planes) 36 | self.conv3 = nn.Conv2d(mid_planes, out_planes, kernel_size=1, groups=groups, bias=False) 37 | self.bn3 = nn.BatchNorm2d(out_planes) 38 | 39 | self.shortcut = nn.Sequential() 40 | if stride == 2: 41 | self.shortcut = nn.Sequential(nn.AvgPool2d(3, stride=2, padding=1)) 42 | 43 | def forward(self, x): 44 | out = F.relu(self.bn1(self.conv1(x))) 45 | out = self.shuffle1(out) 46 | out = F.relu(self.bn2(self.conv2(out))) 47 | out = self.bn3(self.conv3(out)) 48 | res = self.shortcut(x) 49 | out = F.relu(torch.cat([out,res], 1)) if self.stride==2 else F.relu(out+res) 50 | return out 51 | 52 | 53 | class ShuffleNet(nn.Module): 54 | def __init__(self, cfg): 55 | super(ShuffleNet, self).__init__() 56 | out_planes = cfg['out_planes'] 57 | num_blocks = cfg['num_blocks'] 58 | groups = cfg['groups'] 59 | 60 | self.conv1 = nn.Conv2d(3, 24, kernel_size=1, bias=False) 61 | self.bn1 = nn.BatchNorm2d(24) 62 | self.in_planes = 24 63 | self.layer1 = self._make_layer(out_planes[0], num_blocks[0], groups) 64 | self.layer2 = self._make_layer(out_planes[1], num_blocks[1], groups) 65 | self.layer3 = self._make_layer(out_planes[2], num_blocks[2], groups) 66 | self.linear = nn.Linear(out_planes[2], 10) 67 | 68 | def _make_layer(self, out_planes, num_blocks, groups): 69 | layers = [] 70 | for i in range(num_blocks): 71 | stride = 2 if i == 0 else 1 72 | cat_planes = self.in_planes if i == 0 else 0 73 | layers.append(Bottleneck(self.in_planes, out_planes-cat_planes, stride=stride, groups=groups)) 74 | self.in_planes = out_planes 75 | return nn.Sequential(*layers) 76 | 77 | def forward(self, x): 78 | out = F.relu(self.bn1(self.conv1(x))) 79 | out = self.layer1(out) 80 | out = self.layer2(out) 81 | out = self.layer3(out) 82 | out = F.avg_pool2d(out, 4) 83 | out = out.view(out.size(0), -1) 84 | out = self.linear(out) 85 | return out 86 | 87 | 88 | def ShuffleNetG2(): 89 | cfg = { 90 | 'out_planes': [200,400,800], 91 | 'num_blocks': [4,8,4], 92 | 'groups': 2 93 | } 94 | return ShuffleNet(cfg) 95 | 96 | def ShuffleNetG3(): 97 | cfg = { 98 | 'out_planes': [240,480,960], 99 | 'num_blocks': [4,8,4], 100 | 'groups': 3 101 | } 102 | return ShuffleNet(cfg) 103 | 104 | 105 | def test(): 106 | net = ShuffleNetG2() 107 | x = Variable(torch.randn(1,3,32,32)) 108 | y = net(x) 109 | print(y) 110 | 111 | # test() 112 | -------------------------------------------------------------------------------- /models/shufflenet.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/shufflenet.pyc -------------------------------------------------------------------------------- /models/vgg.py: -------------------------------------------------------------------------------- 1 | '''VGG11/13/16/19 in Pytorch.''' 2 | import torch 3 | import torch.nn as nn 4 | from torch.autograd import Variable 5 | 6 | 7 | cfg = { 8 | 'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 9 | 'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 10 | 'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 11 | 'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 12 | } 13 | 14 | 15 | class VGG(nn.Module): 16 | def __init__(self, vgg_name): 17 | super(VGG, self).__init__() 18 | self.features = self._make_layers(cfg[vgg_name]) 19 | self.classifier = nn.Linear(512, 10) 20 | 21 | def forward(self, x): 22 | out = self.features(x) 23 | out = out.view(out.size(0), -1) 24 | out = self.classifier(out) 25 | return out 26 | 27 | def _make_layers(self, cfg): 28 | layers = [] 29 | in_channels = 3 30 | for x in cfg: 31 | if x == 'M': 32 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 33 | else: 34 | layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), 35 | nn.BatchNorm2d(x), 36 | nn.ReLU(inplace=True)] 37 | in_channels = x 38 | layers += [nn.AvgPool2d(kernel_size=1, stride=1)] 39 | return nn.Sequential(*layers) 40 | 41 | # net = VGG('VGG11') 42 | # x = torch.randn(2,3,32,32) 43 | # print(net(Variable(x)).size()) 44 | -------------------------------------------------------------------------------- /models/vgg.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flag-C/ThermometerEncoding/5959c13318386a3acc0e5107fed1b683ffef5c7e/models/vgg.pyc -------------------------------------------------------------------------------- /models/wide_resnet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.init as init 4 | import torch.nn.functional as F 5 | from torch.autograd import Variable 6 | 7 | import sys 8 | import numpy as np 9 | 10 | def conv3x3(in_planes, out_planes, stride=1): 11 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=True) 12 | 13 | def conv_init(m): 14 | classname = m.__class__.__name__ 15 | if classname.find('Conv') != -1: 16 | init.xavier_uniform(m.weight, gain=np.sqrt(2)) 17 | init.constant(m.bias, 0) 18 | elif classname.find('BatchNorm') != -1: 19 | init.constant(m.weight, 1) 20 | init.constant(m.bias, 0) 21 | 22 | class wide_basic(nn.Module): 23 | def __init__(self, in_planes, planes, dropout_rate, stride=1): 24 | super(wide_basic, self).__init__() 25 | self.bn1 = nn.BatchNorm2d(in_planes) 26 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, padding=1, bias=True) 27 | self.dropout = nn.Dropout(p=dropout_rate) 28 | self.bn2 = nn.BatchNorm2d(planes) 29 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=True) 30 | 31 | self.shortcut = nn.Sequential() 32 | if stride != 1 or in_planes != planes: 33 | self.shortcut = nn.Sequential( 34 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=True), 35 | ) 36 | 37 | def forward(self, x): 38 | out = self.dropout(self.conv1(F.relu(self.bn1(x)))) 39 | out = self.conv2(F.relu(self.bn2(out))) 40 | out += self.shortcut(x) 41 | 42 | return out 43 | 44 | class Wide_ResNet(nn.Module): 45 | def __init__(self, depth, widen_factor, dropout_rate, num_classes,level): 46 | super(Wide_ResNet, self).__init__() 47 | self.in_planes = 16 48 | 49 | assert ((depth-4)%6 ==0), 'Wide-resnet depth should be 6n+4' 50 | n = (depth-4)/6 51 | k = widen_factor 52 | 53 | print('| Wide-Resnet %dx%d' %(depth, k)) 54 | nStages = [16, 16*k, 32*k, 64*k] 55 | self.transform = nn.Sequential( 56 | nn.Conv2d(3*level,18,kernel_size=1,stride=1), 57 | nn.Sigmoid() 58 | ) 59 | self.conv1 = conv3x3(18,nStages[0]) 60 | self.layer1 = self._wide_layer(wide_basic, nStages[1], n, dropout_rate, stride=1) 61 | self.layer2 = self._wide_layer(wide_basic, nStages[2], n, dropout_rate, stride=2) 62 | self.layer3 = self._wide_layer(wide_basic, nStages[3], n, dropout_rate, stride=2) 63 | self.bn1 = nn.BatchNorm2d(nStages[3], momentum=0.9) 64 | self.linear = nn.Linear(nStages[3], num_classes) 65 | 66 | def _wide_layer(self, block, planes, num_blocks, dropout_rate, stride): 67 | strides = [stride] + [1]*(num_blocks-1) 68 | layers = [] 69 | 70 | for stride in strides: 71 | layers.append(block(self.in_planes, planes, dropout_rate, stride)) 72 | self.in_planes = planes 73 | 74 | return nn.Sequential(*layers) 75 | 76 | def forward(self, channel0,channel1,channel2): 77 | x = torch.cat((channel0,channel1,channel2),dim=1) 78 | out = self.transform(x) 79 | out = self.conv1(out) 80 | out = self.layer1(out) 81 | out = self.layer2(out) 82 | out = self.layer3(out) 83 | out = F.relu(self.bn1(out)) 84 | out = F.avg_pool2d(out, 8) 85 | out = out.view(out.size(0), -1) 86 | out = self.linear(out) 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | '''Train CIFAR10 with PyTorch.''' 2 | from __future__ import print_function 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.optim as optim 7 | import torch.nn.functional as F 8 | import torch.backends.cudnn as cudnn 9 | from tensorboardX import SummaryWriter 10 | 11 | import torchvision 12 | import torchvision.transforms as transforms 13 | 14 | import os 15 | import argparse 16 | 17 | from models import * 18 | from util import progress_bar 19 | from torch.autograd import Variable 20 | from encoder import encoder 21 | from LSPGA import LSPGA 22 | 23 | 24 | parser = argparse.ArgumentParser(description='PyTorch CIFAR10 Training') 25 | parser.add_argument('--level', default=15, type=int, help='image quantization level') 26 | parser.add_argument('--log',default='them/res50',type=str,help='path of log') 27 | args = parser.parse_args() 28 | 29 | use_cuda = torch.cuda.is_available() 30 | best_acc = 0 # best test accuracy 31 | start_epoch = 0 # start from epoch 0 or last checkpoint epoch 32 | 33 | # Data 34 | print('==> Preparing data..') 35 | transform_test = transforms.Compose([ 36 | transforms.ToTensor(), 37 | ]) 38 | 39 | testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) 40 | testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2) 41 | 42 | classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') 43 | 44 | # Model 45 | 46 | print('==> Resuming from checkpoint..') 47 | assert os.path.isdir('checkpoint'), 'Error: no checkpoint directory found!' 48 | checkpoint = torch.load('./checkpoint/ckpt.t7') 49 | net = checkpoint['net'] 50 | best_acc = checkpoint['acc'] 51 | start_epoch = checkpoint['epoch'] 52 | 53 | if use_cuda: 54 | net.cuda() 55 | net = torch.nn.DataParallel(net, device_ids=range(torch.cuda.device_count())) 56 | cudnn.benchmark = True 57 | 58 | criterion = nn.CrossEntropyLoss() 59 | encoder = encoder(level=args.level) 60 | LSPGA = LSPGA(model=net,epsilon=0.032,k=args.level,delta=1.2,xi=0.01,step=1,criterion=criterion,encoder=encoder) 61 | writer = SummaryWriter(log_dir=args.log) 62 | def advtest(): 63 | net.eval() 64 | test_loss = 0 65 | correct = 0 66 | total = 0 67 | for batch_idx, (inputs, targets) in enumerate(testloader): 68 | channel0, channel1, channel2 = LSPGA.attackthreechannel(inputs, targets) 69 | channel0, channel1, channel2 = torch.Tensor(channel0),torch.Tensor(channel1),torch.Tensor(channel2) 70 | if use_cuda: 71 | channel0, channel1, channel2,targets = channel0.cuda(), channel1.cuda(), channel2.cuda(),targets.cuda() 72 | channel0, channel1, channel2, targets = Variable(channel0),Variable(channel1),Variable(channel2), Variable(targets) 73 | outputs = net(channel0, channel1, channel2) 74 | loss = criterion(outputs, targets) 75 | 76 | test_loss += loss.data[0] 77 | _, predicted = torch.max(outputs.data, 1) 78 | total += targets.size(0) 79 | correct += predicted.eq(targets.data).cpu().sum() 80 | 81 | advc0,advc1,advc2 = (channel[-3:].data.cpu().numpy() for channel in [channel0,channel1,channel2]) 82 | advc0,advc1,advc2 = (encoder.temp2img(advc) for advc in [advc0,advc1,advc2]) 83 | advc0,advc1,advc2 = (torch.Tensor(advc[:,np.newaxis,:,:]) for advc in [advc0,advc1,advc2]) 84 | advimg = torch.cat((advc0,advc1,advc2),dim=1) 85 | advimg = torchvision.utils.make_grid(advimg) 86 | writer.add_image('Imagetest', advimg, batch_idx) 87 | 88 | progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' 89 | % (test_loss/(batch_idx+1), 100.*correct/total, correct, total)) 90 | 91 | if __name__ == '__main__': 92 | advtest() -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | '''Train CIFAR10 with PyTorch.''' 2 | from __future__ import print_function 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.optim as optim 7 | import torch.nn.functional as F 8 | import torch.backends.cudnn as cudnn 9 | 10 | import torchvision 11 | import torchvision.transforms as transforms 12 | 13 | import os 14 | import argparse 15 | 16 | from models import * 17 | from util import progress_bar 18 | from torch.autograd import Variable 19 | from encoder import encoder 20 | from LSPGA import LSPGA 21 | from tensorboardX import SummaryWriter 22 | 23 | 24 | parser = argparse.ArgumentParser(description='PyTorch CIFAR10 Training') 25 | parser.add_argument('--lr', default=0.1, type=float, help='learning rate') 26 | parser.add_argument('--level', default=15, type=int, help='image quantization level') 27 | parser.add_argument('--resume', '-r', action='store_true', help='resume from checkpoint') 28 | parser.add_argument('--step', '-s', default=7, type=int, help='steps of attack') 29 | parser.add_argument('--log',default='them/res50',type=str,help='path of log') 30 | args = parser.parse_args() 31 | 32 | use_cuda = torch.cuda.is_available() 33 | best_acc = 0 # best test accuracy 34 | start_epoch = 0 # start from epoch 0 or last checkpoint epoch 35 | attackstep = args.step 36 | 37 | # Data 38 | print('==> Preparing data..') 39 | transform_train = transforms.Compose([ 40 | transforms.RandomCrop(32, padding=4), 41 | transforms.RandomHorizontalFlip(), 42 | transforms.ToTensor(), 43 | ]) 44 | 45 | transform_test = transforms.Compose([ 46 | transforms.ToTensor(), 47 | ]) 48 | 49 | trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) 50 | trainloader = torch.utils.data.DataLoader(trainset, batch_size=256, shuffle=True, num_workers=2) 51 | 52 | testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) 53 | testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2) 54 | 55 | classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') 56 | 57 | # Model 58 | if args.resume: 59 | # Load checkpoint. 60 | print('==> Resuming from checkpoint..') 61 | assert os.path.isdir('checkpoint'), 'Error: no checkpoint directory found!' 62 | checkpoint = torch.load('./checkpoint/ckpt.t7') 63 | net = checkpoint['net'] 64 | best_acc = checkpoint['acc'] 65 | start_epoch = checkpoint['epoch'] 66 | else: 67 | print('==> Building model..') 68 | #net = ResNet50(level=args.level) 69 | net = Wide_ResNet(depth=34,widen_factor=4,dropout_rate=0.3,num_classes=10,level=args.level) 70 | 71 | if use_cuda: 72 | net.cuda() 73 | net = torch.nn.DataParallel(net, device_ids=range(torch.cuda.device_count())) 74 | cudnn.benchmark = True 75 | 76 | criterion = nn.CrossEntropyLoss() 77 | optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=0.9, weight_decay=5e-4) 78 | scheduler = torch.optim.lr_scheduler.StepLR(optimizer,30) 79 | encoder = encoder(level=args.level) 80 | attacker = LSPGA(model=net,epsilon=0.032,k=args.level,delta=1.2,xi=1.5,step=attackstep,criterion=criterion,encoder=encoder) 81 | writer = SummaryWriter(log_dir=args.log) 82 | # Training 83 | def train(epoch): 84 | print('\nEpoch: %d' % epoch) 85 | net.train() 86 | train_loss = 0 87 | correct = 0 88 | total = 0 89 | for batch_idx, (inputs, targets) in enumerate(trainloader): 90 | channel0,channel1,channel2=inputs.numpy()[:,0,:,:],inputs.numpy()[:,1,:,:],inputs.numpy()[:,2,:,:] 91 | channel0,channel1,channel2 = encoder.tempencoding(channel0),encoder.tempencoding(channel1),encoder.tempencoding(channel2) 92 | channel0, channel1, channel2 = torch.Tensor(channel0),torch.Tensor(channel1),torch.Tensor(channel2) 93 | if use_cuda: 94 | channel0, channel1, channel2,targets = channel0.cuda(), channel1.cuda(), channel2.cuda(),targets.cuda() 95 | optimizer.zero_grad() 96 | channel0, channel1, channel2, targets = Variable(channel0),Variable(channel1),Variable(channel2), Variable(targets) 97 | outputs = net(channel0, channel1, channel2) 98 | loss = criterion(outputs, targets) 99 | loss.backward() 100 | optimizer.step() 101 | 102 | train_loss += loss.data[0] 103 | _, predicted = torch.max(outputs.data, 1) 104 | total += targets.size(0) 105 | correct += predicted.eq(targets.data).cpu().sum() 106 | 107 | progress_bar(batch_idx, len(trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' 108 | % (train_loss/(batch_idx+1), 100.*correct/total, correct, total)) 109 | 110 | def test(epoch): 111 | global best_acc 112 | net.eval() 113 | test_loss = 0 114 | correct = 0 115 | total = 0 116 | for batch_idx, (inputs, targets) in enumerate(testloader): 117 | channel0,channel1,channel2=inputs.numpy()[:,0,:,:],inputs.numpy()[:,1,:,:],inputs.numpy()[:,2,:,:] 118 | channel0,channel1,channel2 = encoder.tempencoding(channel0),encoder.tempencoding(channel1),encoder.tempencoding(channel2) 119 | channel0, channel1, channel2 = torch.Tensor(channel0),torch.Tensor(channel1),torch.Tensor(channel2) 120 | if use_cuda: 121 | channel0, channel1, channel2,targets = channel0.cuda(), channel1.cuda(), channel2.cuda(),targets.cuda() 122 | channel0, channel1, channel2, targets = Variable(channel0),Variable(channel1),Variable(channel2), Variable(targets) 123 | outputs = net(channel0, channel1, channel2) 124 | loss = criterion(outputs, targets) 125 | 126 | test_loss += loss.data[0] 127 | _, predicted = torch.max(outputs.data, 1) 128 | total += targets.size(0) 129 | correct += predicted.eq(targets.data).cpu().sum() 130 | 131 | progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' 132 | % (test_loss/(batch_idx+1), 100.*correct/total, correct, total)) 133 | 134 | # Save checkpoint. 135 | acc = 100.*correct/total 136 | if acc > best_acc: 137 | print('Saving..') 138 | state = { 139 | 'net': net.module if use_cuda else net, 140 | 'acc': acc, 141 | 'epoch': epoch, 142 | } 143 | if not os.path.isdir('checkpoint'): 144 | os.mkdir('checkpoint') 145 | torch.save(state, './checkpoint/ckpt.t7') 146 | best_acc = acc 147 | 148 | def advtrain(epoch): 149 | global attackstep 150 | global attacker 151 | print('\nEpoch: %d' % epoch) 152 | net.train() 153 | train_loss = 0 154 | correct = 0 155 | total = 0 156 | for batch_idx, (inputs, targets) in enumerate(trainloader): 157 | channel0,channel1,channel2 = attacker.attackthreechannel(inputs,targets) 158 | channel0, channel1, channel2 = torch.Tensor(channel0),torch.Tensor(channel1),torch.Tensor(channel2) 159 | if use_cuda: 160 | channel0, channel1, channel2,targets = channel0.cuda(), channel1.cuda(), channel2.cuda(),targets.cuda() 161 | optimizer.zero_grad() 162 | channel0, channel1, channel2, targets = Variable(channel0),Variable(channel1),Variable(channel2), Variable(targets) 163 | outputs = net(channel0, channel1, channel2) 164 | loss = criterion(outputs, targets) 165 | loss.backward() 166 | optimizer.step() 167 | 168 | train_loss += loss.data[0] 169 | _, predicted = torch.max(outputs.data, 1) 170 | total += targets.size(0) 171 | correct += predicted.eq(targets.data).cpu().sum() 172 | if batch_idx==0: 173 | advc0,advc1,advc2 = (channel[-3:].data.cpu().numpy() for channel in [channel0,channel1,channel2]) 174 | advc0,advc1,advc2 = (encoder.temp2img(advc) for advc in [advc0,advc1,advc2]) 175 | advc0,advc1,advc2 = (torch.Tensor(advc[:,np.newaxis,:,:]) for advc in [advc0,advc1,advc2]) 176 | advimg = torch.cat((advc0,advc1,advc2),dim=1) 177 | advimg = torchvision.utils.make_grid(advimg) 178 | writer.add_image('Image', advimg, epoch) 179 | 180 | progress_bar(batch_idx, len(trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' 181 | % (train_loss/(batch_idx+1), 100.*correct/total, correct, total)) 182 | 183 | def advtest(epoch): 184 | global attacker 185 | net.eval() 186 | test_loss = 0 187 | correct = 0 188 | total = 0 189 | for batch_idx, (inputs, targets) in enumerate(testloader): 190 | channel0, channel1, channel2 = attacker.attackthreechannel(inputs, targets) 191 | channel0, channel1, channel2 = torch.Tensor(channel0),torch.Tensor(channel1),torch.Tensor(channel2) 192 | if use_cuda: 193 | channel0, channel1, channel2,targets = channel0.cuda(), channel1.cuda(), channel2.cuda(),targets.cuda() 194 | channel0, channel1, channel2, targets = Variable(channel0),Variable(channel1),Variable(channel2), Variable(targets) 195 | outputs = net(channel0, channel1, channel2) 196 | loss = criterion(outputs, targets) 197 | 198 | test_loss += loss.data[0] 199 | _, predicted = torch.max(outputs.data, 1) 200 | total += targets.size(0) 201 | correct += predicted.eq(targets.data).cpu().sum() 202 | 203 | progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' 204 | % (test_loss/(batch_idx+1), 100.*correct/total, correct, total)) 205 | 206 | acc = 100. * correct / total 207 | state = { 208 | 'net': net.module if use_cuda else net, 209 | 'acc': acc, 210 | 'epoch': epoch, 211 | } 212 | if not os.path.isdir('checkpoint'): 213 | os.mkdir('checkpoint') 214 | torch.save(state, './checkpoint/ckpt.t7') 215 | 216 | 217 | for epoch in range(start_epoch, start_epoch+200): 218 | scheduler.step() 219 | if attackstep==0: 220 | train(epoch) 221 | test(epoch) 222 | else: 223 | advtrain(epoch) 224 | advtest(epoch) 225 | -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import time 4 | import math 5 | 6 | import torch 7 | import torch.nn as nn 8 | import torch.nn.init as init 9 | 10 | def get_mean_and_std(dataset): 11 | '''Compute the mean and std value of dataset.''' 12 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2) 13 | mean = torch.zeros(3) 14 | std = torch.zeros(3) 15 | print('==> Computing mean and std..') 16 | for inputs, targets in dataloader: 17 | for i in range(3): 18 | mean[i] += inputs[:,i,:,:].mean() 19 | std[i] += inputs[:,i,:,:].std() 20 | mean.div_(len(dataset)) 21 | std.div_(len(dataset)) 22 | return mean, std 23 | 24 | def init_params(net): 25 | '''Init layer parameters.''' 26 | for m in net.modules(): 27 | if isinstance(m, nn.Conv2d): 28 | init.kaiming_normal(m.weight, mode='fan_out') 29 | if m.bias: 30 | init.constant(m.bias, 0) 31 | elif isinstance(m, nn.BatchNorm2d): 32 | init.constant(m.weight, 1) 33 | init.constant(m.bias, 0) 34 | elif isinstance(m, nn.Linear): 35 | init.normal(m.weight, std=1e-3) 36 | if m.bias: 37 | init.constant(m.bias, 0) 38 | 39 | 40 | _, term_width = os.popen('stty size', 'r').read().split() 41 | term_width = int(term_width) 42 | 43 | TOTAL_BAR_LENGTH = 65. 44 | last_time = time.time() 45 | begin_time = last_time 46 | def progress_bar(current, total, msg=None): 47 | global last_time, begin_time 48 | if current == 0: 49 | begin_time = time.time() # Reset for new bar. 50 | 51 | cur_len = int(TOTAL_BAR_LENGTH*current/total) 52 | rest_len = int(TOTAL_BAR_LENGTH - cur_len) - 1 53 | 54 | sys.stdout.write(' [') 55 | for i in range(cur_len): 56 | sys.stdout.write('=') 57 | sys.stdout.write('>') 58 | for i in range(rest_len): 59 | sys.stdout.write('.') 60 | sys.stdout.write(']') 61 | 62 | cur_time = time.time() 63 | step_time = cur_time - last_time 64 | last_time = cur_time 65 | tot_time = cur_time - begin_time 66 | 67 | L = [] 68 | L.append(' Step: %s' % format_time(step_time)) 69 | L.append(' | Tot: %s' % format_time(tot_time)) 70 | if msg: 71 | L.append(' | ' + msg) 72 | 73 | msg = ''.join(L) 74 | sys.stdout.write(msg) 75 | for i in range(term_width-int(TOTAL_BAR_LENGTH)-len(msg)-3): 76 | sys.stdout.write(' ') 77 | 78 | # Go back to the center of the bar. 79 | for i in range(term_width-int(TOTAL_BAR_LENGTH/2)+2): 80 | sys.stdout.write('\b') 81 | sys.stdout.write(' %d/%d ' % (current+1, total)) 82 | 83 | if current < total-1: 84 | sys.stdout.write('\r') 85 | else: 86 | sys.stdout.write('\n') 87 | sys.stdout.flush() 88 | 89 | def format_time(seconds): 90 | days = int(seconds / 3600/24) 91 | seconds = seconds - days*3600*24 92 | hours = int(seconds / 3600) 93 | seconds = seconds - hours*3600 94 | minutes = int(seconds / 60) 95 | seconds = seconds - minutes*60 96 | secondsf = int(seconds) 97 | seconds = seconds - secondsf 98 | millis = int(seconds*1000) 99 | 100 | f = '' 101 | i = 1 102 | if days > 0: 103 | f += str(days) + 'D' 104 | i += 1 105 | if hours > 0 and i <= 2: 106 | f += str(hours) + 'h' 107 | i += 1 108 | if minutes > 0 and i <= 2: 109 | f += str(minutes) + 'm' 110 | i += 1 111 | if secondsf > 0 and i <= 2: 112 | f += str(secondsf) + 's' 113 | i += 1 114 | if millis > 0 and i <= 2: 115 | f += str(millis) + 'ms' 116 | i += 1 117 | if f == '': 118 | f = '0ms' 119 | return f --------------------------------------------------------------------------------