关于深度学习:深度学习组件手动实现

9次阅读

共计 5950 个字符,预计需要花费 15 分钟才能阅读完成。

卷积

import numpy as np
input_data=[[[1,0,1,2,1],
               [0,2,1,0,1],
               [1,1,0,2,0],
               [2,2,1,1,0],
               [2,0,1,2,0]],

               [[2,0,2,1,1],
                [0,1,0,0,2],
                [1,0,0,2,1],
                [1,1,2,1,0],
                [1,0,1,1,1]] 
            ]
weights_data=[[[ 1, 0, 1],
                [-1, 1, 0],
                [0,-1, 0]],
               [[-1, 0, 1],
                [0, 0, 1],
                [1, 1, 1]] 

           ]

#fm:[h,w]
#kernel:[k,k]
#return rs:[h,w] 
def compute_conv(fm,kernel):
    [h,w]=fm.shape
    [k,_]=kernel.shape 
    r=int(k/2)
    #定义边界填充 0 后的 map
    padding_fm=np.zeros([h+2,w+2],np.float32)
    #保留计算结果
    rs=np.zeros([h,w],np.float32)
    #将输出在指定该区域赋值,即除了 4 个边界后,剩下的区域
    padding_fm[1:h+1,1:w+1]=fm 
    #对每个点为核心的区域遍历
    for i in range(1,h+1):
        for j in range(1,w+1): 
            #取出以后点为核心的 k * k 区域
            roi=padding_fm[i-r:i+r+1,j-r:j+r+1]
            #计算以后点的卷积, 对 k * k 个点点乘后求和
            rs[i-1][j-1]=np.sum(roi*kernel)
 
    return rs
 
def my_conv2d(input,weights):
    [c,h,w]=input.shape
    [_,k,_]=weights.shape
    outputs=np.zeros([h,w],np.float32)

    #对每个 feature map 遍历,从而对每个 feature map 进行卷积
    for i in range(c):
        #feature map==>[h,w]
        f_map=input[i]
        #kernel ==>[k,k]
        w=weights[i]
        rs =compute_conv(f_map,w)
        outputs=outputs+rs   

    return outputs

def main():  
    
    #shape=[c,h,w]
    input = np.asarray(input_data,np.float32)
    #shape=[in_c,k,k]
    weights =  np.asarray(weights_data,np.float32) 
    rs=my_conv2d(input,weights) 
    print(rs) 


if __name__=='__main__':
    main() 

反卷积 (反卷积 = 卷积 + 填充 + 裁剪)

input_data=[[[1,0,1],
                [0,2,1],
                [1,1,0]],

               [[2,0,2],
                [0,1,0],
                [1,0,0]],

               [[1,1,1],
                [2,2,0],
                [1,1,1]],

               [[1,1,2],
                [1,0,1],
                [0,2,2]]

            ]
weights_data=[[[[ 1, 0, 1],
                [-1, 1, 0],
                [0,-1, 0]],
               [[-1, 0, 1],
                [0, 0, 1],
                [1, 1, 1]],
               [[0, 1, 1],
                [2, 0, 1],
                [1, 2, 1]], 
               [[1, 1, 1],
                [0, 2, 1],
                [1, 0, 1]]],

              [[[1, 0, 2],
                [-2, 1, 1],
                [1,-1, 0]],
               [[-1, 0, 1],
                [-1, 2, 1],
                [1, 1, 1]],
               [[0, 0, 0],
                [2, 2, 1],
                [1,-1, 1]], 
               [[2, 1, 1],
                [0,-1, 1],
                [1, 1, 1]]]  
           ]

#依据输出 map([h,w]) 和卷积核 ([k,k]), 计算卷积后的 feature map
import numpy as np
def compute_conv(fm,kernel):
    [h,w]=fm.shape 
    [k,_]=kernel.shape 
    r=int(k/2)
    #定义边界填充 0 后的 map
    padding_fm=np.zeros([h+2,w+2],np.float32)
    #保留计算结果
    rs=np.zeros([h,w],np.float32) 
    #将输出在指定该区域赋值,即除了 4 个边界后,剩下的区域
    padding_fm[1:h+1,1:w+1]=fm 
    #对每个点为核心的区域遍历
    for i in range(1,h+1):
        for j in range(1,w+1): 
            #取出以后点为核心的 k * k 区域
            roi=padding_fm[i-r:i+r+1,j-r:j+r+1]
            #计算以后点的卷积, 对 k * k 个点点乘后求和
            rs[i-1][j-1]=np.sum(roi*kernel)
 
    return rs
 
