深度学习(一)

博客围绕神经网络推理处理展开,介绍了交叉熵误差、softmax 函数等功能,阐述了反向传播中权重求偏导的意义及梯度法确定权重方向。还提及激活函数、MNIST 数据集,分析了损失函数、导数实现、梯度法等,最后介绍了两层神经网络类及反向传播相关函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

交叉熵误差 和 softmax 函数都有算概率和标签化的功能
反方向传播:
因为正向传播都关系到 多个权重W,求偏导其实就是 E(误差)关于W权重的导数,对W求导,意义就是:w的变动对E影响的贡献程度的大小
又W 是W1 W2 等的一个总关系,他们通过链式法则串起来的像个递归。 通过梯度法确定试W的方向,学习就是反复将试W,
#sigmoid 激活函数

import numpy as np
def sigmoid(x):
    return 1/ (1+np.exp(-x))

#relu激活函数

def relu (x):
    return np.maxium(0,x)#挑选最大值

#矩阵乘法

import numpy as np
A = np.array([1,2,3,4])
A.shape #显示类型(4,)一维4 四个元素

#softmax 分类;推理;概率
一般的当是分类问题时则用sotfmax函数,如果是根据特征推理预测等问题,则用恒等函数

def softmax(a):
    c = np.max(a)'''用来找出最大值然后对齐正则化'''
    epx_a = np.exp(a-c)
    sum_exp_a = np.sum(epx_a)
    y = exp_a/sum_exp_a
    return y

#MNIST 数据集

import sys ,os
sys.path.append(os.pardir)

‘’‘实际上是把父目录deep-learning-from-scratch 加入到sys.path中,把整个父类文件都导入了’’’

from dataset.mnist import load_mnist

load_mnist函数以(训练图像,训练标签),(测试图像,测试标签)形式返回读入的MNIST数据

(x_train,t_train),(x_text,t_text) = load_mnist(flatten = True,normalize=Flase)

normaalize参数是把数据正规化0.0~1.0// flatten设置是否展开为一维数组//one_hot_label设置是否为标签保持

#神经网络的初步权重运算代码

import numpy as np
x=np.array([3.0,4.2,5.3])
w=np.array([2.1,3.4,1.2])
b = np.array([1,1,1])
A1 = np.dot(x,w)+b
Z1 = sigmoid(A1)'''激活函数的运用'''
return 0 ;

输出层的激活函数,一般是回归问题用恒等函数,多元分类问题用sigmore

神经网络推理处理

def get_data():'''数据集的收取'''
    (x_train,t_train),(x-test,t_test)=\
    load_mnist(normalize = Ture,flatten = Ture, one_hot_label = Flase)
    return x_text,t_text
def init_network(): 
    with open("sample_weight.pkl",'rb')as f:利用学习完的参数重新给network 
        network = pickle.load(f)
        return network
def predict(network,x): 传心参数和 x 给它进行前向推理
    w1,w2,w3 = network['w1'],networl['w2'],network['w3']
    b1,b2,b3 = network['b1'],metwork['b2'],network['b3']
    a1 = bp.dot(x,w1)+b1
    z1 = sigmoid(a1)
    a2 = np.dop(z1,w2)+b2
    z2 = sigmoid(a2)
    a3 = bp.dot(z2,w3)+b3
    y = softmax(a3)
    return y

批处理:大多数处理数值计算的库进行了能够高效处理大型数组运算的最优化

x,t = get_data()
network = init_network()
batch_size = 100#批数量
accuracy_cnt = 0
for i in range(0,len(x),batch_size):#生成以100为单为的数据列表
    x_batch = x[i:i+batch_size]#从1到100中取出全部数据
    y_batch = predict(network,x_batch)#传送给前向处理 得到概率Y 的列表
    p = np.argmax(y_batch,axis = 1)#axis 通过第一维为轴经,函数argmax取出最大值的索引
    accuracy_cnt+= np.sum(p==t[i:i+batch_size])#每个训练数据t 跟预期p比较,
    用np.sum()函数计算布尔值ture的个数,这样就看到底多符合预期效果
print("Accuracy:"+str(float(accuracy_cnt)/len(x)))

为什么要分训练数据 和 测试数据,因为最求泛化能力(指处理未被观察过的数据)
只对一个数据集过度拟合的状态称为过度拟合
#损失函数:衡量神经网络性能的“”恶劣程度,多大程度上的不拟合
#均方误差

def mean_squared_error(y,t):#y是经过softmax的概率,而t是标签
    return 0.5*np.sum((t-y)**2) #得出来的是神经网络的损失值

#交叉熵误差

