2016-12-15 23 views
11

Tôi muốn làm một cái gì đó tương tự như giấy Hoàn toàn mạng lưới liên kết (https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn.pdf) bằng cách sử dụng Keras. Tôi có một mạng lưới kết thúc bằng việc làm phẳng các bản đồ tính năng và chạy chúng qua một vài lớp dày đặc. Tôi muốn tải trọng số từ một mạng như thế này vào một nơi mà các lớp dày đặc được thay thế bằng các cuộc cách mạng tương đương.Làm thế nào để chuyển đổi một lớp dày đặc thành một lớp chập tương đương trong Keras?

Mạng VGG16 đi kèm với Keras có thể được sử dụng làm ví dụ, trong đó đầu ra 7x7x512 của MaxPooling2D cuối cùng() được làm phẳng và sau đó đi vào lớp Dày đặc (4096). Trong trường hợp này, Dense (4096) sẽ được thay thế bằng một chập 7x7x4096.

Mạng thực của tôi hơi khác một chút, có lớp GlobalAveragePooling2D() thay vì MaxPooling2D() và Flatten(). Đầu ra của GlobalAveragePooling2D() là một tensor 2D, và không cần phải làm phẳng thêm nữa, vì vậy tất cả các lớp dày đặc bao gồm cả lớp đầu tiên sẽ được thay thế bằng các vòng xoắn 1x1.

Tôi đã nhìn thấy câu hỏi này: Python keras how to transform a dense layer into a convolutional layer có vẻ rất giống nhau nếu không giống nhau. Vấn đề là tôi không thể có được giải pháp được đề xuất để làm việc, bởi vì (a) Tôi đang sử dụng TensorFlow làm phụ trợ, do đó, sắp xếp lại trọng lượng/bộ lọc "xoay vòng" không đúng, và (b) tôi không thể làm thế nào để tải trọng lượng. Tải tập tin trọng số cũ vào mạng mới với model.load_weights(by_name=True) không hoạt động, vì tên không khớp (và thậm chí nếu chúng có kích thước khác nhau).

Bố cục sắp xếp lại khi sử dụng TensorFlow là gì?

Làm cách nào để tải trọng số? Tôi có tạo một trong mỗi mô hình, gọi model.load_weights() trên cả hai để tải trọng số giống nhau và sau đó sao chép một số trọng số bổ sung cần sắp xếp lại?

Trả lời

1

a. Không cần phải xoay vòng phức tạp. Chỉ cần định hình lại đang hoạt động

b. Sử dụng get_weights() và init layer mới

Lặp lại thông qua model.layers, tạo cùng một lớp với cấu hình và tải trọng bằng cách sử dụng set_weights hoặc như được hiển thị bên dưới.

Đoạn mã giả sau hoạt động cho tôi. (Keras 2.0)

Pseudo Code:

# find input dimensions of Flatten layer 
f_dim = flatten_layer.input_shape 

# Creating new Conv layer and putting dense layers weights 
m_layer = model.get_layer(layer.name) 
input_shape = m_layer.input_shape 
output_dim = m_layer.get_weights()[1].shape[0] 
W,b = layer.get_weights() 
if first dense layer : 
    shape = (f_dim[1],f_dim[2],f_dim[3],output_dim) 
    new_W = W.reshape(shape) 
    new_layer = Convolution2D(output_dim,(f_dim[1],f_dim[2]),strides=(1,1),activation='relu',padding='valid',weights=[new_W,b]) 

else: (not first dense layer) 
    shape = (1,1,input_shape[1],output_dim) 
    new_W = W.reshape(shape) 
    new_layer = Convolution2D(output_dim,(1,1),strides=(1,1),activation='relu',padding='valid',weights=[new_W,b]) 
1

Dựa trên câu trả lời của HARS, tôi tạo ra chức năng này để chuyển đổi một cnn tùy ý vào một fcn:

from keras.models import Sequential 
from keras.layers.convolutional import Convolution2D 
from keras.engine import InputLayer 
import keras 

def to_fully_conv(model): 

    new_model = Sequential() 

    input_layer = InputLayer(input_shape=(None, None, 3), name="input_new") 

    new_model.add(input_layer) 

    for layer in model.layers: 

     if "Flatten" in str(layer): 
      flattened_ipt = True 
      f_dim = layer.input_shape 

     elif "Dense" in str(layer): 

      input_shape = layer.input_shape 
      output_dim = layer.get_weights()[1].shape[0] 
      W,b = layer.get_weights() 

      if flattened_ipt: 
       shape = (f_dim[1],f_dim[2],f_dim[3],output_dim) 
       new_W = W.reshape(shape) 
       new_layer = Convolution2D(output_dim, 
              (f_dim[1],f_dim[2]), 
              strides=(1,1), 
              activation=layer.activation, 
              padding='valid', 
              weights=[new_W,b]) 
       flattened_ipt = False 

      else: 
       shape = (1,1,input_shape[1],output_dim) 
       new_W = W.reshape(shape) 
       new_layer = Convolution2D(output_dim, 
              (1,1), 
              strides=(1,1), 
              activation=layer.activation, 
              padding='valid', 
              weights=[new_W,b]) 


     else: 
      new_layer = layer 

     new_model.add(new_layer) 

    return new_model 

bạn có thể kiểm tra chức năng như thế này:

model = keras.applications.vgg16.VGG16() 
new_model = to_fully_conv(model) 
Các vấn đề liên quan