#填充 0
def fill_zeros(input):
    [c,h,w]=input.shape
    rs=np.zeros([c,h*2+1,w*2+1],np.float32)
    
    for i in range(c):
        for j in range(h):
            for k in range(w): 
                rs[i,2*j+1,2*k+1]=input[i,j,k] 
    return rs

def my_deconv(input,weights):
    #weights shape=[out_c,in_c,h,w]
    [out_c,in_c,h,w]=weights.shape   
    out_h=h*2
    out_w=w*2
    rs=[]
    for i in range(out_c):
        w=weights[i]
        tmp=np.zeros([out_h,out_w],np.float32)
        for j in range(in_c):
            conv=compute_conv(input[j],w[j])
            #留神裁剪,最初一行和最初一列去掉
            tmp=tmp+conv[0:out_h,0:out_w]
        rs.append(tmp)
   
    return rs 

 
def main():  
    input=np.asarray(input_data,np.float32)
    input= fill_zeros(input)
    weights=np.asarray(weights_data,np.float32)
    deconv=my_deconv(input,weights)
   
    print(np.asarray(deconv))

if __name__=='__main__':
    main()

Dropout

import numpy as np

def dropout(x, p, mode='train'):
    keep_prob = 1 - p
    if mode == 'train':
        x *= np.random.binomial(1, keep_prob, size=x.shape)
    else:
        x *= keep_prob
    return x
---------------------
test = np.random.binomial(5, 0.5, 10)  #伯努利二项式散布
print(test)
输入:[1 5 5 2 4 2 3 3 2 3]
(一次抛 5 枚硬币,每枚硬币侧面朝上概率为 0.5,做 10 次试验,求每次试验产生侧面朝上的硬币个数:)

IOU

def IOU(x1,y1,X1,Y1,x2,y2,X2,Y2):
    xx=max(x1,x2)
    XX=min(X1,X2)
    yy=max(y1,y2)
    YY=min(Y1,Y2)
    m=max(0,XX-xx)
    n=max(0,YY-yy)
    jiao=m*n
    bing=(X1-x1+1)*(Y1-y1+1)+(X2-x2+1)*(Y2-y2+1)-jiao  #+ 1 避免为 0
    return jiao/bing

NMS


