2016-04-11 45 views
18

Có chức năng gốc TensorFlow không chia sẻ cho mạng Deconvolutional không?TensorFlow: Unpooling

Tôi đã viết điều này bằng python bình thường, nhưng nó trở nên phức tạp khi muốn dịch nó sang TensorFlow vì nó không hỗ trợ gán mục vào lúc này, và tôi nghĩ đây là một sự bất tiện lớn với TF.

+2

Tò mò, bạn có thể đăng những gì Python bình thường của bạn trông như thế nào cho deconv? (có lẽ tôi có thể thấy một cách TF tốt hơn) –

Trả lời

12

Tôi không nghĩ rằng có một lớp chung chưa chính thức nào gây phiền toái bởi vì bạn phải sử dụng thay đổi kích thước hình ảnh (nội suy song tuyến hoặc hàng xóm gần nhất) giống như hoạt động bình thường và nó chậm. Nhìn vào tf api trong phần 'hình ảnh' và bạn sẽ tìm thấy nó. Lưu lượng có một maxpooling_with_argmax điều mà bạn có được bạn maxpooled đầu ra cũng như kích hoạt bản đồ đó là tốt đẹp như bạn có thể sử dụng nó trong một unpooling lớp để bảo vệ 'bị mất' spacial thông tin nhưng có vẻ như không có như vậy một hoạt động không có hoạt động. Tôi đoán rằng họ đang có kế hoạch để thêm nó ... sớm.

Chỉnh sửa: Tôi đã tìm thấy một số người trên google thảo luận cách đây một tuần dường như đã triển khai một cái gì đó như thế này nhưng cá nhân tôi chưa thử. https://github.com/ppwwyyxx/tensorpack/blob/master/tensorpack/models/pool.py#L66

6

Tôi đang tìm kiếm hoạt động unpooling tối đa và cố gắng triển khai. Tôi đã đưa ra một số loại hacky implementation for the gradient, như tôi đã đấu tranh với CUDA.

Mã là here, bạn sẽ cần tạo mã từ nguồn có hỗ trợ GPU. Dưới đây là một ứng dụng demo. Không có bảo đảm, mặc dù!

Cũng tồn tại một open issue cho thao tác này.

import tensorflow as tf 
import numpy as np 

def max_pool(inp, k=2): 
    return tf.nn.max_pool_with_argmax_and_mask(inp, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding="SAME") 

def max_unpool(inp, argmax, argmax_mask, k=2): 
    return tf.nn.max_unpool(inp, argmax, argmax_mask, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding="SAME") 

def conv2d(inp, name): 
    w = weights[name] 
    b = biases[name] 
    var = tf.nn.conv2d(inp, w, [1, 1, 1, 1], padding='SAME') 
    var = tf.nn.bias_add(var, b) 
    var = tf.nn.relu(var) 
    return var 

def conv2d_transpose(inp, name, dropout_prob): 
    w = weights[name] 
    b = biases[name] 

    dims = inp.get_shape().dims[:3] 
    dims.append(w.get_shape()[-2]) # adpot channels from weights (weight definition for deconv has switched input and output channel!) 
    out_shape = tf.TensorShape(dims) 

    var = tf.nn.conv2d_transpose(inp, w, out_shape, strides=[1, 1, 1, 1], padding="SAME") 
    var = tf.nn.bias_add(var, b) 
    if not dropout_prob is None: 
     var = tf.nn.relu(var) 
     var = tf.nn.dropout(var, dropout_prob) 
    return var 


weights = { 
    "conv1": tf.Variable(tf.random_normal([3, 3, 3, 16])), 
    "conv2": tf.Variable(tf.random_normal([3, 3, 16, 32])), 
    "conv3": tf.Variable(tf.random_normal([3, 3, 32, 32])), 
    "deconv2": tf.Variable(tf.random_normal([3, 3, 16, 32])), 
    "deconv1": tf.Variable(tf.random_normal([3, 3, 1, 16])) } 