def cross_entropy(y,t):
    delta = 1e-7#防止对数为0时,无限小
    return -np.sum(t*np.log(y+delta))
#np.random.choice(train_size,batch_size),随机从训练数据中抽取batch_size个数据
#mini-batch交叉熵误差的实现
def cross_entropy_error(y,t):
    if y.ndim ==1:
        t = t.reshape(1,t.size)
        y = y.reshape(1,y.size)
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size),t]+le-7))/batch_size
    #能抽出各个数据正确解标签对应的神经网络的输出

#损失函数和识别精度
1:对权重参数的损失函数求导,表示的是如果稍微改变这个权重参数的值,损失函数就会发生变化
2:对损失函数求导其实就是梯度,直到导数值为0时才才停止参数更新
3:因为识别精度类似阶跃函数,稍微改变参数,识别精度还是不变,因为识别精度是基于成功识别和没有识别作为自变量,
4:损失函数能时时刻刻反映梯度情况

#函数导数的实现

def numerical_diff(f,x):
    h = 10e-4  注意会导致舍入误差 问题
    return (f(x+h)-f(x-h))/2*h

真的导数会有误差所以用中心差分
解析求导,认为消掉误差

#偏导数的实现

def function_2(x):
    return x[0]**2+x[1]

numerical_diff(function_2,3.0) 在#3处的导数

#梯度
#像偏导数各变量的导数构成的坐标向量,也叫做梯度

def numerical_gradient(f,x):
    h = le-4#0.0001
    grad = np.zero_like(x)#生成和x形状相同的数组,且每个元素都是0
    
    for idx in range(x.size):
        tmp = x[idx]
        
        x[idx] = tmp+h
        fxh1 = f(x)#函数会在这里执行f函数,所以为了与之兼容而定义函数f(w)或f = lambda w:net.loss(x,t)
        x[idx]= tmp-h
        fxh2 = f(x)
        
        grad[idx] = (fxh1-fxh2)/(2*h)
        x[idx] = tmp#还原值?
    return grad 得到的是个梯度(各自导数得到的坐标)

#梯度法,

这里的 f 是损失函数,x是 权重
 def gradient_descent(f,init_x,lr=0.01,step_num=100):#f是最优化函数,lr是学习率,是超参数 
x = init_x for i range(step_num): 
grad = numerical_gradient(f,x)   #得到梯度值,(参数对于损失值得关系大小值)
 x = x-lr* grad     #进行step_num次数值更新, return x

#实现类,1,前向推理,softmax 再到损失值运算

import sys ,os
sys.path.appeend(os.pardir)
import numpy as np
from common.functions import softmax ,cross_entropy_error#导入softmax 和损失函数
from common.gradient import numerical_gradient #导入生成梯度模块

class simpleNet:
    def _init_(self):
        self.w = np.random.randn(2,3)#用高斯分布进行初始化
    def predict(self,x):
        return np.dot(x,self.w)
    def loss (self,x,t):#x 接收数据 t 为正确标签
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y,t)
        return loss

————————————————————————————————————————————————————————————————————————————————
#两层神经网络的的类的实现

import sys ,os
sys.path.append(os.pardir)
from common.function import *
from common.gradient import numerical_gradient

class TwolayeNet:
    def _init_(self,input_size,hidden_size,output_size
                  weight_init_std=0.01):#初始化了输入输出隐藏层神经
            self.params = {}#空字典保存神经网络的参数的字典型变量
            self.params['w1']=weight_init_std*\
                              np.random.randn(input_size,hidden_size)#高斯分布初始化权重
            self.params['b1']=np.zeros(hidden_size)#偏置进行初始化为0
            self.params['w2']=weight_init_std*\
                              np.random.randn(hidden_size,output_size)
            self.params['b2']=np.zeros(output_size)
            
   def predict(self.x): #传新参数和 x 给它进行前向推理
    w1,w2,w3 = self.params['w1'],self.params['w2']
    b1,b2,b3 = self.params['b1'],self.params['b2']
    a1 = bp.dot(x,w1)+b1
    z1 = sigmoid(a1)
    a2 = np.dop(z1,w2)+b2
    y = sigmoid(a2)
    return y
    
   def lose(self,x,t):#x是输入数据,t是监督数据
       y = self.predict(x)#前向推理值给y,由交叉熵函数来计算损失情况
       return cross_entropy_error(y,t)
       
   def accuracy(self,x,t):
       y = self.predict(x)
       y = np.argmax(y,axis = 1)
       t = np.agrmax(t,axis = 1)
       
       accuracy = np.sum(y==t)/float(x.shape[0])     
       return accuracy  
   def numerical_gradient(self,x,t):
       loss_w = lambda w:self.loss(x,t)#这个函数里面会计算loss函数,并计算各个参数对损失函数的梯度
       
       grads={}#保存的梯度值
       grads['w1']= numerical_gradient(loss_w,self.params['w1'])
       grads['b1']= numerical_gradient(loss_w,self.params['b1'])
       grads['w2']= numerical_gradient(loss_w,self.params['w2'])
       grads['b2']= numerical_gradient(loss_w,self.params['b2'])

