├── .gitignore ├── requirements.sh ├── README.md ├── LICENSE ├── scripts ├── test.lua └── train.lua ├── core └── autoencoder.lua ├── docs ├── ae1.tex ├── ae2.tex └── ae3.tex └── io └── lmdb_reader.lua /.gitignore: -------------------------------------------------------------------------------- 1 | data/networks/* 2 | data/results/* 3 | -------------------------------------------------------------------------------- /requirements.sh: -------------------------------------------------------------------------------- 1 | luarocks install https://raw.githubusercontent.com/eladhoffer/lmdb.torch/master/lmdb.torch-scm-1.rockspec 2 | 3 | luarocks install protobuf 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is archived as of 2019 because Torch is no longer a relevant machine learning framework. 2 | 3 | # imagenet-autoencoder 4 | Autoencoder trained on ImageNet Using Torch 7 5 | 6 | Description is available at: http://siavashk.github.io/2016/02/22/autoencoder-imagenet/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Siavash Khallaghi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/test.lua: -------------------------------------------------------------------------------- 1 | require 'torch' 2 | require 'nn' 3 | 4 | require '../core/autoencoder.lua' 5 | require '../io/lmdb_reader' 6 | require 'image' 7 | 8 | defaults = { 9 | batch_size = 1, 10 | n_batches = 1, 11 | save_prefix = './data/results' 12 | } 13 | 14 | cmd = torch.CmdLine() 15 | cmd:argument('net_path', 'network to load') 16 | cmd:argument('data_path', 'lmdb database to test on') 17 | cmd:option('-batch_size', defaults.batch_size, 'batch size') 18 | cmd:option('-n_batches', defaults.n_batches, 'number of batches') 19 | cmd:option('-save_prefix', defaults.save_prefix, 'number of batches') 20 | 21 | 22 | options = cmd:parse(arg) 23 | 24 | print(options) 25 | 26 | imagenet_reader = lmdb_reader(options.data_path) 27 | 28 | ae = autoencoder() 29 | 30 | ae:initialize() 31 | 32 | ae:load(options.net_path) 33 | 34 | for i=1, options.n_batches do 35 | data_batch = imagenet_reader:get_data(options.batch_size) 36 | for j=1, options.batch_size do 37 | local input_filename = options.save_prefix .. '/' .. 'input_' .. i .. '_' .. j .. '.jpg' 38 | local output_filename = options.save_prefix .. '/' .. 'output_' .. i .. '_' .. j .. '.jpg' 39 | 40 | input = data_batch[j] 41 | 42 | image.save(input_filename, input) 43 | 44 | result = ae:forward(input) 45 | 46 | image.save(output_filename, result) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /scripts/train.lua: -------------------------------------------------------------------------------- 1 | require 'torch' 2 | require 'nn' 3 | 4 | require '../core/autoencoder.lua' 5 | require '../io/lmdb_reader' 6 | 7 | defaults = { 8 | epochs = 100, 9 | iters = 100, 10 | learning_rate = 0.01, 11 | batch_size = 1000, 12 | save_path = './data/networks/autoencoder.bin' 13 | } 14 | 15 | cmd = torch.CmdLine() 16 | cmd:argument('data_path', 'lmdb database to train on') 17 | cmd:option('save_path', defaults.save_path, 'lmdb database to test on') 18 | cmd:option('-epochs', defaults.epochs, 'number of epochs') 19 | cmd:option('-iters', defaults.iters, 'number of iterations per epochs') 20 | cmd:option('-learning_rate', defaults.learning_rate, 'learning rate') 21 | cmd:option('-batch_size', defaults.batch_size, 'batch size') 22 | 23 | options = cmd:parse(arg) 24 | 25 | print(options) 26 | 27 | imagenet_reader = lmdb_reader(options.data_path) 28 | 29 | ae = autoencoder() 30 | 31 | ae:initialize() 32 | 33 | ae:printself() 34 | 35 | criterion = nn.MSECriterion():cuda() 36 | 37 | trainer = nn.StochasticGradient(ae.net, criterion) 38 | 39 | trainer.learningRate = options.learning_rate 40 | trainer.maxIteration = options.iters 41 | 42 | 43 | for t=1, options.epochs do 44 | print('Epoch ' .. t) 45 | data_set = imagenet_reader:get_training_data(options.batch_size) 46 | 47 | trainer:train(data_set) 48 | 49 | end 50 | 51 | ae:save(options.save_path) 52 | -------------------------------------------------------------------------------- /core/autoencoder.lua: -------------------------------------------------------------------------------- 1 | require 'torch' 2 | require 'cutorch' 3 | require 'cudnn' 4 | require 'nn' 5 | require 'cunn' 6 | 7 | autoencoder = {} 8 | autoencoder.__index = autoencoder 9 | 10 | setmetatable(autoencoder, { 11 | __call = function (cls, ...) 12 | return cls.new(...) 13 | end, 14 | }) 15 | 16 | function autoencoder.new() 17 | local self = setmetatable({}, autoencoder) 18 | return self 19 | end 20 | 21 | function autoencoder:initialize() 22 | local pool_layer1 = nn.SpatialMaxPooling(2, 2, 2, 2) 23 | local pool_layer2 = nn.SpatialMaxPooling(2, 2, 2, 2) 24 | 25 | self.net = nn.Sequential() 26 | self.net:add(nn.SpatialConvolution(3, 12, 3, 3, 1, 1, 1, 1)) 27 | self.net:add(nn.ReLU()) 28 | self.net:add(nn.SpatialConvolution(12, 12, 3, 3, 1, 1, 1, 1)) 29 | self.net:add(nn.ReLU()) 30 | self.net:add(pool_layer1) 31 | self.net:add(nn.SpatialConvolution(12, 24, 3, 3, 1, 1, 1, 1)) 32 | self.net:add(nn.ReLU()) 33 | self.net:add(pool_layer2) 34 | self.net:add(nn.Reshape(24 * 16 * 16)) 35 | self.net:add(nn.Linear(24 * 16 * 16, 1568)) 36 | self.net:add(nn.Linear(1568, 24 * 16 * 16)) 37 | self.net:add(nn.Reshape(24, 16, 16)) 38 | self.net:add(nn.SpatialConvolution(24, 12, 3, 3, 1, 1, 1, 1)) 39 | self.net:add(nn.ReLU()) 40 | self.net:add(nn.SpatialMaxUnpooling(pool_layer2)) 41 | self.net:add(nn.SpatialConvolution(12, 12, 3, 3, 1, 1, 1, 1)) 42 | self.net:add(nn.ReLU()) 43 | self.net:add(nn.SpatialMaxUnpooling(pool_layer1)) 44 | self.net:add(nn.SpatialConvolution(12, 3, 3, 3, 1, 1, 1, 1)) 45 | 46 | self.net = self.net:cuda() 47 | end 48 | 49 | function autoencoder:printself() 50 | print(self.net) 51 | end 52 | 53 | function autoencoder:save(filename) 54 | torch.save(filename, self.net) 55 | end 56 | 57 | function autoencoder:load(filename) 58 | self:initialize() 59 | self.net = torch.load(filename) 60 | end 61 | 62 | function autoencoder:forward(input) 63 | return self.net:forward(input) 64 | end 65 | -------------------------------------------------------------------------------- /docs/ae1.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Welcome to Overleaf --- just edit your LaTeX on the left, 4 | % and we'll compile it for you on the right. If you give 5 | % someone the link to this page, they can edit at the same 6 | % time. See the help menu above for more info. Enjoy! 7 | % 8 | % Note: you can export the pdf to see the result at full 9 | % resolution. 10 | % 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Block diagram wire junctions 13 | \documentclass{article} 14 | \usepackage{tikz} 15 | \usetikzlibrary{arrows} 16 | \usepackage{verbatim} 17 | \usetikzlibrary{patterns} 18 | 19 | \begin{comment} 20 | :Title: Block diagram line junctions 21 | :Slug: line-junctions 22 | :Tags: Block diagrams, Foreach, Transformations, Paths 23 | 24 | An example of how to draw line junctions in a block diagram. 25 | A semicircle is used to indicate that two lines are not connected. 26 | This is a good example of how flexible TikZ' paths are. 27 | The intersection between the lines are calculated using the convenient 28 | ``-|`` syntax. Since we want the semicircle to have its center where 29 | the lines intersect, we have to shift the intersection coordinate 30 | accordingly. 31 | 32 | \end{comment} 33 | 34 | 35 | \begin{document} 36 | 37 | \tikzstyle{block} = [draw,minimum size=2em] 38 | \tikzstyle{data} = [draw,shape=circle,minimum size=2em] 39 | 40 | 41 | % diameter of semicircle used to indicate that two lines are not connected 42 | \def\radius{.7mm} 43 | \tikzstyle{branch}=[fill,shape=circle,minimum size=3pt,inner sep=0pt] 44 | 45 | \begin{tikzpicture}[>=latex'] 46 | \node[data] at (0,0) (input) {I}; 47 | \node[block] at (1.5,0) (encoder) {$Encoder$}; 48 | \draw[->] (input) -- (encoder); 49 | \node[data] at (3,0) (code) {C}; 50 | \draw[->] (encoder) -- (code); 51 | \node[block] at (4.5,0) (decoder) {$Decoder$}; 52 | \draw[->] (code) -- (decoder); 53 | \node[data] at (6,0) (output) {$\hat{\mathrm{I}}$}; 54 | \draw[->] (decoder) -- (output); 55 | \end{tikzpicture} 56 | \end{document} 57 | -------------------------------------------------------------------------------- /docs/ae2.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Welcome to Overleaf --- just edit your LaTeX on the left, 4 | % and we'll compile it for you on the right. If you give 5 | % someone the link to this page, they can edit at the same 6 | % time. See the help menu above for more info. Enjoy! 7 | % 8 | % Note: you can export the pdf to see the result at full 9 | % resolution. 10 | % 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Block diagram wire junctions 13 | \documentclass{article} 14 | \usepackage{tikz} 15 | \usetikzlibrary{arrows} 16 | \usepackage{verbatim} 17 | 18 | \begin{comment} 19 | :Title: Block diagram line junctions 20 | :Slug: line-junctions 21 | :Tags: Block diagrams, Foreach, Transformations, Paths 22 | 23 | An example of how to draw line junctions in a block diagram. 24 | A semicircle is used to indicate that two lines are not connected. 25 | This is a good example of how flexible TikZ' paths are. 26 | The intersection between the lines are calculated using the convenient 27 | ``-|`` syntax. Since we want the semicircle to have its center where 28 | the lines intersect, we have to shift the intersection coordinate 29 | accordingly. 30 | 31 | \end{comment} 32 | 33 | 34 | \begin{document} 35 | 36 | \tikzstyle{block} = [draw,minimum size=2em] 37 | \tikzstyle{data} = [draw,shape=circle,minimum size=2em] 38 | 39 | 40 | % diameter of semicircle used to indicate that two lines are not connected 41 | \def\radius{.7mm} 42 | \tikzstyle{branch}=[fill,shape=circle,minimum size=3pt,inner sep=0pt] 43 | 44 | \begin{tikzpicture}[>=latex'] 45 | \node[data] at (0,0) (input) {I}; 46 | \node[block] at (1.5,0) (conv1) {$Conv_1$}; 47 | \draw[->] (input) -- (conv1); 48 | \node[block] at (3,0) (relu1) {$ReLU$}; 49 | \draw[->] (conv1) -- (relu1); 50 | \node[block] at (4.5,0) (conv2) {$Conv_2$}; 51 | \draw[->] (relu1) -- (conv2); 52 | \node[block] at (6,0) (relu2) {$ReLU$}; 53 | \draw[->] (conv2) -- (relu2); 54 | \node[block] at (7.5,0) (pool1) {$Pool_1$}; 55 | \draw[->] (relu2) -- (pool1); 56 | \node[block] at (9,0) (conv3) {$Conv_3$}; 57 | \draw[->] (pool1) -- (conv3); 58 | \node[block] at (10.5,0) (relu3) {$ReLU$}; 59 | \draw[->] (conv3) -- (relu3); 60 | \node[block] at (12,0) (pool2) {$Pool_2$}; 61 | \draw[->] (relu3) -- (pool2); 62 | \node[block] at (13.5,0) (l1) {$Linear$}; 63 | \draw[->] (pool2) -- (l1); 64 | \node[data] at (15,0) (output) {C}; 65 | \draw[->] (l1) -- (output); 66 | 67 | \end{tikzpicture} 68 | \end{document} 69 | -------------------------------------------------------------------------------- /io/lmdb_reader.lua: -------------------------------------------------------------------------------- 1 | require 'lmdb' 2 | require 'string' 3 | require 'torch' 4 | require 'image' 5 | pb = require './pb' 6 | 7 | lmdb_reader = {} 8 | lmdb_reader.__index = lmdb_reader 9 | 10 | setmetatable(lmdb_reader, { 11 | __call = function (cls, ...) 12 | return cls.new(...) 13 | end, 14 | }) 15 | 16 | 17 | function lmdb_reader.new(file_path) 18 | local self = setmetatable({}, lmdb_reader) 19 | self.dims = {3, 64, 64} 20 | self.datum = pb.Datum() 21 | self.db= lmdb.env{ 22 | Path = file_path, 23 | } 24 | self.db:open() 25 | local reader = self.db:txn(true) 26 | self.cursor = reader:cursor() 27 | 28 | return self 29 | end 30 | 31 | function lmdb_reader:addString(stack, s) 32 | table.insert(stack, s) --push 's' into the stack 33 | for i=table.getn(stack)-1, 1,-1 do 34 | if string.len(stack[i]) > string.len(stack[i+1]) then 35 | break 36 | end 37 | stack[i] = stack[i] .. table.remove(stack) 38 | end 39 | end 40 | 41 | 42 | function lmdb_reader:get_data(num_elements) 43 | dataset = {} 44 | function dataset:size() return num_elements end -- 100 examples 45 | 46 | for i=1,num_elements do 47 | dataset[i] = self:get_tensor(datum) 48 | self.cursor:next() 49 | end 50 | return dataset 51 | end 52 | 53 | function lmdb_reader:get_training_data(num_elements) 54 | dataset = {} 55 | function dataset:size() return num_elements end 56 | 57 | for i=1,num_elements do 58 | local v = self:get_tensor(datum) 59 | dataset[i] = {v, v} 60 | self.cursor:next() 61 | end 62 | return dataset 63 | end 64 | 65 | function lmdb_reader:get_tensor() 66 | local data = self.cursor:getData() 67 | local str = self.tensor_2_string(data) 68 | self.datum:ParseFromString(str) 69 | return self.string_2_tensor(self.datum.data, self.dims):cuda() 70 | end 71 | --this is the slow part! 72 | function lmdb_reader.tensor_2_string(tensor) 73 | 74 | s = {""} -- an empty stack 75 | for i=1, tensor:size()[1] do 76 | lmdb_reader:addString(s, string.char(tensor[i])) 77 | end 78 | s = table.concat(s) 79 | s = tostring(s) 80 | return s 81 | end 82 | 83 | --this is kind of slow too! 84 | function lmdb_reader.string_2_tensor(string, dims) 85 | local tensor = torch.Tensor(dims[1], dims[2], dims[3]) 86 | local idx = 1 87 | for c = 1, dims[1] do 88 | for x = 1, dims[2] do 89 | for y = 1, dims[3] do 90 | tensor[c][x][y] = string:byte(idx) / 256 91 | idx = idx + 1 92 | end 93 | end 94 | end 95 | return tensor 96 | end 97 | -------------------------------------------------------------------------------- /docs/ae3.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Welcome to Overleaf --- just edit your LaTeX on the left, 4 | % and we'll compile it for you on the right. If you give 5 | % someone the link to this page, they can edit at the same 6 | % time. See the help menu above for more info. Enjoy! 7 | % 8 | % Note: you can export the pdf to see the result at full 9 | % resolution. 10 | % 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Block diagram wire junctions 13 | \documentclass{article} 14 | \usepackage{tikz} 15 | \usetikzlibrary{arrows} 16 | \usepackage{verbatim} 17 | 18 | \begin{comment} 19 | :Title: Block diagram line junctions 20 | :Slug: line-junctions 21 | :Tags: Block diagrams, Foreach, Transformations, Paths 22 | 23 | An example of how to draw line junctions in a block diagram. 24 | A semicircle is used to indicate that two lines are not connected. 25 | This is a good example of how flexible TikZ' paths are. 26 | The intersection between the lines are calculated using the convenient 27 | ``-|`` syntax. Since we want the semicircle to have its center where 28 | the lines intersect, we have to shift the intersection coordinate 29 | accordingly. 30 | 31 | \end{comment} 32 | 33 | 34 | \begin{document} 35 | 36 | \tikzstyle{block} = [draw,minimum size=2em] 37 | \tikzstyle{data} = [draw,shape=circle,minimum size=2em] 38 | 39 | 40 | % diameter of semicircle used to indicate that two lines are not connected 41 | \def\radius{.7mm} 42 | \tikzstyle{branch}=[fill,shape=circle,minimum size=3pt,inner sep=0pt] 43 | 44 | \begin{tikzpicture}[>=latex'] 45 | \node[data] at (0,0) (input) {C}; 46 | \node[block] at (1.2,0) (l1) {$Linear$}; 47 | \draw[->] (input) -- (l1); 48 | \node[block] at (2.8,0) (unpool2) {$Unpool_2$}; 49 | \draw[->] (l1) -- (unpool2); 50 | \node[block] at (4.4,0) (dconv3) {$DConv_3$}; 51 | \draw[->] (unpool2) -- (dconv3); 52 | \node[block] at (5.9,0) (relu3) {$ReLU$}; 53 | \draw[->] (dconv3) -- (relu3); 54 | \node[block] at (7.4,0) (unpool1) {$Unpool_1$}; 55 | \draw[->] (relu3) -- (unpool1); 56 | \node[block] at (9,0) (dconv2) {$DConv_2$}; 57 | \draw[->] (unpool1) -- (dconv2); 58 | \node[block] at (10.5,0) (relu2) {$ReLU$}; 59 | \draw[->] (dconv2) -- (relu2); 60 | \node[block] at (12,0) (dconv1) {$DConv_1$}; 61 | \draw[->] (relu2) -- (dconv1); 62 | \node[block] at (13.5,0) (relu1) {$ReLU$}; 63 | \draw[->] (dconv1) -- (relu1); 64 | \node[data] at (14.7,0) (output) {$\hat{\mathrm{I}}$}; 65 | \draw[->] (relu1) -- (output); 66 | 67 | \end{tikzpicture} 68 | \end{document} 69 | --------------------------------------------------------------------------------