def py_cpu_nms(dets, thresh):
    #首先数据赋值和计算对应矩形框的面积
    #dets 的数据格式是 dets[[xmin,ymin,xmax,ymax,scores]....]
 
    x1 = dets[:,0]
    y1 = dets[:,1]
    x2 = dets[:,2]
    y2 = dets[:,3]
    areas = (y2-y1+1) * (x2-x1+1)
    scores = dets[:,4]
    print('areas',areas)
    print('scores',scores)
 
    #这边的 keep 用于寄存,NMS 后残余的方框
    keep = []
    
    #取出分数从大到小排列的索引。.argsort() 是从小到大排列,[::-1] 是列表头和尾颠倒一下。index = scores.argsort()[::-1]
    print(index) 
    #下面这两句比方分数 [0.72 0.8  0.92 0.72 0.81 0.9]    
    #  对应的索引 index[2   5    4     1    3   0] 记住是取出索引,scores 列表没变。#index 会剔除遍历过的方框,和合并过的方框。while index.size >0:
        print(index.size)
        #取出第一个方框进行和其余方框比对,看有没有能够合并的
        i = index[0]       # every time the first is the biggst, and add it directly
        
        #因为咱们这边分数曾经按从大到小排列了。#所以如果有合并存在,也是保留分数最高的这个,也就是咱们当初那个这个
        #keep 保留的是索引值,不是具体的分数。keep.append(i)
        print(keep)
        print('x1',x1[i])
        print(x1[index[1:]])
 
        #计算交加的左上角和右下角
        #这里要留神,比方 x1[i] 这个方框的左上角 x 和所有其余的方框的左上角 x 的
        x11 = np.maximum(x1[i], x1[index[1:]])    # calculate the points of overlap 
        y11 = np.maximum(y1[i], y1[index[1:]])
        x22 = np.minimum(x2[i], x2[index[1:]])
        y22 = np.minimum(y2[i], y2[index[1:]])
        
        print(x11,y11,x22,y22)
        #这边要留神,如果两个方框相交,X22-X11 和 Y22-Y11 是正的。#如果两个方框不相交,X22-X11 和 Y22-Y11 是负的,咱们把不相交的 W 和 H 设为 0.
        w = np.maximum(0, x22-x11+1)    
        h = np.maximum(0, y22-y11+1)    
       
        #计算重叠面积就是下面说的交加面积。不相交因为 W 和 H 都是 0,所以不相交面积为 0
        overlaps = w*h
        print('overlaps is',overlaps)
        
        #这个就是 IOU 公式(交并比)。#得进去的 ious 是一个列表,外面领有以后方框和其余所有方框的 IOU 后果。ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)
        print('ious is',ious)
        
        #接下来是合并重叠度最大的方框,也就是合并 ious 中值大于 thresh 的方框
        #咱们合并的操作就是把他们剔除,因为咱们合并这些方框只保留下分数最高的。#咱们通过排序以后咱们操作的方框就是分数最高的,所以咱们剔除其余和以后重叠度最高的方框
        #这里 np.where(ious<=thresh)[0] 是一个固定写法。idx = np.where(ious<=thresh)[0]
        print(idx)
 
        #把留下来框在进行 NMS 操作
        #这边留下的框是去除以后操作的框,和以后操作的框重叠度大于 thresh 的框
        #每一次都会先去除以后操作框,所以索引的列表就会向前挪动移位,要还原就 +1,向后挪动一位
        index = index[idx+1]   # because index start from 1
        print(index)
    return keep

BatchNormalization

def Batchnorm_simple_for_train(x, gamma, beta, bn_param):
"""
param:x    : 输出数据,设 shape(B,L)
param:gama : 缩放因子  γ
param:beta : 平移因子  β
param:bn_param   : batchnorm 所须要的一些参数
    eps      : 靠近 0 的数,避免分母呈现 0
    momentum : 动量参数,个别为 0.9,0.99,0.999
    running_mean:滑动均匀的形式计算新的均值,训练时计算,为测试数据做筹备
    running_var  : 滑动均匀的形式计算新的方差,训练时计算,为测试数据做筹备
"""running_mean = bn_param['running_mean']  #shape = [B]
    running_var = bn_param['running_var']    #shape = [B]
    momentun = bn_param['momentun']    #shape = [B]
    results = 0. # 建设一个新的变量

    x_mean=x.mean(axis=0)  # 计算 x 的均值
    x_var=x.var(axis=0)    # 计算方差

    running_mean = momentum * running_mean + (1 - momentum) * x_mean
    running_var = momentum * running_var + (1 - momentum) * x_var

    x_normalized=(x - running_mean)/np.sqrt(running_var + eps)       # 归一化
    results = gamma * x_normalized + beta            # 缩放平移


    #记录新的值
    bn_param['running_mean'] = running_mean
    bn_param['running_var'] = running_var 

    return results , bn_param

def Batchnorm_simple_for_test(x, gamma, beta, bn_param):
"""
param:x    : 输出数据,设 shape(B,L)
param:gama : 缩放因子  γ
param:beta : 平移因子  β
param:bn_param   : batchnorm 所须要的一些参数
    eps      : 靠近 0 的数,避免分母呈现 0
    momentum : 动量参数,个别为 0.9,0.99,0.999
    running_mean:滑动均匀的形式计算新的均值,训练时计算,为测试数据做筹备
    running_var  : 滑动均匀的形式计算新的方差,训练时计算,为测试数据做筹备
"""running_mean = bn_param['running_mean']  #shape = [B]
    running_var = bn_param['running_var']    #shape = [B]
    results = 0. # 建设一个新的变量

    x_normalized=(x-running_mean)/np.sqrt(running_var +eps)       # 归一化
    results = gamma * x_normalized + beta            # 缩放平移

    return results , bn_param
正文完
 0