深度学习组件手动实现
卷积
import numpy as np
input_data=https://www.it610.com/article/[
[[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+rsreturn outputsdef 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=https://www.it610.com/article/[
[[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 rsdef 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 npdef 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.80.92 0.72 0.81 0.9 ]
#对应的索引index[254130]记住是取出索引,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_varx_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_paramdef 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
推荐阅读
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习
- 【韩语学习】(韩语随堂笔记整理)
- 焦点学习田源分享第267天《来访》