biases = { 
    "conv1": tf.Variable(tf.random_normal([16])), 
    "conv2": tf.Variable(tf.random_normal([32])), 
    "conv3": tf.Variable(tf.random_normal([32])), 
    "deconv2": tf.Variable(tf.random_normal([16])), 
    "deconv1": tf.Variable(tf.random_normal([ 1])) } 


## Build Miniature CEDN 
x = tf.placeholder(tf.float32, [12, 20, 20, 3]) 
y = tf.placeholder(tf.float32, [12, 20, 20, 1]) 
p = tf.placeholder(tf.float32) 

conv1         = conv2d(x, "conv1") 
maxp1, maxp1_argmax, maxp1_argmax_mask = max_pool(conv1) 

conv2         = conv2d(maxp1, "conv2") 
maxp2, maxp2_argmax, maxp2_argmax_mask = max_pool(conv2) 

conv3         = conv2d(maxp2, "conv3") 

maxup2         = max_unpool(conv3, maxp2_argmax, maxp2_argmax_mask) 
deconv2         = conv2d_transpose(maxup2, "deconv2", p) 

maxup1         = max_unpool(deconv2, maxp1_argmax, maxp1_argmax_mask) 
deconv1         = conv2d_transpose(maxup1, "deconv1", None) 


## Optimizing Stuff 
loss  = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(deconv1, y)) 
optimizer = tf.train.AdamOptimizer(learning_rate=1).minimize(loss) 


## Test Data 
np.random.seed(123) 
batch_x = np.where(np.random.rand(12, 20, 20, 3) > 0.5, 1.0, -1.0) 
batch_y = np.where(np.random.rand(12, 20, 20, 1) > 0.5, 1.0, 0.0) 
prob = 0.5 


with tf.Session() as session: 
    tf.set_random_seed(123) 
    session.run(tf.initialize_all_variables()) 

    print "\n\n" 
    for i in range(10): 
     session.run(optimizer, feed_dict={x: batch_x, y: batch_y, p: prob}) 
     print "step", i + 1 
     print "loss", session.run(loss, feed_dict={x: batch_x, y: batch_y, p: 1.0}), "\n\n" 

Sửa 29.11.17

Một số thời gian trở lại, tôi reimplemented nó trong một thời trang sạch chống TensorFlow 1.0, các hoạt động về phía trước cũng có sẵn như CPU-phiên bản. Bạn có thể tìm thấy nó in this branch, tôi khuyên bạn nên tìm kiếm một vài cam kết cuối cùng nếu bạn muốn sử dụng nó.

+0

bạn không cần phải có một 'conv2d_transpose (conv3," deconv3 ")' trước 'maxup2 = max_unpool (conv3, maxp2_argmax, maxp2_argmax_mask)'? –

+0

@RoxanaIstrate Tôi đoán bạn sẽ làm điều đó, nếu đó là một mô hình cedn thực sự. Trong priniciple bạn có thể cắm bất cứ điều gì phù hợp với kích thước lớp của phần unpooling trong đó. Ví dụ đã được nhiều hơn để chứng minh các khớp nối của pooling và unpooling. – jns

6

Có một vài hiện thực đây WhatWhereAutoencoder.py

Cụ thể:

1) hoạt động unpool (source) mà sử dụng đầu ra của tf.nn.max_pool_with_argmax. Mặc dù xin lưu ý rằng điều đó xảy ra với lưu lượng là 1. 2) hoạt động upsample bắt chước nghịch đảo của max-pooling bằng cách điền các vị trí của vùng không được chia sẻ với số không hoặc bản sao của phần tử tối đa. So sánh với tensorpack nó cho phép sao chép các phần tử thay vì số không và hỗ trợ các bước tiến khác ngoài [2, 2].

Không biên dịch lại, chống lưng thân thiện.

Minh họa: Upsampling

Unpooling