Python3 实现卷积层的前向传播

本本利用python3实现卷积层的前向传播,提取图像特征。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May  8 11:22:25 2018

@author: wsw
"""

# convolution implement
import numpy as np
import math
import cv2
import matplotlib.pyplot as plt


def conv2D(x,kernel,stride=1,padding='SAME'):
    '''
    conv2D implements a convolutional operation on single channel
    x:a single channel of input image
    kernel:conv kernel
    stirde:conv2D stride
    padding:default 'SAME'
    '''
    x_row,x_col = x.shape
    k_row,k_col = kernel.shape
    if k_row%2==0 or k_col%2==0:
        raise Exception('kernel size must be odd')
    if padding=='SAME':
        # padding input 
        pad_size_row, pad_size_col = k_row-1, k_col-1
        pad_x = np.zeros(shape=(x_row+pad_size_row,x_col+pad_size_col))
        id_row = pad_size_row//2
        id_col = pad_size_col//2
        pad_x[id_row:id_row+x_row,id_col:id_col+x_col] = x
        # compute output size
        res_row, res_col = math.ceil(x_row/stride), math.ceil(x_col/stride)
        res = np.zeros(shape=(res_row,res_col))
        # compute conv result
        for i in range(0,res_row,stride):
            for j in range(0,res_col,stride):
                sub = pad_x[i:i+k_row,j:j+k_col]
                res[i,j] = np.sum(sub*kernel)
        return res
    elif padding=='VALID':
        # compute output size
        res_row = math.ceil((x_row-k_row+1)/stride)
        res_col = math.ceil((x_col-k_col+1)/stride)
        res = np.zeros((res_row,res_col))
        # compute conv result
        for i in range(0,res_row,stride):
            for j in range(0,res_col,stride):
                sub = x[i:i+k_row,j:j+k_col]
                res[i,j] = np.sum(sub*kernel)
        return res
    else:
        raise Exception('padding type is not support')
        

class convLayer():
    '''
    Construct Convolutional Layer
    '''
    
    def __init__(self,in_channels,out_channels,kernel_h,kernel_w):
        self.conv_weights = np.random.normal(size=[kernel_h,kernel_w,
                                                   in_channels,out_channels])
        self.biases = np.zeros(out_channels)
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_h = kernel_h
        self.kernel_w = kernel_w
        
    def forward(self,inputs,stride=1,padding='SAME'):
        row, col, channels = inputs.shape
        if padding=='SAME':
            res_row,res_col = math.ceil(row/stride),math.ceil(col/stride)
        else:
            res_row = math.ceil((row-self.kernel_h+1)/stride)
            res_col = math.ceil((col-self.kernel_w+1)/stride)
        res = np.zeros((res_row,res_col,self.out_channels))
        for j in range(self.out_channels):
            for i in range(self.in_channels):
                res[:,:,j] += conv2D(inputs[:,:,i],self.conv_weights[:,:,i,j],
                                     stride=stride,padding=padding)
            res[:,:,j] += self.biases[j]
        return res
            
            
        

if __name__ == '__main__':
    # default 3 channels BGR model
    img = cv2.imread('/home/wsw/图片/ha.jpg',cv2.COLOR_BGR2RGB)
    img = img/255.0
    conv = convLayer(3,1,3,3)
    # set specifical kernel
    kernel = [[[-1,-2,-1],[0,0,0],[1,2,1]]]
    conv.conv_weights[:,:,:,0] = np.tile(kernel,[3,1,1])
    res = conv.forward(img)
    # display result
    plt.subplot(1,2,1)
    plt.imshow(img)
    plt.title('Original Image')
    plt.axis('off')
    plt.subplot(1,2,2)
    plt.imshow(res[:,:,0],cmap='Greys_r')
    plt.title('Feature Map')
    plt.axis('off') 
    plt.show()
    

特征提取:

Python3 实现卷积层的前向传播_第1张图片

你可能感兴趣的:(机器学习,深度学习)