————————————————————————————————————————————————————————————————————————————————————————
#MINIST数据集的一个实现

import numpy as np
from datast.mnist import load_mnist#导入一个数据收集函数
from two_layer_net import TwoLayerNet
(x_train,t_train),(x_text,t_text) = \load_mnist(one_hot_label= True,normalize=True)
train_loss_list = []#进行记录损失值得变化
#超参数
iters_num = 10000#进行10000次循环,为了梯度下降
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
network = TwoLayerNet(input_size = 784,hidden_size = 50,output_size = 10)

for i in range(iters_num):
    batch_mask = np.random.choice(train_size,batch_size)#'在train_size中以batch_size为单位随机取出值放在batch_mask numpy数组中
    x_batch = x_train[batch_mask]#在0到batch_mask中依次取出批量训练数据
    y_batch = y_train[batch_mask]
    
    grad = network.numerical_gradient(x_batch,y_batch)#高速版:grad = network.gradient(x_batch,y_batch),生成梯度
    for key in ('w1','b1','w2','b2'):#循环4个numpy数组
        network.params[key] -=learning_rate*grad[key]#更新参数
        
    loss = network.loss(x_batch,t_batch)
    train_loss_list.append(loss)

#实现反向传播得乘法层

class MulLayer:
    def _init_(self):
        self.x = None
        self.y = None
    def forward(self,x,y):
        self.x = x
        self.y = y
        out = x*y
        return out
    def backward(self,dout):
        dx = dout*self.y
        dy = dout*self.x
        return dx,dy

#加法层实现

class AddLayer:
    def _init_(self):
        pass
    def forward(self,x,y):
        out = x+y
        return out
    def backward(self,dout):
        dx = dout*1
        dy = dout*1
        return dx,dy

#反向传播得ReLU 函数(反向时反正之前由传值则让他畅通无阻,如果不是堵死他)

def ReLU:
    def _init_(self):
        self.mask = None
    def forward(self,x):
        self.mask = (x<=0)#这个变量mask 是由True 和False 组成得numpy数组,它会将x传送的小于等于0得数保存为True 其余为False
        out = x.copy()
        out[self.mask] = 0#将True都改为0 也就是不能过的,而能过得没改变
        return out
    def backword(self,dout):
        dout[self.mask] = 0#它会延用正向传播时的mask数组,将True都改成0,不能过的改为0
        dx = dout
        return out

#Sigmoid 函数的反向传播

class Sigmoid:
    def _init_(self):
        self.out = None#放为全局属性就可以反复调用了
    def forward(self.x):
        out = 1/(1+np.exp(-x))
        self.out = out
        return out 
    def backward(self,dout):
        dx = dout*(1.0-self.out)*self.out
        return dx
#Affine矩阵层的实现
class Affine:
    def _init_(self,w,b):
        self.w = w
        self.b = b
        self.x = None
        self.dw = None
        self.db = None 
    def forward(self,x):
        self.x = x
        out = np.dot(x,self.w)+self.b
        return out
    def backward(self,dout):
        dx = np.dot(dout,self.w.T)
        self.dw = np.dot(dout,self.x.T)
        self.db = np.sum(dout,axis = 0)#以第一轴进行和运算
        return dx

#Softmax-with-lose 概率和损失函数的结合体
#神经网络的推理阶段不需要Softmax函数 ,但学习阶段需要
#这个结合体函数反向传播会得到一个比较漂亮的值(y1-t1,y2-t2,y3-t3)实际上是识别成功率(softmax的输出)和正确监督标签的差分,将其返回给上一层让他们很好的学习

class SoftmaxWithLoss:
    def _init_(self):
        self.loss = None
        self.y = None 
        self.t = None 
    def forward (self,x,t):
        self.t = t
        self.y = softmax(x)#需要数据
        self.loss = cross_entropy_error(self.y,self.t)#需要数据和正确监督标签
        return self.loss #反映损失值
    def backward (self,dout = 1):
        batch_size = self.t.shape[0]#???
        dx = (self.y-self.t)/batch_size#除以批的大小
        return dx
#单层感知机为什么没办法解决问题
因为 x1*w1+w2*w2 == 其实等价于一条直线
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值