Commit b179dc12 by Ting PAN

Redirect DragonLair

1 parent 5564c17a
Showing with 5 additions and 5040 deletions
......@@ -17,6 +17,7 @@
# Compiled python
*.pyc
__pycache__
# Compiled MATLAB
*.mex*
......
[submodule "DragonBoard"]
path = DragonBoard
url = git://github.com/seetaresearch/DragonBoard.git
[submodule "DragonLair"]
path = DragonLair
url = https://github.com/seetaresearch/DragonLair.git
Subproject commit 0e7c32d84ba3758cb1ae703923d73a47add5442d
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
class Config(object):
#########################################################################
# Game configuration
# Name of the game, with version (e.g. PongDeterministic-v0)
ATARI_GAME = 'PongDeterministic-v0'
# Enable to see the trained agent in action
PLAY_MODE = False
# Enable to train
TRAIN_MODELS = True
# Load old models. Throws if the model doesn't exist
LOAD_CHECKPOINT = False
# If 0, the latest checkpoint is loaded
LOAD_EPISODE = 32000
#########################################################################
# Number of agents, predictors, trainers and other system settings
# If the dynamic configuration is on, these are the initial values.
# Number of Agents
AGENTS = 32
# Number of Predictors
PREDICTORS = 2
# Number of Trainers
TRAINERS = 2
# Device
DEVICE = 'gpu:0'
# Enable the dynamic adjustment (+ waiting time to start it)
DYNAMIC_SETTINGS = True
DYNAMIC_SETTINGS_STEP_WAIT = 20
DYNAMIC_SETTINGS_INITIAL_WAIT = 10
#########################################################################
# Algorithm parameters
# Discount factor
DISCOUNT = 0.99
# Tmax
TIME_MAX = 5
# Reward Clipping
REWARD_MIN = -1
REWARD_MAX = 1
# Max size of the queue
MAX_QUEUE_SIZE = 100
PREDICTION_BATCH_SIZE = 128
# Input of the DNN
STACKED_FRAMES = 4
IMAGE_WIDTH = 84
IMAGE_HEIGHT = 84
# Total number of episodes and annealing frequency
EPISODES = 400000
ANNEALING_EPISODE_COUNT = 400000
# Entropy regualrization hyper-parameter
BETA_START = 0.01
BETA_END = 0.01
# Learning rate
LEARNING_RATE_START = 0.0003
LEARNING_RATE_END = 0.0003
# RMSProp parameters
RMSPROP_DECAY = 0.99
RMSPROP_MOMENTUM = 0.0
RMSPROP_EPSILON = 0.1
# Dual RMSProp - we found that using a single RMSProp for the two cost function works better and faster
DUAL_RMSPROP = False
# Gradient clipping
USE_GRAD_CLIP = True
GRAD_CLIP_NORM = 40.0
# Epsilon (regularize policy lag in GA3C)
LOG_EPSILON = 1e-6
# Training min batch size - increasing the batch size increases the stability of the algorithm, but make learning slower
TRAINING_MIN_BATCH_SIZE = 0
#########################################################################
# Log and save
# Enable TensorBoard
TENSORBOARD = False
# Update TensorBoard every X training steps
TENSORBOARD_UPDATE_FREQUENCY = 1000
# Enable to save models every SAVE_FREQUENCY episodes
SAVE_MODELS = True
# Save every SAVE_FREQUENCY episodes
SAVE_FREQUENCY = 2000
# Print stats every PRINT_STATS_FREQUENCY episodes
PRINT_STATS_FREQUENCY = 1
# The window to average stats
STAT_ROLLING_MEAN_WINDOW = 1000
# Results filename
RESULTS_FILENAME = 'results.txt'
# Network checkpoint name
NETWORK_NAME = 'network'
#########################################################################
# More experimental parameters here
# Minimum policy
MIN_POLICY = 0.0
# Use log_softmax() instead of log(softmax())
USE_LOG_SOFTMAX = False
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
import numpy as np
import scipy.misc as misc
from Config import Config
from GameManager import GameManager
class Queue(object):
def __init__(self, maxsize):
self._maxsize = maxsize
self.queue = []
def full(self):
return len(self.queue) >= self._maxsize
def get(self):
ret = self.queue[0]
self.queue = self.queue[1:]
return ret
def put(self, x):
self.queue.append(x)
def clear(self):
self.queue = []
class Environment:
def __init__(self):
self.game = GameManager(Config.ATARI_GAME, display=Config.PLAY_MODE)
self.nb_frames = Config.STACKED_FRAMES
self.frame_q = Queue(maxsize=self.nb_frames)
self.previous_state = None
self.current_state = None
self.total_reward = 0
self.reset()
@staticmethod
def _rgb2gray(rgb):
return np.dot(rgb[..., :3], [0.299, 0.587, 0.114])
@staticmethod
def _preprocess(image):
image = Environment._rgb2gray(image)
image = misc.imresize(image, [Config.IMAGE_HEIGHT, Config.IMAGE_WIDTH], 'bilinear')
image = image.astype(np.float32) / 128.0 - 1.0
return image
def _get_current_state(self):
if not self.frame_q.full():
return None # frame queue is not full yet.
x_ = np.array(self.frame_q.queue, dtype=np.float32)
return x_
def _update_frame_q(self, frame):
if self.frame_q.full():
self.frame_q.get()
image = Environment._preprocess(frame)
self.frame_q.put(image)
def get_num_actions(self):
return self.game.env.action_space.n
def reset(self):
self.total_reward = 0
self.frame_q.clear()
self._update_frame_q(self.game.reset())
self.previous_state = self.current_state = None
def step(self, action):
observation, reward, done, _ = self.game.step(action)
self.total_reward += reward
self._update_frame_q(observation)
self.previous_state = self.current_state
self.current_state = self._get_current_state()
return reward, done
\ No newline at end of file
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from Config import Config
from Server import Server
# Adjust configs for Play mode
if Config.PLAY_MODE:
Config.AGENTS = 1
Config.PREDICTORS = 1
Config.TRAINERS = 1
Config.DYNAMIC_SETTINGS = False
Config.LOAD_CHECKPOINT = True
Config.TRAIN_MODELS = False
Config.SAVE_MODELS = False
if __name__ == "__main__":
import dragon.config
dragon.config.EnableCUDA()
Server().main()
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
import gym
class GameManager:
def __init__(self, game_name, display):
self.game_name = game_name
self.display = display
self.env = gym.make(game_name)
self.reset()
def reset(self):
observation = self.env.reset()
return observation
def step(self, action):
self._update_display()
observation, reward, done, info = self.env.step(action)
return observation, reward, done, info
def _update_display(self):
if self.display:
self.env.render()
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
import threading
from dragon.core.tensor import Tensor
import dragon.vm.theano as theano
import dragon.vm.theano.tensor as T
import dragon.ops as ops
import dragon.core.workspace as ws
import dragon.updaters as updaters
from Config import Config
mutex = threading.Lock()
class NetworkVP:
def __init__(self, model_name, num_actions):
self.model_name = model_name
self.num_actions = num_actions
self.network_params = []
self.img_width = Config.IMAGE_WIDTH
self.img_height = Config.IMAGE_HEIGHT
self.img_channels = Config.STACKED_FRAMES
self.learning_rate = Config.LEARNING_RATE_START
self.beta = Config.BETA_START
self.log_epsilon = Config.LOG_EPSILON
self._create_graph()
if Config.PLAY_MODE:
ws
def _create_graph(self):
self.x = Tensor(shape=[None, self.img_channels, self.img_height, self.img_width]).Variable()
self.y_r = Tensor(shape=[None], name='Yr').Variable()
# As implemented in A3C paper
self.n1 = ops.Relu(ops.Conv2D([self.x] + self.weight_bias(), kernel_size=8, stride=4, num_output=16))
self.n2 = ops.Relu(ops.Conv2D([self.n1] + self.weight_bias(), kernel_size=4, stride=2, num_output=32))
self.action_index = Tensor(shape=[None, self.num_actions]).Variable()
self.d1 = ops.Relu(ops.InnerProduct([self.n2] + self.weight_bias(), num_output=256))
self.logits_v = ops.InnerProduct([self.d1] + self.weight_bias(), num_output=1)
self.cost_v = ops.L2Loss([self.y_r, self.logits_v])
self.logits_p = ops.InnerProduct([self.d1] + self.weight_bias(), num_output=self.num_actions)
if Config.USE_LOG_SOFTMAX: raise NotImplementedError()
else:
self.softmax_p = ops.Softmax(self.logits_p)
self.selected_action_prob = ops.Sum(self.softmax_p * self.action_index, axis=1)
self.cost_p_1 = ops.Log(ops.Clip(self.selected_action_prob, self.log_epsilon, None)) * \
(self.y_r - ops.StopGradient(self.logits_v))
self.cost_p_2 = ops.Sum(ops.Log(ops.Clip(self.softmax_p, self.log_epsilon, None)) *
self.softmax_p, axis=1) * (-self.beta)
self.cost_p_1_agg = ops.Sum(self.cost_p_1)
self.cost_p_2_agg = ops.Sum(self.cost_p_2)
self.cost_p = -(self.cost_p_1_agg + self.cost_p_2_agg)
self.cost_all = self.cost_p + self.cost_v
if Config.DUAL_RMSPROP: raise NotImplementedError()
else:
if Config.USE_GRAD_CLIP:
self.opt = updaters.RMSPropUpdater(decay=Config.RMSPROP_DECAY,
eps=Config.RMSPROP_EPSILON,
clip_gradient=Config.GRAD_CLIP_NORM)
else:
self.opt = updaters.RMSPropUpdater(decay=Config.RMSPROP_DECAY,
eps=Config.RMSPROP_EPSILON)
grads = T.grad(self.cost_all, self.network_params)
for p, g in zip(self.network_params, grads):
self.opt.append((p, g), lr_mult=1.0)
def weight_bias(self, weights_init=None, no_bias=False):
if weights_init is None:
weight = Tensor().Xavier()
else:
weight = weights_init
if no_bias:
self.network_params.extend([weight])
return [weight]
bias = Tensor().Constant(value=0)
self.network_params.extend([weight, bias])
return [weight, bias]
def predict_single(self, x):
return self.predict_p(x[None, :])[0]
def predict_v(self, x):
if not hasattr(self, '_predict_p'):
self._predict_v = theano.function(inputs=self.x, outputs=self.logits_v)
return self._predict_v(x)
def predict_p(self, x):
if not hasattr(self, '_predict_p'):
self._predict_p = theano.function(inputs=self.x, outputs=self.softmax_p)
return self._predict_p(x)
def predict_p_and_v(self, x):
if not hasattr(self, '_predict_p_and_v'):
self._predict_p_and_v = theano.function(inputs=self.x, outputs=[self.softmax_p, self.logits_v])
global mutex
mutex.acquire()
p, v = self._predict_p_and_v(x)
mutex.release()
return p, v
def train(self, x, y_r, a):
if not hasattr(self, '_train'):
self._compute = theano.function(inputs=[self.x, self.y_r, self.action_index],
outputs=self.cost_all)
self._train = theano.function(updater=self.opt)
global mutex
mutex.acquire()
loss = self._compute(x, y_r, a)
mutex.release()
self._train()
return loss
def save(self, episode):
filename = 'checkpoints/%s_%08d' % (self.model_name, episode)
ws.Snapshot(self.network_params, filename)
def load(self):
filename = 'checkpoints/%s_%08d.bin' % (self.model_name, Config.LOAD_EPISODE)
ws.Restore(filename)
return Config.LOAD_EPISODE
\ No newline at end of file
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from datetime import datetime
from multiprocessing import Process, Queue, Value
import numpy as np
import time
from Config import Config
from Environment import Environment
class Experience(object):
def __init__(self, state, action, prob, reward, done):
self.state = state
self.action = action
self.prob = prob
self.reward = reward
self.done = done
class ProcessAgent(Process):
def __init__(self, id, prediction_q, training_q, episode_log_q):
super(ProcessAgent, self).__init__()
self.id = id
self.prediction_q = prediction_q
self.training_q = training_q
self.episode_log_q = episode_log_q
self.env = Environment()
self.num_actions = self.env.get_num_actions()
self.actions = np.arange(self.num_actions)
self.discount_factor = Config.DISCOUNT
# one frame at a time
self.wait_q = Queue(maxsize=1)
self.exit_flag = Value('i', 0)
@staticmethod
def _accumulate_rewards(experiences, discount_factor, terminal_reward):
reward_sum = terminal_reward
for t in reversed(range(0, len(experiences) - 1)):
r = np.clip(experiences[t].reward, Config.REWARD_MIN, Config.REWARD_MAX)
reward_sum = discount_factor * reward_sum + r
experiences[t].reward = reward_sum
return experiences[:-1]
def convert_data(self, experiences):
x_ = np.array([exp.state for exp in experiences])
a_ = np.eye(self.num_actions)[np.array([exp.action for exp in experiences])].astype(np.float32)
r_ = np.array([exp.reward for exp in experiences], dtype=np.float32) # R
r_ = r_.reshape((-1, 1))
return x_, r_, a_
def predict(self, state):
# put the state in the prediction q
self.prediction_q.put((self.id, state))
# wait for the prediction to come back
p, v = self.wait_q.get()
return p, v
def select_action(self, prediction):
if Config.PLAY_MODE:
action = np.argmax(prediction)
else:
action = np.random.choice(self.actions, p=prediction)
return action
def run_episode(self):
self.env.reset()
done = False
experiences = []
time_count = 0
reward_sum = 0.0
while not done:
# very first few frames
if self.env.current_state is None:
self.env.step(0) # 0 == NOOP
continue
prediction, value = self.predict(self.env.current_state)
action = self.select_action(prediction)
reward, done = self.env.step(action)
reward_sum += reward
exp = Experience(self.env.previous_state, action, prediction, reward, done)
experiences.append(exp)
if done or time_count == Config.TIME_MAX:
terminal_reward = 0 if done else value
updated_exps = ProcessAgent._accumulate_rewards(experiences, self.discount_factor, terminal_reward)
x_, r_, a_ = self.convert_data(updated_exps)
yield x_, r_, a_, reward_sum
# reset the tmax count
time_count = 0
# keep the last experience for the next batch
experiences = [experiences[-1]]
reward_sum = 0.0
time_count += 1
def run(self):
# randomly sleep up to 1 second. helps agents boot smoothly.
time.sleep(np.random.rand())
np.random.seed(np.int32(time.time() % 1 * 1000 + self.id * 10))
while self.exit_flag.value == 0:
total_reward = 0
total_length = 0
for x_, r_, a_, reward_sum in self.run_episode():
total_reward += reward_sum
total_length += len(r_) + 1 # +1 for last frame that we drop
self.training_q.put((x_, r_, a_))
self.episode_log_q.put((datetime.now(), total_reward, total_length))
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
import sys
if sys.version_info >= (3, 0):
from queue import Queue as queueQueue
else:
from Queue import Queue as queueQueue
from datetime import datetime
from multiprocessing import Process, Queue, Value
import numpy as np
import time
from Config import Config
class ProcessStats(Process):
def __init__(self):
super(ProcessStats, self).__init__()
self.episode_log_q = Queue(maxsize=100)
self.episode_count = Value('i', 0)
self.training_count = Value('i', 0)
self.should_save_model = Value('i', 0)
self.trainer_count = Value('i', 0)
self.predictor_count = Value('i', 0)
self.agent_count = Value('i', 0)
self.total_frame_count = 0
def FPS(self):
# average FPS from the beginning of the training (not current FPS)
return np.ceil(self.total_frame_count / (time.time() - self.start_time))
def TPS(self):
# average TPS from the beginning of the training (not current TPS)
return np.ceil(self.training_count.value / (time.time() - self.start_time))
def run(self):
with open(Config.RESULTS_FILENAME, 'a') as results_logger:
rolling_frame_count = 0
rolling_reward = 0
results_q = queueQueue(maxsize=Config.STAT_ROLLING_MEAN_WINDOW)
self.start_time = time.time()
first_time = datetime.now()
while True:
episode_time, reward, length = self.episode_log_q.get()
results_logger.write('%s, %d, %d\n' % (episode_time.strftime("%Y-%m-%d %H:%M:%S"), reward, length))
results_logger.flush()
self.total_frame_count += length
self.episode_count.value += 1
rolling_frame_count += length
rolling_reward += reward
if results_q.full():
old_episode_time, old_reward, old_length = results_q.get()
rolling_frame_count -= old_length
rolling_reward -= old_reward
first_time = old_episode_time
results_q.put((episode_time, reward, length))
if self.episode_count.value % Config.SAVE_FREQUENCY == 0:
self.should_save_model.value = 1
if self.episode_count.value % Config.PRINT_STATS_FREQUENCY == 0:
print(
'[Time: %8d] '
'[Episode: %8d Score: %10.4f] '
'[RScore: %10.4f RPPS: %5d] '
'[PPS: %5d TPS: %5d] '
'[NT: %2d NP: %2d NA: %2d]'
% (int(time.time() - self.start_time),
self.episode_count.value, reward,
rolling_reward / results_q.qsize(),
rolling_frame_count / (datetime.now() - first_time).total_seconds(),
self.FPS(), self.TPS(),
self.trainer_count.value, self.predictor_count.value, self.agent_count.value))
sys.stdout.flush()
# GA3C [TinyDragon Style]
This is a Dragon implementation of GA3C comparing to [NVlabs](https://github.com/NVlabs/GA3C) based on TensorFlow.
GA3C is a hybrid CPU/GPU version of the Asynchronous Advantage Actor-Critic (A3C) algorithm.
Currently the state-of-the-art method in reinforcement learning for various gaming tasks.
This CPU/GPU implementation, based on Dragon, achieves a significant speed up compared to a similar CPU implementation.
**```Attention```**: GA3C does not support **Windows**, the hybrid Thread/Process will trigger a deadlock if trainers or predictors >=2.
## How do I get set up? ###
* Install [Dragon](https://github.com/neopenx/Dragon)
* Install [OpenAI Gym](https://github.com/openai/gym)
## How to Train a model from scratch? ###
Run GA3C.
You can modify the training parameters directly in `Config.py`.
The output should look like below:
...
[Time: 33] [Episode: 26 Score: -19.0000] [RScore: -20.5000 RPPS: 822] [PPS: 823 TPS: 183] [NT: 2 NP: 2 NA: 32]
[Time: 33] [Episode: 27 Score: -20.0000] [RScore: -20.4815 RPPS: 855] [PPS: 856 TPS: 183] [NT: 2 NP: 2 NA: 32]
[Time: 35] [Episode: 28 Score: -20.0000] [RScore: -20.4643 RPPS: 854] [PPS: 855 TPS: 185] [NT: 2 NP: 2 NA: 32]
[Time: 35] [Episode: 29 Score: -19.0000] [RScore: -20.4138 RPPS: 877] [PPS: 878 TPS: 185] [NT: 2 NP: 2 NA: 32]
[Time: 36] [Episode: 30 Score: -20.0000] [RScore: -20.4000 RPPS: 899] [PPS: 900 TPS: 186] [NT: 2 NP: 2 NA: 32]
...
**PPS** (predictions per second) demonstrates the speed of processing frames, while **Score** shows the achieved score.
**RPPS** and **RScore** are the rolling average of the above values.
To stop the training procedure, adjuts `EPISODES` in `Config.py` propoerly, or simply use ctrl + c.
## How to continue training a model? ###
If you want to continue training a model, set `LOAD_CHECKPOINTS=True` in `Config.py`.
Set `LOAD_EPISODE` to the episode number you want to load.
Be sure that the corresponding model has been saved in the checkpoints folder (the model name includes the number of the episode).
## How to play a game with a trained agent? ###
set `PLAY_MODE=True` and set `LOAD_EPISODE=xxxx` in `Config.py`
Run GA3C.py
## How to change the game, configurations, etc.? ###
All the configurations are in `Config.py`
## Sample learning curves
Typical learning curves for Pong and Boxing are shown here. These are easily obtained from the results.txt file.
![Convergence Curves](http://mb2.web.engr.illinois.edu/images/pong_boxing.png)
### References ###
If you use this code, please refer to [ICLR 2017 paper](https://openreview.net/forum?id=r1VGvBcxl):
```
@conference{babaeizadeh2017ga3c,
title={Reinforcement Learning thorugh Asynchronous Advantage Actor-Critic on a GPU},
author={Babaeizadeh, Mohammad and Frosio, Iuri and Tyree, Stephen and Clemons, Jason and Kautz, Jan},
booktitle={ICLR},
biurl={https://openreview.net/forum?id=r1VGvBcxl},
year={2017}
}
```
This work was first presented in an oral talk at the [The 1st International Workshop on Efficient Methods for Deep Neural Networks](http://allenai.org/plato/emdnn/papers.html), NIPS Workshop, Barcelona (Spain), Dec. 9, 2016:
```
@article{babaeizadeh2016ga3c,
title={{GA3C:} {GPU}-based {A3C} for Deep Reinforcement Learning},
author={Babaeizadeh, Mohammad and Frosio, Iuri and Tyree, Stephen and Clemons, Jason and Kautz, Jan},
journal={NIPS Workshop},
biurl={arXiv preprint arXiv:1611.06256},
year={2016}
}
```
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from multiprocessing import Queue
import time
from Config import Config
from Environment import Environment
from NetworkVP import NetworkVP
from ProcessAgent import ProcessAgent
from ProcessStats import ProcessStats
from ThreadDynamicAdjustment import ThreadDynamicAdjustment
from ThreadPredictor import ThreadPredictor
from ThreadTrainer import ThreadTrainer
class Server(object):
def __init__(self):
self.stats = ProcessStats()
self.training_q = Queue(maxsize=Config.MAX_QUEUE_SIZE)
self.prediction_q = Queue(maxsize=Config.MAX_QUEUE_SIZE)
self.model = NetworkVP(Config.NETWORK_NAME, Environment().get_num_actions())
if Config.LOAD_CHECKPOINT:
self.stats.episode_count.value = self.model.load()
self.training_step = 0
self.frame_counter = 0
self.agents = []
self.predictors = []
self.trainers = []
self.dynamic_adjustment = ThreadDynamicAdjustment(self)
def add_agent(self):
self.agents.append(
ProcessAgent(len(self.agents), self.prediction_q, self.training_q, self.stats.episode_log_q))
self.agents[-1].start()
def remove_agent(self):
self.agents[-1].exit_flag.value = True
self.agents[-1].join()
self.agents.pop()
def add_predictor(self):
self.predictors.append(ThreadPredictor(self, len(self.predictors)))
self.predictors[-1].start()
def remove_predictor(self):
self.predictors[-1].exit_flag = True
self.predictors[-1].join()
self.predictors.pop()
def add_trainer(self):
self.trainers.append(ThreadTrainer(self, len(self.trainers)))
self.trainers[-1].start()
def remove_trainer(self):
self.trainers[-1].exit_flag = True
self.trainers[-1].join()
self.trainers.pop()
def train_model(self, x_, r_, a_):
self.model.train(x_, r_, a_)
self.training_step += 1
self.frame_counter += x_.shape[0]
self.stats.training_count.value += 1
self.dynamic_adjustment.temporal_training_count += 1
if Config.TENSORBOARD and self.stats.training_count.value % Config.TENSORBOARD_UPDATE_FREQUENCY == 0:
self.model.log(x_, r_, a_)
def save_model(self):
self.model.save(self.stats.episode_count.value)
def main(self):
self.stats.start()
self.dynamic_adjustment.start()
if Config.PLAY_MODE:
for trainer in self.trainers:
trainer.enabled = False
learning_rate_multiplier = (Config.LEARNING_RATE_END - Config.LEARNING_RATE_START) / Config.ANNEALING_EPISODE_COUNT
while self.stats.episode_count.value < Config.EPISODES:
step = min(self.stats.episode_count.value, Config.ANNEALING_EPISODE_COUNT - 1)
self.model.opt.lr = Config.LEARNING_RATE_START + learning_rate_multiplier * step
# Saving is async - even if we start saving at a given episode, we may save the model at a later episode
if Config.SAVE_MODELS and self.stats.should_save_model.value > 0:
self.save_model()
self.stats.should_save_model.value = 0
time.sleep(0.01)
self.dynamic_adjustment.exit_flag = True
while self.agents:
self.remove_agent()
while self.predictors:
self.remove_predictor()
while self.trainers:
self.remove_trainer()
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from threading import Thread
import numpy as np
import time
from Config import Config
class ThreadDynamicAdjustment(Thread):
def __init__(self, server):
super(ThreadDynamicAdjustment, self).__init__()
self.setDaemon(True)
self.server = server
self.enabled = Config.DYNAMIC_SETTINGS
self.trainer_count = Config.TRAINERS
self.predictor_count = Config.PREDICTORS
self.agent_count = Config.AGENTS
self.temporal_training_count = 0
self.exit_flag = False
def enable_disable_components(self):
cur_len = len(self.server.trainers)
if cur_len < self.trainer_count:
for _ in np.arange(cur_len, self.trainer_count):
self.server.add_trainer()
elif cur_len > self.trainer_count:
for _ in np.arange(self.trainer_count, cur_len):
self.server.remove_trainer()
cur_len = len(self.server.predictors)
if cur_len < self.predictor_count:
for _ in np.arange(cur_len, self.predictor_count):
self.server.add_predictor()
elif cur_len > self.predictor_count:
for _ in np.arange(self.predictor_count, cur_len):
self.server.remove_predictor()
cur_len = len(self.server.agents)
if cur_len < self.agent_count:
for _ in np.arange(cur_len, self.agent_count):
self.server.add_agent()
elif cur_len > self.agent_count:
for _ in np.arange(self.agent_count, cur_len):
self.server.remove_agent()
def random_walk(self):
# 3 directions, 1 for Trainers, 1 for Predictors and 1 for Agents
# 3 outcome for each, -1: add one, 0: no change, 1: remove one
direction = np.random.randint(3, size=3) - 1
self.trainer_count = max(1, self.trainer_count - direction[0])
self.predictor_count = max(1, self.predictor_count - direction[1])
self.agent_count = max(1, self.agent_count - direction[2])
def update_stats(self):
self.server.stats.trainer_count.value = self.trainer_count
self.server.stats.predictor_count.value = self.predictor_count
self.server.stats.agent_count.value = self.agent_count
def run(self):
self.enable_disable_components()
self.update_stats()
if not self.enabled: return
# Wait for initialization
time.sleep(Config.DYNAMIC_SETTINGS_INITIAL_WAIT)
while not self.exit_flag:
old_trainer_count, old_predictor_count, old_agent_count = \
self.trainer_count, self.predictor_count, self.agent_count
self.random_walk()
# If no change, do nothing
if self.trainer_count == old_trainer_count \
and self.predictor_count == old_predictor_count \
and self.agent_count == old_agent_count:
continue
old_count = self.temporal_training_count
self.enable_disable_components()
self.temporal_training_count = 0
time.sleep(Config.DYNAMIC_SETTINGS_STEP_WAIT)
cur_count = self.temporal_training_count
# if it didn't work, revert the changes
if cur_count < old_count:
self.trainer_count, self.predictor_count, self.agent_count = \
old_trainer_count, old_predictor_count, old_agent_count
self.update_stats()
\ No newline at end of file
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from threading import Thread
import numpy as np
from Config import Config
class ThreadPredictor(Thread):
def __init__(self, server, id):
super(ThreadPredictor, self).__init__()
self.setDaemon(True)
self.id = id
self.server = server
self.exit_flag = False
def run(self):
ids = np.zeros(Config.PREDICTION_BATCH_SIZE, dtype=np.uint16)
states = np.zeros(
(Config.PREDICTION_BATCH_SIZE, Config.STACKED_FRAMES, Config.IMAGE_HEIGHT, Config.IMAGE_WIDTH, ),
dtype=np.float32)
while not self.exit_flag:
ids[0], states[0] = self.server.prediction_q.get()
size = 1
while size < Config.PREDICTION_BATCH_SIZE and not self.server.prediction_q.empty():
ids[size], states[size] = self.server.prediction_q.get()
size += 1
batch = states[:size]
p, v = self.server.model.predict_p_and_v(batch)
for i in range(size):
if ids[i] < len(self.server.agents):
self.server.agents[ids[i]].wait_q.put((p[i], v[i]))
# --------------------------------------------------------
# GA3C for Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
from threading import Thread
import numpy as np
from Config import Config
class ThreadTrainer(Thread):
def __init__(self, server, id):
super(ThreadTrainer, self).__init__()
self.setDaemon(True)
self.id = id
self.server = server
self.exit_flag = False
def run(self):
while not self.exit_flag:
batch_size = 0
while batch_size <= Config.TRAINING_MIN_BATCH_SIZE:
x_, r_, a_ = self.server.training_q.get()
if batch_size == 0:
x__ = x_
r__ = r_
a__ = a_
else:
x__ = np.concatenate((x__, x_))
r__ = np.concatenate((r__, r_))
a__ = np.concatenate((a__, a_))
batch_size += x_.shape[0]
if Config.TRAIN_MODELS:
self.server.train_model(x__, r__, a__)
\ No newline at end of file
# Dragon Zoo
This page contains various implements for Dragon.
We demonstrate that our framework is much easier to make full use of the works that are already done,
which was described in our arXiv paper: [Dragon: A Computation Graph Virtual Machine Based Deep Learning Framework](https://arxiv.org/abs/1707.08265)
## <a name="list-of-examples"></a>List of examples
* [cifar10](https://github.com/neopenx/Dragon/tree/master/examples/cifar10) - How to train/infer a basic classification network [*Caffe1 Style*]
* [Seg-FCN](https://github.com/neopenx/Dragon/tree/master/examples/Seg-FCN) - Fully Convolutional Networks for Semantic Segmentation [*Caff1 Style*]
* [GA3C](https://github.com/neopenx/Dragon/tree/master/examples/GA3C) - A hybrid CPU/GPU version of the A3C algorithm [*TinyDragon Style*]
# Fully Convolutional Networks for Semantic Segmentation
This is the reference implementation of the models and code for the fully convolutional networks (FCNs) in the [PAMI FCN](https://arxiv.org/abs/1605.06211) and [CVPR FCN](http://www.cv-foundation.org/openaccess/content_cvpr_2015/html/Long_Fully_Convolutional_Networks_2015_CVPR_paper.html) papers:
Fully Convolutional Models for Semantic Segmentation
Evan Shelhamer*, Jonathan Long*, Trevor Darrell
PAMI 2016
arXiv:1605.06211
Fully Convolutional Models for Semantic Segmentation
Jonathan Long*, Evan Shelhamer*, Trevor Darrell
CVPR 2015
arXiv:1411.4038
### Requirements: software
Python packages you might not have: `numpy`, `PIL`, `python-opencv`
### Requirements: hardware
For training the FCN with VGG16 for VOC images(~500x350), 4G of GPU memory is sufficient (using CUDNN)
### Installation (sufficient for the demo)
1. We'll call the directory of Seg-FCN as `FCN_ROOT`
2. Download pre-computed Seg-FCN models
* [FCN-32s PASCAL](http://dl.caffe.berkeleyvision.org/fcn32s-heavy-pascal.caffemodel): single stream, 32 pixel prediction stride net, scoring 63.6 mIU on seg11valid
* [FCN-16s PASCAL](http://dl.caffe.berkeleyvision.org/fcn16s-heavy-pascal.caffemodel): two stream, 16 pixel prediction stride net, scoring 65.0 mIU on seg11valid
* [FCN-8s PASCAL](http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel): three stream, 8 pixel prediction stride net, scoring 65.5 mIU on seg11valid and 67.2 mIU on seg12test
* [FCN-8s PASCAL at-once](http://dl.caffe.berkeleyvision.org/fcn8s-atonce-pascal.caffemodel): all-at-once, three stream, 8 pixel prediction stride net, scoring 65.4 mIU on seg11valid
```Shell
cp fcn8s-heavy-pascal.caffemodel $FCN_ROOT/data/seg_fcn_models
```
These models were trained online with high momentum, using extra data from [Hariharan et al.](http://www.cs.berkeley.edu/~bharath2/codes/SBD/download.html), but excluding SBD val.
FCN-32s is fine-tuned from the [ILSVRC-trained VGG-16 model](https://github.com/BVLC/caffe/wiki/Model-Zoo#models-used-by-the-vgg-team-in-ilsvrc-2014), and the finer strides are then fine-tuned in turn.
The "at-once" FCN-8s is fine-tuned from VGG-16 all-at-once by scaling the skip connections to better condition optimization.
### Demo
*After successfully completing [basic installation](#installation-sufficient-for-the-demo)*, you'll be ready to run the demo.
To run the demo
```Shell
cd $FCN_ROOT
python infer.py
```
The demo performs semantic segmentation using a VGG16 network trained for semantic segmentation on SBDD.
### Beyond the demo: installation for training and testing models
1. Download the SBDD(for training), VOC2011(for testing)
```Shell
wget http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2011/VOCtrainval_25-May-2011.tar
```
2. Extract all of these tars into the $FCN_ROOT/data, should have this basic structure
```Shell
$FCN_ROOT/data/sbdd/dataset
$FCN_ROOT/data/pascal/VOC2011
# ... and several other directories ...
```
3. Follow the next sections to download pre-trained ImageNet models
### Download pre-trained ImageNet models
Pre-trained [ImageNet models](http://pan.baidu.com/s/1eSGLwsE) can be downloaded for backbone net: VGG16.
### Transplant a fully-connected net into a fully-convolution net
```Shell
cp VGG16.v2.caffemodel $FCN_ROOT/transplant/VGG16
cd $FCN_ROOT/transplant/VGG16
python solve.py
```
This script will generate a new model ``VGG16.fcn.caffemodel`` for training.
### Training
FCN prefers two training methods:
1. CVPR version:
First, Train FCN-32s for 1 day.
Then, Train FCN-16s fintune from FCN-32s for 1 day.
Final, Train FCN-8s fintune from FCN-16s for 1 day.
Follow this way, you should run $FCN_ROOT/voc-fcn32s | voc-fcn16s | fcn-8s/solve.py ``sequentially``.
2. PAMI version:
Directly run $FCN_ROOT/voc-fcn8s-atonce/solve.py
Both of above ways train same iterations, ``PAMI ver.`` is simpier and got similar results.
Trained Seg-FCN networks are saved under:
```
voc-fcnxs/snapshot/
```
Test outputs are saved under:
```
voc-fcnxs/segs/
```
No preview for this file type
2007_000033
2007_000042
2007_000061
2007_000123
2007_000129
2007_000175
2007_000187
2007_000323
2007_000332
2007_000346
2007_000452
2007_000464
2007_000491
2007_000529
2007_000559
2007_000572
2007_000629
2007_000636
2007_000661
2007_000663
2007_000676
2007_000727
2007_000762
2007_000783
2007_000799
2007_000804
2007_000830
2007_000837
2007_000847
2007_000862
2007_000925
2007_000999
2007_001154
2007_001175
2007_001239
2007_001284
2007_001288
2007_001289
2007_001299
2007_001311
2007_001321
2007_001377
2007_001408
2007_001423
2007_001430
2007_001457
2007_001458
2007_001526
2007_001568
2007_001585
2007_001586
2007_001587
2007_001594
2007_001630
2007_001677
2007_001678
2007_001717
2007_001733
2007_001761
2007_001763
2007_001774
2007_001884
2007_001955
2007_002046
2007_002094
2007_002119
2007_002132
2007_002260
2007_002266
2007_002268
2007_002284
2007_002376
2007_002378
2007_002387
2007_002400
2007_002412
2007_002426
2007_002427
2007_002445
2007_002470
2007_002539
2007_002565
2007_002597
2007_002618
2007_002619
2007_002624
2007_002643
2007_002648
2007_002719
2007_002728
2007_002823
2007_002824
2007_002852
2007_002903
2007_003011
2007_003020
2007_003022
2007_003051
2007_003088
2007_003101
2007_003106
2007_003110
2007_003131
2007_003134
2007_003137
2007_003143
2007_003169
2007_003188
2007_003194
2007_003195
2007_003201
2007_003349
2007_003367
2007_003373
2007_003499
2007_003503
2007_003506
2007_003530
2007_003571
2007_003587
2007_003611
2007_003621
2007_003682
2007_003711
2007_003714
2007_003742
2007_003786
2007_003841
2007_003848
2007_003861
2007_003872
2007_003917
2007_003957
2007_003991
2007_004033
2007_004052
2007_004112
2007_004121
2007_004143
2007_004189
2007_004190
2007_004193
2007_004241
2007_004275
2007_004281
2007_004380
2007_004392
2007_004405
2007_004468
2007_004483
2007_004510
2007_004538
2007_004558
2007_004644
2007_004649
2007_004712
2007_004722
2007_004856
2007_004866
2007_004902
2007_004969
2007_005058
2007_005074
2007_005107
2007_005114
2007_005149
2007_005173
2007_005281
2007_005294
2007_005296
2007_005304
2007_005331
2007_005354
2007_005358
2007_005428
2007_005460
2007_005469
2007_005509
2007_005547
2007_005600
2007_005608
2007_005626
2007_005689
2007_005696
2007_005705
2007_005759
2007_005803
2007_005813
2007_005828
2007_005844
2007_005845
2007_005857
2007_005911
2007_005915
2007_005978
2007_006028
2007_006035
2007_006046
2007_006076
2007_006086
2007_006117
2007_006171
2007_006241
2007_006260
2007_006277
2007_006348
2007_006364
2007_006373
2007_006444
2007_006449
2007_006549
2007_006553
2007_006560
2007_006647
2007_006678
2007_006680
2007_006698
2007_006761
2007_006802
2007_006837
2007_006841
2007_006864
2007_006866
2007_006946
2007_007007
2007_007084
2007_007109
2007_007130
2007_007165
2007_007168
2007_007195
2007_007196
2007_007203
2007_007211
2007_007235
2007_007341
2007_007414
2007_007417
2007_007470
2007_007477
2007_007493
2007_007498
2007_007524
2007_007534
2007_007624
2007_007651
2007_007688
2007_007748
2007_007795
2007_007810
2007_007815
2007_007818
2007_007836
2007_007849
2007_007881
2007_007996
2007_008051
2007_008084
2007_008106
2007_008110
2007_008204
2007_008222
2007_008256
2007_008260
2007_008339
2007_008374
2007_008415
2007_008430
2007_008543
2007_008547
2007_008596
2007_008645
2007_008670
2007_008708
2007_008722
2007_008747
2007_008802
2007_008815
2007_008897
2007_008944
2007_008964
2007_008973
2007_008980
2007_009015
2007_009068
2007_009084
2007_009088
2007_009096
2007_009221
2007_009245
2007_009251
2007_009252
2007_009258
2007_009320
2007_009323
2007_009331
2007_009346
2007_009392
2007_009413
2007_009419
2007_009446
2007_009458
2007_009521
2007_009562
2007_009592
2007_009654
2007_009655
2007_009684
2007_009687
2007_009691
2007_009706
2007_009750
2007_009756
2007_009764
2007_009794
2007_009817
2007_009841
2007_009897
2007_009911
2007_009923
2007_009938
2008_000073
2008_000075
2008_000107
2008_000123
2008_000149
2008_000213
2008_000215
2008_000223
2008_000233
2008_000239
2008_000271
2008_000345
2008_000391
2008_000401
2008_000501
2008_000533
2008_000573
2008_000589
2008_000657
2008_000661
2008_000725
2008_000731
2008_000763
2008_000765
2008_000811
2008_000853
2008_000911
2008_000919
2008_000943
2008_001135
2008_001231
2008_001249
2008_001379
2008_001433
2008_001439
2008_001513
2008_001531
2008_001547
2008_001715
2008_001821
2008_001885
2008_001971
2008_002043
2008_002205
2008_002239
2008_002269
2008_002273
2008_002379
2008_002383
2008_002467
2008_002521
2008_002623
2008_002681
2008_002775
2008_002835
2008_002859
2008_003105
2008_003135
2008_003155
2008_003369
2008_003709
2008_003777
2008_003821
2008_003885
2008_004069
2008_004172
2008_004175
2008_004279
2008_004339
2008_004345
2008_004363
2008_004453
2008_004562
2008_004575
2008_004621
2008_004659
2008_004705
2008_004995
2008_005049
2008_005097
2008_005105
2008_005145
2008_005217
2008_005262
2008_005439
2008_005525
2008_005633
2008_005637
2008_005691
2008_006055
2008_006229
2008_006327
2008_006553
2008_006835
2008_007025
2008_007031
2008_007123
2008_007497
2008_007677
2008_007797
2008_007811
2008_008051
2008_008103
2008_008301
2009_000013
2009_000022
2009_000032
2009_000037
2009_000039
2009_000087
2009_000121
2009_000149
2009_000201
2009_000205
2009_000219
2009_000335
2009_000351
2009_000387
2009_000391
2009_000446
2009_000455
2009_000457
2009_000469
2009_000487
2009_000523
2009_000619
2009_000641
2009_000675
2009_000705
2009_000723
2009_000727
2009_000771
2009_000845
2009_000879
2009_000919
2009_000931
2009_000935
2009_000989
2009_000991
2009_001255
2009_001299
2009_001333
2009_001363
2009_001391
2009_001411
2009_001433
2009_001505
2009_001535
2009_001565
2009_001607
2009_001663
2009_001683
2009_001687
2009_001731
2009_001775
2009_001851
2009_001941
2009_002035
2009_002165
2009_002171
2009_002221
2009_002291
2009_002295
2009_002317
2009_002445
2009_002487
2009_002521
2009_002527
2009_002535
2009_002539
2009_002549
2009_002571
2009_002573
2009_002591
2009_002635
2009_002649
2009_002651
2009_002727
2009_002749
2009_002753
2009_002771
2009_002887
2009_002975
2009_003003
2009_003005
2009_003059
2009_003063
2009_003065
2009_003071
2009_003105
2009_003123
2009_003193
2009_003269
2009_003273
2009_003311
2009_003323
2009_003343
2009_003387
2009_003481
2009_003517
2009_003523
2009_003549
2009_003551
2009_003589
2009_003607
2009_003703
2009_003707
2009_003771
2009_003849
2009_003857
2009_003895
2009_004021
2009_004033
2009_004043
2009_004099
2009_004125
2009_004217
2009_004255
2009_004455
2009_004507
2009_004509
2009_004579
2009_004581
2009_004687
2009_004801
2009_004859
2009_004867
2009_004895
2009_004969
2009_004993
2009_005087
2009_005089
2009_005137
2009_005189
2009_005217
2009_005219
2010_000003
2010_000065
2010_000083
2010_000159
2010_000163
2010_000309
2010_000427
2010_000559
2010_000573
2010_000639
2010_000683
2010_000907
2010_000961
2010_001017
2010_001061
2010_001069
2010_001149
2010_001151
2010_001251
2010_001313
2010_001327
2010_001331
2010_001553
2010_001557
2010_001563
2010_001577
2010_001579
2010_001767
2010_001773
2010_001851
2010_001995
2010_002017
2010_002025
2010_002137
2010_002147
2010_002161
2010_002271
2010_002305
2010_002361
2010_002531
2010_002623
2010_002693
2010_002701
2010_002763
2010_002921
2010_002929
2010_002939
2010_003123
2010_003187
2010_003207
2010_003239
2010_003275
2010_003325
2010_003365
2010_003381
2010_003409
2010_003453
2010_003473
2010_003495
2010_003531
2010_003547
2010_003675
2010_003781
2010_003813
2010_003915
2010_003971
2010_004041
2010_004063
2010_004149
2010_004165
2010_004219
2010_004355
2010_004419
2010_004479
2010_004529
2010_004543
2010_004551
2010_004559
2010_004697
2010_004763
2010_004783
2010_004795
2010_004815
2010_004825
2010_005013
2010_005021
2010_005063
2010_005159
2010_005187
2010_005245
2010_005305
2010_005421
2010_005531
2010_005705
2010_005709
2010_005719
2010_005727
2010_005871
2010_005877
2010_005899
2010_005991
2011_000045
2011_000051
2011_000173
2011_000185
2011_000291
2011_000419
2011_000435
2011_000455
2011_000479
2011_000503
2011_000521
2011_000536
2011_000598
2011_000607
2011_000661
2011_000669
2011_000747
2011_000789
2011_000809
2011_000843
2011_000969
2011_001069
2011_001071
2011_001161
2011_001263
2011_001281
2011_001287
2011_001313
2011_001341
2011_001421
2011_001447
2011_001529
2011_001567
2011_001589
2011_001597
2011_001601
2011_001607
2011_001613
2011_001619
2011_001665
2011_001669
2011_001713
2011_001745
2011_001775
2011_001793
2011_001812
2011_001868
2011_001984
2011_002041
2011_002121
2011_002223
2011_002279
2011_002295
2011_002317
2011_002327
2011_002343
2011_002371
2011_002379
2011_002391
2011_002509
2011_002535
2011_002575
2011_002589
2011_002623
2011_002641
2011_002675
2011_002685
2011_002713
2011_002863
2011_002929
2011_002993
2011_002997
2011_003011
2011_003055
2011_003085
2011_003145
2011_003197
2011_003271
\ No newline at end of file
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Source Code by Evan Shelhamer
# Re-Written by Ting Pan
# --------------------------------------------------------
""" Infer for a single Image and show """
import numpy as np
from PIL import Image
import dragon.vm.caffe as caffe
import dragon.core.workspace as ws
import os
import cv2
# init
caffe.set_mode_gpu()
# load net
net = caffe.Net('voc-fcn8s/deploy.prototxt', 'data/seg_fcn_models/fcn8s-heavy-pascal.caffemodel', caffe.TEST)
# load color table
color_table = np.fromfile('colors/pascal_voc.act', dtype=np.uint8)
def load_image(file):
# load image, switch to BGR, subtract mean, and make dims C x H x W for Caffe
im = Image.open(file)
in_ = np.array(im, dtype=np.float32)
in_ = in_[:,:,::-1]
in_ -= np.array((104.00698793,116.66876762,122.67891434))
in_ = in_.transpose((2,0,1))
return in_
def seg(file, save_dir="data/seg_results", mix=True, show=True):
if save_dir is not None:
if not os.path.exists(save_dir):
os.makedirs(save_dir)
im = load_image(file)
# shape for input (data blob is N x C x H x W), set data
im = im.reshape(1, *im.shape)
ws.FeedTensor(net.blobs['data'].data, im)
# run net and take argmax for prediction
net.forward()
if save_dir is not None:
filename_ext = file.split('/')[-1]
filename = filename_ext.split('.')[-2]
filepath = os.path.join(save_dir, filename + '.png')
mat = ws.FetchTensor(net.blobs['score'].data)
im = Image.fromarray(mat[0].argmax(0).astype(np.uint8), mode='P')
im.putpalette(color_table)
im.save(filepath)
if show:
if mix:
show1 = cv2.imread(file)
show2 = cv2.imread(filepath)
show3 = cv2.addWeighted(show1, 0.7, show2, 0.5, 1)
else: show3 = cv2.imread(filepath)
cv2.imshow('Seg-FCN', show3)
cv2.waitKey(0)
if __name__ == '__main__':
seg('data/demo/001763.jpg')
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Source Code by Evan Shelhamer
# Re-Written by Ting Pan
# --------------------------------------------------------
from __future__ import division
import dragon.core.workspace as ws
import numpy as np
import os
from datetime import datetime
from PIL import Image
color_table = np.fromfile('../colors/pascal_voc.act', dtype=np.uint8)
def fast_hist(a, b, n):
k = (a >= 0) & (a < n)
return np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n)
def compute_hist(net, save_dir, dataset, layer='score', gt='label'):
n_cl = hist = None
loss = 0
for idx in dataset:
net.forward()
gt_mat = ws.FetchTensor(net.blobs[gt].data)
layer_mat = ws.FetchTensor(net.blobs[layer].data)
loss_mat = ws.FetchTensor(net.blobs['loss'].data)
if n_cl is None: n_cl = layer_mat.shape[1]
if hist is None: hist = np.zeros((n_cl, n_cl))
hist += fast_hist(gt_mat[0, 0].flatten(),
layer_mat[0].argmax(0).flatten(), n_cl)
if save_dir:
im = Image.fromarray(layer_mat[0].argmax(0).astype(np.uint8), mode='P')
im.putpalette(color_table)
im.save(os.path.join(save_dir, idx + '.png'))
# compute the loss as well
loss += loss_mat.flat[0]
return hist, loss / len(dataset)
def seg_tests(solver, save_format, dataset, layer='score', gt='label'):
print '>>>', datetime.now(), 'Begin seg tests'
solver.test_nets[0].share_with(solver.net)
do_seg_tests(solver.test_nets[0], solver.iter, save_format, dataset, layer, gt)
def do_seg_tests(net, iter, save_format, dataset, layer='score', gt='label'):
if save_format:
save_format = save_format.format(iter)
if not os.path.exists(save_format): os.makedirs(save_format)
hist, loss = compute_hist(net, save_format, dataset, layer, gt)
# mean loss
print '>>>', datetime.now(), 'Iteration', iter, 'loss', loss
# overall accuracy
acc = np.diag(hist).sum() / hist.sum()
print '>>>', datetime.now(), 'Iteration', iter, 'overall accuracy', acc
# per-class accuracy
acc = np.diag(hist) / hist.sum(1)
print '>>>', datetime.now(), 'Iteration', iter, 'mean accuracy', np.nanmean(acc)
# per-class IU
iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))
print '>>>', datetime.now(), 'Iteration', iter, 'mean IU', np.nanmean(iu)
freq = hist.sum(1) / hist.sum()
print '>>>', datetime.now(), 'Iteration', iter, 'fwavacc', \
(freq[freq > 0] * iu[freq > 0]).sum()
return hist
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Source Code by Evan Shelhamer
# Re-Written by Ting Pan
# --------------------------------------------------------
from __future__ import division
import dragon.core.workspace as ws
import numpy as np
def transplant(new_net, net):
# create graph
net.function()
new_net.function()
for p in net.params:
if p not in new_net.params:
print 'dropping', p
continue
for i in range(len(net.params[p])):
if i > (len(new_net.params[p]) - 1):
print 'dropping', p, i
break
print 'copying', p, i
net_param = ws.FetchTensor(net.params[p][i].data)
new_net_param = ws.FetchTensor(new_net.params[p][i].data)
name = new_net.params[p][i].data._name
if net_param.shape != new_net_param.shape:
print 'coercing', p, i, 'from', net_param.shape, 'to', new_net_param.shape
else:
pass
new_net_param.flat = new_net_param.flat
ws.FeedTensor(name, new_net_param)
def upsample_filt(size):
factor = (size + 1) // 2
if size % 2 == 1:
center = factor - 1
else:
center = factor - 0.5
og = np.ogrid[:size, :size]
return (1 - abs(og[0] - center) / factor) * \
(1 - abs(og[1] - center) / factor)
def interp(net, layers):
print 'bilinear-interp for layers:', layers
net.forward() # dragon must forward once to create weights
for l in layers:
net_param = ws.FetchTensor(net.params[l][0].data)
m, k, h, w = net_param.shape
if m != k and k != 1:
print 'input + output channels need to be the same or |output| == 1'
raise
if h != w:
print 'filters need to be square'
raise
filt = upsample_filt(h)
net_param[range(m), range(k), :, :] = filt
ws.FeedTensor(net.params[l][0].data._name, net_param)
input: "data"
input_shape {
dim: 1
dim: 3
dim: 224
dim: 224
}
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "InnerProduct"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 4096
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
}
}
\ No newline at end of file
input: "data"
input_shape {
dim: 1
dim: 3
dim: 224
dim: 224
}
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
}
}
\ No newline at end of file
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
""" Transplant fully-connected caffemodel into fully-convolution ver. """
import surgery
import dragon.vm.caffe as caffe
if __name__ == '__main__':
net = caffe.Net('net.prototxt', 'VGG16.v2.caffemodel', caffe.TEST)
new_net = caffe.Net('new_net.prototxt', caffe.TEST)
surgery.transplant(new_net, net)
new_net.save('VGG16.fcn.caffemodel')
\ No newline at end of file
http://dl.caffe.berkeleyvision.org/fcn16s-heavy-pascal.caffemodel
\ No newline at end of file
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Source Code by Evan Shelhamer
# Re-Written by Ting Pan
# --------------------------------------------------------
import dragon.vm.caffe as caffe
from dragon.vm.caffe import layers as L, params as P
from dragon.vm.caffe.coord_map import crop
def conv_relu(bottom, nout, ks=3, stride=1, pad=1):
conv = L.Convolution(bottom, kernel_size=ks, stride=stride,
num_output=nout, pad=pad,
param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)])
return conv, L.ReLU(conv, in_place=True)
def max_pool(bottom, ks=2, stride=2):
return L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride)
def fcn(split):
n = caffe.NetSpec()
pydata_params = dict(split=split, mean=(104.00699, 116.66877, 122.67892),
seed=1337)
if split == 'train':
pydata_params['sbdd_dir'] = './data/sbdd/dataset'
pylayer = 'SBDDSegDataLayer'
else:
pydata_params['voc_dir'] = '../data/pascal/VOC2011'
pylayer = 'VOCSegDataLayer'
n.data, n.label = L.Python(module='voc_layers', layer=pylayer,
ntop=2, param_str=str(pydata_params))
# the base net
n.conv1_1, n.relu1_1 = conv_relu(n.data, 64, pad=100)
n.conv1_2, n.relu1_2 = conv_relu(n.relu1_1, 64)
n.pool1 = max_pool(n.relu1_2)
n.conv2_1, n.relu2_1 = conv_relu(n.pool1, 128)
n.conv2_2, n.relu2_2 = conv_relu(n.relu2_1, 128)
n.pool2 = max_pool(n.relu2_2)
n.conv3_1, n.relu3_1 = conv_relu(n.pool2, 256)
n.conv3_2, n.relu3_2 = conv_relu(n.relu3_1, 256)
n.conv3_3, n.relu3_3 = conv_relu(n.relu3_2, 256)
n.pool3 = max_pool(n.relu3_3)
n.conv4_1, n.relu4_1 = conv_relu(n.pool3, 512)
n.conv4_2, n.relu4_2 = conv_relu(n.relu4_1, 512)
n.conv4_3, n.relu4_3 = conv_relu(n.relu4_2, 512)
n.pool4 = max_pool(n.relu4_3)
n.conv5_1, n.relu5_1 = conv_relu(n.pool4, 512)
n.conv5_2, n.relu5_2 = conv_relu(n.relu5_1, 512)
n.conv5_3, n.relu5_3 = conv_relu(n.relu5_2, 512)
n.pool5 = max_pool(n.relu5_3)
# fully conv
n.fc6, n.relu6 = conv_relu(n.pool5, 4096, ks=7, pad=0)
n.drop6 = L.Dropout(n.relu6, dropout_ratio=0.5, in_place=True)
n.fc7, n.relu7 = conv_relu(n.drop6, 4096, ks=1, pad=0)
n.drop7 = L.Dropout(n.relu7, dropout_ratio=0.5, in_place=True)
n.score_fr = L.Convolution(n.drop7, num_output=21, kernel_size=1, pad=0,
param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)])
n.upscore2 = L.Deconvolution(n.score_fr,
convolution_param=dict(num_output=21, kernel_size=4, stride=2,
bias_term=False),
param=[dict(lr_mult=0)])
n.score_pool4 = L.Convolution(n.pool4, num_output=21, kernel_size=1, pad=0,
param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)])
n.score_pool4c = crop(n.score_pool4, n.upscore2)
n.fuse_pool4 = L.Eltwise(n.upscore2, n.score_pool4c,
operation=P.Eltwise.SUM)
n.upscore16 = L.Deconvolution(n.fuse_pool4,
convolution_param=dict(num_output=21, kernel_size=32, stride=16,
bias_term=False),
param=[dict(lr_mult=0)])
n.score = crop(n.upscore16, n.data)
n.loss = L.SoftmaxWithLoss(n.score, n.label,
loss_param=dict(normalize=False, ignore_label=255))
return n.to_proto()
def make_net():
with open('train.prototxt', 'w') as f:
f.write(str(fcn('train')))
with open('val.prototxt', 'w') as f:
f.write(str(fcn('seg11valid')))
if __name__ == '__main__':
make_net()
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
""" Train a FCN-16s(PASCAL VOC) network """
import dragon.vm.caffe as caffe
import surgery
weights = '../voc-fcn32s/snapshot/train_iter_100000.caffemodel'
if __name__ == '__main__':
# init
caffe.set_mode_gpu()
caffe.set_device(0)
solver = caffe.SGDSolver('solver.prototxt')
solver.net.copy_from(weights)
# surgeries
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
surgery.interp(solver.net, interp_layers)
for _ in range(25):
solver.step(4000)
\ No newline at end of file
train_net: "train.prototxt"
test_net: "val.prototxt"
test_iter: 1111
# make test net, but don't invoke it from the solver itself
test_interval: 999999999
display: 20
average_loss: 20
lr_policy: "fixed"
# lr for unnormalized softmax
base_lr: 1e-12
# high momentum
momentum: 0.99
# no gradient accumulation
iter_size: 1
max_iter: 100000
weight_decay: 0.0005
snapshot: 4000
snapshot_prefix: "snapshot/train"
test_initialization: false
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
""" Test a FCN-16s(PASCAL VOC) network """
import dragon.vm.caffe as caffe
import score
import numpy as np
weights = 'snapshot/train_iter_44000.caffemodel'
if __name__ == '__main__':
# init
caffe.set_mode_gpu()
caffe.set_device(0)
solver = caffe.SGDSolver('solver.prototxt')
solver.net.copy_from(weights)
# scoring
val = np.loadtxt('../data/seg11valid.txt', dtype=str)
score.seg_tests(solver, 'seg', val)
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "voc_layers"
layer: "SBDDSegDataLayer"
param_str: "{\'sbdd_dir\': \'./data/sbdd/dataset\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 116.66877, 122.67892)}"
}
}
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "score_fr"
type: "Convolution"
bottom: "fc7"
top: "score_fr"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "upscore2"
type: "Deconvolution"
bottom: "score_fr"
top: "upscore2"
param {
lr_mult: 0.0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 4
stride: 2
}
}
layer {
name: "score_pool4"
type: "Convolution"
bottom: "pool4"
top: "score_pool4"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "score_pool4c"
type: "Crop"
bottom: "score_pool4"
bottom: "upscore2"
top: "score_pool4c"
crop_param {
axis: 2
offset: 5
}
}
layer {
name: "fuse_pool4"
type: "Eltwise"
bottom: "upscore2"
bottom: "score_pool4c"
top: "fuse_pool4"
eltwise_param {
operation: SUM
}
}
layer {
name: "upscore16"
type: "Deconvolution"
bottom: "fuse_pool4"
top: "upscore16"
param {
lr_mult: 0.0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 32
stride: 16
}
}
layer {
name: "score"
type: "Crop"
bottom: "upscore16"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 27
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "score"
bottom: "label"
top: "loss"
loss_param {
ignore_label: 255
normalize: false
}
}
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "voc_layers"
layer: "VOCSegDataLayer"
param_str: "{\'voc_dir\': \'../data/pascal/VOC2011\', \'seed\': 1337, \'split\': \'seg11valid\', \'mean\': (104.00699, 116.66877, 122.67892)}"
}
}
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "score_fr"
type: "Convolution"
bottom: "fc7"
top: "score_fr"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "upscore2"
type: "Deconvolution"
bottom: "score_fr"
top: "upscore2"
param {
lr_mult: 0.0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 4
stride: 2
}
}
layer {
name: "score_pool4"
type: "Convolution"
bottom: "pool4"
top: "score_pool4"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "score_pool4c"
type: "Crop"
bottom: "score_pool4"
bottom: "upscore2"
top: "score_pool4c"
crop_param {
axis: 2
offset: 5
}
}
layer {
name: "fuse_pool4"
type: "Eltwise"
bottom: "upscore2"
bottom: "score_pool4c"
top: "fuse_pool4"
eltwise_param {
operation: SUM
}
}
layer {
name: "upscore16"
type: "Deconvolution"
bottom: "fuse_pool4"
top: "upscore16"
param {
lr_mult: 0.0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 32
stride: 16
}
}
layer {
name: "score"
type: "Crop"
bottom: "upscore16"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 27
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "score"
bottom: "label"
top: "loss"
loss_param {
ignore_label: 255
normalize: false
}
}
http://dl.caffe.berkeleyvision.org/fcn32s-heavy-pascal.caffemodel
\ No newline at end of file
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Source Code by Evan Shelhamer
# Re-Written by Ting Pan
# --------------------------------------------------------
import dragon.vm.caffe as caffe
from dragon.vm.caffe import layers as L, params as P
from dragon.vm.caffe.coord_map import crop
def conv_relu(bottom, nout, ks=3, stride=1, pad=1):
conv = L.Convolution(bottom, kernel_size=ks, stride=stride,
num_output=nout, pad=pad,
param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)])
return conv, L.ReLU(conv, in_place=True)
def max_pool(bottom, ks=2, stride=2):
return L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride)
def fcn(split):
n = caffe.NetSpec()
pydata_params = dict(split=split, mean=(104.00699, 116.66877, 122.67892),
seed=1337)
if split == 'train':
pydata_params['sbdd_dir'] = '../data/sbdd/dataset'
pylayer = 'SBDDSegDataLayer'
else:
pydata_params['voc_dir'] = '../data/pascal/VOC2011'
pylayer = 'VOCSegDataLayer'
n.data, n.label = L.Python(module='voc_layers', layer=pylayer,
ntop=2, param_str=str(pydata_params))
# the base net
n.conv1_1, n.relu1_1 = conv_relu(n.data, 64, pad=100)
n.conv1_2, n.relu1_2 = conv_relu(n.relu1_1, 64)
n.pool1 = max_pool(n.relu1_2)
n.conv2_1, n.relu2_1 = conv_relu(n.pool1, 128)
n.conv2_2, n.relu2_2 = conv_relu(n.relu2_1, 128)
n.pool2 = max_pool(n.relu2_2)
n.conv3_1, n.relu3_1 = conv_relu(n.pool2, 256)
n.conv3_2, n.relu3_2 = conv_relu(n.relu3_1, 256)
n.conv3_3, n.relu3_3 = conv_relu(n.relu3_2, 256)
n.pool3 = max_pool(n.relu3_3)
n.conv4_1, n.relu4_1 = conv_relu(n.pool3, 512)
n.conv4_2, n.relu4_2 = conv_relu(n.relu4_1, 512)
n.conv4_3, n.relu4_3 = conv_relu(n.relu4_2, 512)
n.pool4 = max_pool(n.relu4_3)
n.conv5_1, n.relu5_1 = conv_relu(n.pool4, 512)
n.conv5_2, n.relu5_2 = conv_relu(n.relu5_1, 512)
n.conv5_3, n.relu5_3 = conv_relu(n.relu5_2, 512)
n.pool5 = max_pool(n.relu5_3)
# fully conv
n.fc6, n.relu6 = conv_relu(n.pool5, 4096, ks=7, pad=0)
n.drop6 = L.Dropout(n.relu6, dropout_ratio=0.5, in_place=True)
n.fc7, n.relu7 = conv_relu(n.drop6, 4096, ks=1, pad=0)
n.drop7 = L.Dropout(n.relu7, dropout_ratio=0.5, in_place=True)
n.score_fr = L.Convolution(n.drop7, num_output=21, kernel_size=1, pad=0,
param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)])
n.upscore = L.Deconvolution(n.score_fr,
convolution_param=dict(num_output=21, kernel_size=64, stride=32,
bias_term=False),
param=[dict(lr_mult=0)])
n.score = crop(n.upscore, n.data)
n.loss = L.SoftmaxWithLoss(n.score, n.label,
loss_param=dict(normalize=False, ignore_label=255))
return n.to_proto()
def make_net():
with open('train.prototxt', 'w') as f:
f.write(str(fcn('train')))
with open('val.prototxt', 'w') as f:
f.write(str(fcn('seg11valid')))
if __name__ == '__main__':
make_net()
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
""" Train a FCN-32s(PASCAL VOC) network """
import dragon.vm.caffe as caffe
import surgery
import numpy as np
weights = '../transplants/VGG16/VGG16.fcn.caffemodel'
if __name__ == '__main__':
# init
caffe.set_mode_gpu()
caffe.set_device(0)
solver = caffe.SGDSolver('solver.prototxt')
solver.net.copy_from(weights)
# surgeries
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
surgery.interp(solver.net, interp_layers)
for _ in range(25):
solver.step(4000)
\ No newline at end of file
train_net: "train.prototxt"
test_net: "val.prototxt"
test_iter: 1111
# make test net, but don't invoke it from the solver itself
test_interval: 999999999
display: 20
average_loss: 20
lr_policy: "fixed"
# lr for unnormalized softmax
base_lr: 1e-10
# high momentum
momentum: 0.99
# no gradient accumulation
iter_size: 1
max_iter: 100000
weight_decay: 0.0005
snapshot: 4000
snapshot_prefix: "snapshot/train"
test_initialization: false
# --------------------------------------------------------
# Seg-FCN for Dragon
# Copyright (c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------
""" Test a FCN-32s(PASCAL VOC) network """
import dragon.vm.caffe as caffe
import score
import numpy as np
weights = 'snapshot/train_iter_100000.caffemodel'
if __name__ == '__main__':
# init
caffe.set_mode_gpu()
caffe.set_device(0)
solver = caffe.SGDSolver('solver.prototxt')
solver.net.copy_from(weights)
# scoring
val = np.loadtxt('../data/seg11valid.txt', dtype=str)
score.seg_tests(solver, 'seg', val)
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "voc_layers"
layer: "SBDDSegDataLayer"
param_str: "{\'sbdd_dir\': \'../data/sbdd/dataset\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 116.66877, 122.67892)}"
}
}
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "score_fr"
type: "Convolution"
bottom: "fc7"
top: "score_fr"
param {
lr_mult: 1.0
decay_mult: 1.0
}
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "upscore"
type: "Deconvolution"
bottom: "score_fr"
top: "upscore"
param {
lr_mult: 0.0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 64
stride: 32
}
}
layer {
name: "score"
type: "Crop"
bottom: "upscore"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 19
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "score"
bottom: "label"
top: "loss"
loss_param {
ignore_label: 255
normalize: false
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!