如何在Keras中创建自定义卷积层

时间:2020-11-11 19:20:09

标签: python tensorflow keras neural-network

Keras中,我需要一个自定义的卷积神经网络,其中输入6x6,输出2x2。这该怎么做? (也许带有自定义图层)

我创建了numpy示例(错误和缓慢的代码):

import numpy as np
from matplotlib import image as mpimg, pyplot as plt
import json

def sigmoid(x, deriv=False):
    if deriv:
        return sigmoid(x)*(1-sigmoid(x))
    return 1/(1+np.exp(-x))

def read_rect(arr, x, y, w, h):
    new_arr = np.zeros((w, h, arr.shape[2]))
    for pix_x in range(w):
        for pix_y in range(h):
            if x+pix_x >= arr.shape[0] or y+pix_y >= arr.shape[1] or x+pix_x < 0 or y+pix_y < 0:
                pass
            else:
                new_arr[pix_x, pix_y] = arr[x+pix_x, y+pix_y]
    return new_arr
    return arr[x:x+w, y:y+w]

def write_rect(arr, dat, x, y):
    new_arr = arr.copy()
    for pix_x in range(dat.shape[0]):
        for pix_y in range(dat.shape[1]):
            if x+pix_x >= new_arr.shape[0] or y+pix_y >= new_arr.shape[1]:
                pass
            else:
                new_arr[x+pix_x, y+pix_y] = dat[pix_x, pix_y]
    return new_arr

def size(l):
    l = np.array(l)
    r = 1
    for i in l.ravel():
        r *= i
    return r

class UpConv2D:
    def __init__(self, kernel_in = (10, 10, 3), kernel_out = (2, 2, 3), activation=sigmoid):
        self.kernel_in = kernel_in[:3]
        self.kernel_out = kernel_out[:3]
        self.weights = 2*np.random.random((size(self.kernel_in),size(self.kernel_out))) - 1
        self.activation = activation

    def do_pixel(self, inp):
        inp = inp.ravel()[:size(self.kernel_in)]
        out = self.activation(np.dot(inp,self.weights))
        return np.array(out.reshape(self.kernel_out))
    def call(self, inp):
        out = np.zeros(np.append(np.array(inp.shape[:2])*self.kernel_out[:2], self.kernel_out[2]))
        for x in range(inp.shape[0]):
            for y in range(inp.shape[1]):
                square_in = read_rect(inp, x-self.kernel_in[0]//2, y-self.kernel_in[1]//2, self.kernel_in[0], self.kernel_in[1])
                square_out = self.do_pixel(square_in)
                out = write_rect(out, square_out, x*self.kernel_out[0], y*self.kernel_out[1])
        return out
    def __call__(self, *args, **kwargs):
        return self.call(*args, **kwargs)

    def write_weights(self):
        return json.dumps(self.weights.tolist())
    def read_weights(self, data):
        self.weights = numpy.array(json.loads(data))

我需要为 Keras 做。如果kernel_out为(5,6,3),inp为(100,120,3),则输出图像的形状将为(5x100,6x120,3)或(500,720,3)。因此,我创建了一个空的(零)矩阵,其空余数为(500,720,3),然后在扫描时填充该矩阵。 Do_pixel是简单的一层神经网络,具有输入kernel_in和输出kernel_out。 Read_rect-从图像获取矩形。 Write_rect-在图像中写入矩形。就像是高级卷积层

1 个答案:

答案 0 :(得分:1)

如果输入为6x6,输出应该为2x2,我相信您需要简单的卷积:

Conv2D(filter_num, kernel_size=(3,3), strides=(3,3), padding='valid', activation='relu')

别忘了从docs开始,输入是4D:

如果data_format ='channels_first',则4 + D张量的形状为:batch_shape +(通道,行,列),如果data_format ='channels_last',则为4 + D张量的形状为:batch_shape +(行,列,通道)。 / p>