精华内容
下载资源
问答
  • 卷积神经网络结构示意,可以作为一个参考进行修改,包含有卷积层,池化层,Flatten,全连接层和softmax
  • 图解全连接神经网络及算法

    千次阅读 2018-12-24 17:52:44
    看完Adreaw NG的深度学习第一课后,想着自己用python来实现一个全连接多层神经网络,但在实现的过程中,由于对从0开始计数等不太能想象,发现index很烦,就自己拿出一张纸来写出过程给自己冷静冷静,通过给参数W,b...

    看完Adreaw NG的深度学习第一课后,想着自己用python来实现一个全连接多层神经网络,但在实现的过程中,由于对从0开始计数等不太能想象,发现index很烦,就自己拿出一张纸来写出过程给自己冷静冷静,通过给参数W,b,中间变量A, Z等数据结构添加了一个0变量后使得他们与神经网络的层数对齐后,然后所有的问题都迎刃而解了!所以以后写代码还是先拿出笔纸来列个提纲后确定了之后再开始写代码吧。。。

    不多说了,上图解:(基于二分类logistics regression cost function的梯度下降反向传播推导出来的算法,推导过程这里省略了)

     

    我的实现代码见我的GitHub:Interesting6

    实验效果:

    分类边界图:

    用了两个隐藏层,以tanh为隐藏层激活函数,sigmoid为输出层激活函数,可以看到分类的效果还是不错的。

    展开全文
  • 全连接神经网络中,每相邻两层之间的节点都有边相连,于是会将每一层的全连接层中的节点组织成一列,这样方便显示连接结构。而对于卷积神经网络,相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,一般...

    在这里大致说明以一下我在学习过程中的理解:

           卷积神经网络也是通过一层一层的节点组织起来的。和全连接神经网络一样,卷积神经网络中的每一个节点就是一个神经元。在全连接神经网络中,每相邻两层之间的节点都有边相连,于是会将每一层的全连接层中的节点组织成一列,这样方便显示连接结构。而对于卷积神经网络,相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,一般会将每一层卷积层的节点组织成一个三维矩阵。

           除了结构相似,卷积神经网络的输入输出以及训练的流程和全连接神经网络也基本一致,以图像分类为列,卷积神经网络的输入层就是图像的原始图像,而输出层中的每一个节点代表了不同类别的可信度。这和全连接神经网络的输入输出是一致的。类似的,全连接神经网络的损失函数以及参数的优化过程也都适用于卷积神经网络。因此,全连接神经网络和卷积神经网络的唯一区别就是神经网络相邻两层的连接方式。

          但是,通过我后面的学习,我发现全神经网络无法很好地处理好图像数据,然而卷积神经网络却很好地客服了这个缺点,使用全连接神经网络处理图像的最大问题就是:全连接层的参数太多,对于MNIST数据,每一张图片的大小是28*28*1,其中28*28代表的是图片的大小,*1表示图像是黑白的,有一个色彩通道。假设第一层隐藏层的节点数为500个,那么一个全连接层的神经网络有28*28*500+500=392500个参数,而且有的图片会更大或者是彩色的图片,这时候参数将会更多。参数增多除了导致计算速度减慢,还很容易导致过拟合的问题。所以需要一个合理的神经网络结构来有效的减少神经网络中参数的个数。卷积神经网络就可以更好的达到这个目的。
     

    展开全文
  • 第六节:Pytorch实现全连接神经网络

    千次阅读 2020-09-19 19:19:30
    第六节:Pytorch实现全连接神经网络 前面的五节中,我们讲解了使用PyTorch搭建一个神经网络中需要的需要各种技巧,包括:网络的搭建、选择不同的实践技巧(优化器选择、学习率下降等等)以及可视化训练过程 接下来的...

    第六节:Pytorch实现全连接神经网络

    前面的五节中,我们讲解了使用PyTorch搭建一个神经网络中需要的需要各种技巧,包括:网络的搭建、选择不同的实践技巧(优化器选择、学习率下降等等)以及可视化训练过程

    接下来的几章,我们将使用Pytorch搭建各种神经网络

    本章我们将使用PyTorch从头到尾完整的搭建一个全连接神经网络

    我们使用垃圾邮件分类和加利福尼亚房价数据两个数据集来进行训练,分别对应机器学习中有监督学习的分类和回归任务

    分类任务:垃圾邮件分类

    垃圾邮件分类的数据集可以在加利福尼亚大学尔湾分校的网站上下载

    数据集一共包含三个文件,data文件是数据文件,其中的每一行都代表一个邮件,一共有4061个邮件,其中有1813个非垃圾邮件,2788个垃圾邮件

    我们的目标是训练一个全连接神经网络来实现对垃圾邮件的预测

    数据集一共有58列,其中前48列是某个关键词在全文的频率×100,例如you、make等词语,每一个词语以word_freq_xxx作为列索引,例如free的全文频率以word_freq_free作为列索引;

    49~54列是一些符号在全文所有符号中出现的评论×100,例如;,#,$等,同样,这些列以char_freq_x的形式作为列名,例如;的列索引名称为char_freq_;

    55列是全文中所有连续的大写单词的平均长度,56列是大写单词的最长长度,57列是邮件中大写字母的数量,58列是文件是否是垃圾邮件

    names文件中包含所有的特征名称

    DOCUMENTATION中包含数据集的描述信息

    准备工作

    我们首先导入需要使用的库

    import numpy as np
    import pandas as pd
    from sklearn.preprocessing import StandardScaler,MinMaxScaler
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score,confusion_matrix,classification_report
    from sklearn.manifold import TSNE
    import torch
    import torch.nn as nn
    from torch.optim import SGD,Adam
    import torch.utils.data as Data
    import matplotlib.pyplot as plt
    import seaborn as sns
    import hiddenlayer as hl
    from torchviz import make_dot
    

    其中sklearn.preprocessing是用于对数据进行标准化预处理的模块,帮助我们将所有的值映射到0~1之间,便于模型学习到数据的分布

    由于我们是从csv文件中读取的数据,因此我们还要使用sklearn.model_selection来帮助我们分割训练集与测试集

    我们使用sklearn.metrics来评估模型的预测效果

    最后为了对数据集进行直观的理解,我们使用sklearn.manifold来对输入的数据(具有57个特征的邮件)进行降维,将57个特征按照重要性组合为2个特征从而能够在平面上显示,我们将使用这个模块来降维以及可视化

    数据清洗

    我们首先对数据进行读取、清洗、分割等预处理

    在一个完整的机器学习的流程中,我们对给定数据集首先进行清洗、分割等预操作之后,还要根据对数据集进行了解,以确定我们会使用的机器学习算法,这里我们已经确定使用的是全连接神经网络,但是为了体现一个完整的机器学习流程,我们还是会对数据集特征进行可视化与了解

    data=pd.read_csv(filepath_or_buffer='./data/spambase/spambase.data',sep=',',header=None)
    index=pd.read_csv(filepath_or_buffer='./data/spambase/spambase.names',sep='\t',header=None)
    print(data.shape)
    print(data.head(2))
    print('')
    print(index.shape)
    print(index.tail(20))
    >>>
    (4601, 58)
         0     1     2    3     4     5     6     7    8     9   ...   48     49  \
    0  0.00  0.64  0.64  0.0  0.32  0.00  0.00  0.00  0.0  0.00  ...  0.0  0.000   
    1  0.21  0.28  0.50  0.0  0.14  0.28  0.21  0.07  0.0  0.94  ...  0.0  0.132   
    
        50     51    52     53     54   55    56  57  
    0  0.0  0.778  0.00  0.000  3.756   61   278   1  
    1  0.0  0.372  0.18  0.048  5.114  101  1028   1  
    
    [2 rows x 58 columns]
    
    (87, 1)
                                              0
    67      word_freq_parts:        continuous.
    68      word_freq_pm:           continuous.
    69      word_freq_direct:       continuous.
    70      word_freq_cs:           continuous.
    71      word_freq_meeting:      continuous.
    72      word_freq_original:     continuous.
    73      word_freq_project:      continuous.
    74      word_freq_re:           continuous.
    75      word_freq_edu:          continuous.
    76      word_freq_table:        continuous.
    77      word_freq_conference:   continuous.
    78      char_freq_;:            continuous.
    79      char_freq_(:            continuous.
    80      char_freq_[:            continuous.
    81      char_freq_!:            continuous.
    82      char_freq_$:            continuous.
    83      char_freq_#:            continuous.
    84  capital_run_length_average: continuous.
    85  capital_run_length_longest: continuous.
    86  capital_run_length_total:   continuous.
    

    由于我们读取的names文件夹中除了特征名以外,还有其他的内容,因此我们首先对names读取出的特征内容进行清洗

    首先通过抽样确定特征开始的行

    print(index.iloc[25:33])
    >>>
                                                        0
    25            | i.e. unsolicited commercial e-mail.  
    26                                                  |
    27  | For more information, see file 'spambase.DOC...
    28  | UCI Machine Learning Repository: http://www....
    29                  1, 0.    | spam, non-spam classes
    30                word_freq_make:         continuous.
    31                word_freq_address:      continuous.
    32                word_freq_all:          continuous.
    

    得知特征的名称从30行开始,考虑到带分割特征中每一行:前都是我们需要提取的数据,因此我们使用字符串的split方法

    index=index.loc[30:].copy()
    print(index.head())
    for i,word in enumerate(index.values):
        index.iloc[i]=index.iloc[i].values[0].split(':')[0]
    print(index.head())
    >>>
                                          0
    30  word_freq_make:         continuous.
    31  word_freq_address:      continuous.
    32  word_freq_all:          continuous.
    33  word_freq_3d:           continuous.
    34  word_freq_our:          continuous.
                        0
    30     word_freq_make
    31  word_freq_address
    32      word_freq_all
    33       word_freq_3d
    34      word_freq_our
    

    接下来我们为添加上文件特征这一行之后,将其转化为Index对象作为data对象的行名

    index.loc[87]='label'
    newIndex=pd.Index(index.values.reshape(len(index.values)))
    data.columns=newIndex
    print(data.iloc[0:2,0:3])
    >>>
       word_freq_make  word_freq_address  word_freq_all
    0            0.00               0.64           0.64
    1            0.21               0.28           0.50
    

    数据预处理

    下面我们对数据进行预处理,以达到可以用于训练的程度

    首先划分数据集,我们主要调用scikit-learn中的train_test_split来划分数据集,我们指定测试集的大小以及随机抽取的混乱度

    X=data.iloc[:,0:57].values
    y=data['label'].values
    X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=123)
    print(y.shape)
    print(X_test.shape)
    print(X_train.shape)
    print(y_test.shape)
    print(y_train.shape)
    >>>
    (4601,)
    (1151, 57)
    (3450, 57)
    (1151,)
    (3450,)
    

    接下来标准化输入的数据,使得输入数据的范围在0~1内,我们使用scikit-learn中的MinMaxScaler方法

    最后我们为了检验标准化的结果,我们指定求出测试和训练集中的每个特征的最大值,判断是否为1,最小值是否为0

    由于计算机的浮点数精度问题,实际上我们无法得到精确的1,只能得到一个和1相差为10-14~1017的数字,在计算机的角度来说我们就认为其为1

    scaler=MinMaxScaler(feature_range=(0,1))
    X_train=scaler.fit_transform(X_train)
    X_train=scaler.fit_transform(X_test)
    print((X_train.max(axis=0)>(1-1e-7)).sum(),(X_train.min(axis=0)==0).sum())
    >>>
    57 57
    

    数据特征可视化

    在训练前我们对训练数据集所有数据的某一个特征进行可视化

    我们使用箱须图来进行可视化,箱须图中的箱体的三条线分别表示25%,50%,75%位置的值,而须线的上边缘和下边缘分别是75%值+1.5(75%的值-25%的值)和25%的值-(75%的值-25%的值)

    colname=data.columns.values[:-1]
    plt.figure(figsize=(20,14))
    for ii in range(len(colname)):
        plt.subplot(7,9,ii+1)
        sns.boxplot(x=y_train,y=X_train[:,ii])
        plt.title(colname[ii])
    plt.subplots_adjust(hspace=0.4)
    plt.show()
    

    在这里插入图片描述

    搭建网络并可视化网络结构

    接下来我们将搭建出网络并可视化网络结构

    class FullyConnectedNuralNetwork(nn.Module):
        def __init__(self):
            super(FullyConnectedNuralNetwork,self)
            self.hidden1=nn.Sequential(
                    nn.Linear(in_features=57,out_features=30,bias=True),
                    nn.ReLU())
            self.hidden2=nn.Sequential(
                    nn.Linear(in_features=30,out_features=10,bias=True),
                    nn.ReLU())
            self.hidden3=nn.Sequential(
                    nn.Linear(in_features=10,out_features=2,bias=True),
                    nn.Sigmoid())
        def forward(self,x):
            fc1=self.hidden1(x)
            fc2=self.hidden2(fc1)
            output=self.hidden3(fc2)
            return fc1,fc2,output
    

    接下来用前面讲过的torchviz库的make_dot函数来可视化网络结构

    FCNN1=FullyConnectedNuralNetwork()
    x=torch.randn(size=(1,57)).requires_grad_(True)
    y=FCNN1(x)
    FCArchitecture=make_dot(y,params=dict(list(FCNN1.named_parameters())+[('x',x)]))
    FCArchitecture.format='png'
    FCArchitecture.directory='../图片/'
    FCArchitecture.view()
    

    在这里插入图片描述

    训练网络

    接下来我们将训练我们的网络,并使用前面讲解的方法来检测训练

    首先需要使用将数据直接处理为可用于训练的tensor,并且使用dataloader分批

    X_train=torch.from_numpy(X_train.astype(np.float32))
    y_train=torch.from_numpy(y_train.astype(np.float32))
    X_test=torch.from_numpy(X_test.astype(np.float32))
    y_test=torch.from_numpy(y_test.astype(np.float32))
    
    train_data=Data.TensorDataset(X_train,y_train)
    train_loader=Data.DataLoader(dataset=train_data,batch_size=64,shuffle=True,num_workers=1)
    for step,(batch_x,batch_y) in enumerate(train_loader):
        if step>0:
            break
    print(step,batch_x.shape,batch_y.shape)
    >>>
    1 torch.Size([64, 57]) torch.Size([64])
    

    然后定义需要使用的优化器和损失函数

    optomizerAdam=torch.optim.Adam(FCNN1.parameters(),lr=0.01)
    lossFunc=nn.CrossEntropyLoss()
    

    由于我们是一个轻量级的网络,因此使用HiddenLayer来进行可视化,注意我们如果把绘图函数放在训练过程内,那么就会得到动态的绘图效果

    history1=hl.History()
    canvas1=hl.Canvas()
    logStep=25
    for epoch in range(15):
        for step,(batch_x,batch_y) in enumerate(train_loader):
            _,_,output=FCNN1(batch_x)
            train_loss=lossFunc(output,batch_y)
            optomizerAdam.zero_grad()
            train_loss.backward()
            optomizerAdam.step()
            
            niter=epoch*len(train_loader)+step+1
            if niter % logStep ==0:
                _,_,output=FCNN1(X_test)
                _,pre_lab=torch.max(output,1)
                test_accuracy=accuracy_score(y_test,pre_lab)
                history1.log(niter,train_loss=train_loss,test_accuracy=test_accuracy)
                with canvas1:
                    canvas1.draw_plot(history1['train_loss'])
                    canvas1.draw_plot(history1['test_accuracy'])
    

    最后的效果如下

    在这里插入图片描述

    最后,尽管我们训练的准确度不稳定,但是我们的准确度却依旧维持在了较高的水平

    对于没有得到稳定的准确度,一个可能的原因是训练后期我们当前使用lr过大,导致一直在最优点之前震荡而无法下降到最优点

    理解网络

    我们上面训练的网络本质上是个黑箱模型,我们无法了解其中发生了什么事,下面我们对网络中间进行可视化,来了解输入数据在网络中计算的时候发生了什么

    落实到代码上就是我们要得到中间层的输出

    得到中间层输出有两种方法,第一种就是直接利用我们前向传播时候返回的中间值,第二种就是使用钩子技术

    钩子技术可以理解为在不影响原业务的基础上获得我们希望的中间值

    我们下面将使用钩子技术来获取中间值,钩子技术的实现主要靠闭包

    activations={}
    activations['origin']=X_test
    def getActivation(name):
        def hook(model,inputData,outputData):
            activations[name]=outputData.detach()
        return hook
    

    这里activations字典主要用于存储中间层的输出,hook需要定义的输入实际上是Pytorch中以及规定好的,需要我们预留的,因此必须这样写

    Pytorch中的每个层为我们预留了register_forward_hook函数,即预留了一个接口,我们如果调用这个接口,那么就会将隐藏在底层的输入和输出显化

    接下来Pytorch会将model填充为我们自定义的模型,input是指定层的输入,output是指定层的输出,这里由于我们只需要指定层的输出,因此只需要将获取的输出保存在全局上的字典即可

    接下来我们在获取中间值的时候再进行一次正常的计算就能够获取中间值,获取的原理就是上面说的,X_test的正向传播时候隐藏在底层的hidden1的输入和输出显化,并且按照我们设定的字典的模式保存

    FCNN1.hidden1.register_forward_hook(getActivation('hidden1'))
    FCNN1.hidden2.register_forward_hook(getActivation('hidden2'))
    FCNN1.hidden3.register_forward_hook(getActivation('hidden3'))
    _,_,_=FCNN1(X_test)
    

    我们查看下保存的效果

    print(len(activations))
    for item in activations:
        print(type(activations[item]))
        print(activations[item].shape)
    >>>
    4
    <class 'torch.Tensor'>
    torch.Size([1151, 57])
    <class 'torch.Tensor'>
    torch.Size([1151, 30])
    <class 'torch.Tensor'>
    torch.Size([1151, 10])
    <class 'torch.Tensor'>
    torch.Size([1151, 2])
    

    最后我们将每层得到的输出,包括原始输入使用TSNE方法进行降维,降维到二维以便于在图像上显示

    plt.figure(figsize=(16,12))
    for i,item in enumerate(activations):
        plt.subplot(2,2,i+1)
        value=TSNE(n_components=2).fit_transform(activations[item].data.numpy())
        plt.xlim([min(value[:,0]-1),max(value[:,0]+1)])
        plt.ylim([min(value[:,1]-1),max(value[:,0]+1)])
        plt.plot(value[y_test==0,0],value[y_test==0,1],'bo',label='Non-trash')
        plt.plot(value[y_test==1,0],value[y_test==1,1],'rd',label='Trash')
        plt.title(item)
    plt.legend()
    plt.subplots_adjust(hspace=0.4)
    plt.show()
    

    我们能够看到,原始输入的邮件具有57个特征,使用TSNE函数,即先使用PCA将57个特征根据重要程度压缩为2个特征,然后可视化,我们发现这个时候垃圾邮件和非垃圾邮件是杂乱的掺杂的

    但是经过第一个隐藏层之后,得到了有效的划分,接下来再经过第二个隐藏层之后进一步得到到了划分,一直直到最后一层

    在这里插入图片描述

    至此,第一个例子已经讲解完毕

    回归任务:房价预测

    下面我们将使用scikit-learning库中的加利福尼亚州的房价数据来训练我们的网络,来完成对房价的预测

    CA房价数据集来源于1990美国人口普查,这次人口普查将整个CA划分为多个人口普查区域,每个普查区域通常有600~3000的人口

    该数据集中的每一行都是一个普查区,一共包含20640个普查区,每个普查区有10个特征,例如:该区域收入平均数、房屋年龄、平均房间数等等

    最后我们将搭建一个全连接神经网络,来预测房屋的价格

    具体的步骤和上面进行垃圾邮件分类的任务大体相似,只不过由于我们使用的是scikit-learn中现成的库,因此免去了我们进行数据清洗的过程

    准备工作

    首先是导入库

    import numpy as np
    import pandas as pd
    from sklearn.preprocessing import StandardScaler
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import mean_squared_error,mean_absolute_error
    from sklearn.datasets import fetch_california_housing
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    from torch.optim import Adam
    import matplotlib.pyplot as plt
    import seaborn as sns
    

    数据预处理

    我们直接使用fetch_california_housing来获取需要处理的数据

    但是由于使用这个函数将会访问外网来下载数据集,经常会由于url无法打开而报错,因此这里直接读取已经下载好的csv文件即可

    具体的资源csdn上搜索加利福尼亚房屋价格即可

    houseData=pd.read_csv('./data/housing.csv',sep=',')
    print(houseData.shape)
    print(houseData.head())
    >>>
    (20640, 10)
       longitude  latitude  housing_median_age  total_rooms  total_bedrooms  \
    0    -122.23     37.88                  41          880           129.0   
    1    -122.22     37.86                  21         7099          1106.0   
    2    -122.24     37.85                  52         1467           190.0   
    3    -122.25     37.85                  52         1274           235.0   
    4    -122.25     37.85                  52         1627           280.0   
    
       population  households  median_income  median_house_value ocean_proximity  
    0         322         126         8.3252              452600        NEAR BAY  
    1        2401        1138         8.3014              358500        NEAR BAY  
    2         496         177         7.2574              352100        NEAR BAY  
    3         558         219         5.6431              341300        NEAR BAY  
    4         565         259         3.8462              342200        NEAR BAY  
    

    这里median_house_value就是我们要预测的房屋价格

    由于ocean_proximity这一列是字符,我们需要将其转化为数值才能够参与到后面的运算

    我们首先查询下一共有那些数值

    types=[]
    for i in houseData['ocean_proximity'].values:
        if i not in types:
            types.append(i)
    print(types)
    >>>
    ['NEAR BAY', '<1H OCEAN', 'INLAND', 'NEAR OCEAN', 'ISLAND']
    

    我们根据顺序,分别给分0,1,2,3,来进行转化

    houseData['ocean_proximity_value']=np.zeros_like(houseData['households'])
    for mark,location in enumerate(types):
        houseData.ocean_proximity_value[houseData.ocean_proximity==location]=mark
    newtype=[]
    for i in houseData['ocean_proximity_value']:
        if i not in newtype:
            newtype.append(i)
    print(newtype)
    >>>
    [0, 1, 2, 3, 4]
    

    我们首先添加了ocean_proximity_value这一列来储存转化的数值,初值全为0

    enumerate函数的功能是将列表的值与索引绑定起来,形成一个元组,在这里是type最初为[‘NEAR BAY’, ‘<1H OCEAN’, ‘INLAND’, ‘NEAR OCEAN’, ‘ISLAND’]

    我们使用enumerate绑定之后返回的结果就是[(0,‘NEAR BAY’), (1,’<1H OCEAN’), (2,‘INLAND’), (3,‘NEAR OCEAN’), (4,‘ISLAND’)]

    然后我们使用元组赋值的方法来在每次迭代的时候同时赋值

    每次迭代内部,我们对houseData的ocean_proximity_value这一列进行修改,需要注意的是,我们使用的属性查值,而非索引查值,这样避免了链式索引带来的问题

    接下来对数据进行分割

    houseLabel=houseData['median_house_value'].copy()
    houseData.drop(['median_house_value','ocean_proximity'],axis=1,inplace=True)
    X_train,X_test,y_train,y_test=train_test_split(houseData.values,houseLabel.values,test_size=0.3,random_state=42)
    scaler=StandardScaler()
    X_train=scaler.fit_transform(X_train)
    X_test=scaler.fit_transform(X_test)
    print(X_train.shape)
    print(X_test.shape)
    >>>
    (14448, 9)
    (6192, 9)
    

    数据特征可视化

    接下来我们训练数据集的九个特征进行可视化

    首先是箱须图,来了解训练数据集的9个特征的分布

    colnames=houseData.columns.values
    print(colnames)
    plt.figure(figsize=(20,8))
    for ii,name in enumerate(colnames):
        plt.subplot(5,2,ii+1)
        sns.boxplot(x=X_train[:,ii])
        plt.title(name)
    plt.subplots_adjust(hspace=0.6)
    plt.show()
    

    在这里插入图片描述

    接下来我们绘制所有特征之间的相关系数热力图

    dataCor=np.corrcoef(X_train,rowvar=0)
    dataCor=pd.DataFrame(dataCor,columns=colnames,index=colnames)
    plt.figure(figsize=(8,6))
    sns.heatmap(dataCor,square=True,annot=True,fmt='.3f',linewidths=.5,cmap='YlGnBu',
               cbar_kws={'fraction':0.046,'pad':0.03})
    plt.show()
    

    在这里插入图片描述

    最后,我们将数据转换为Tensor,便于下面的网络计算

    X_train=torch.from_numpy(X_train.astype(np.float32))
    y_train=torch.from_numpy(y_train.astype(np.float32))
    X_test=torch.from_numpy(X_test.astype(np.float32))
    y_test=torch.from_numpy(y_test.astype(np.float32))
    
    train_data=Data.TensorDataset(X_train,y_train)
    test_data=Data.TensorDataset(X_test,y_test)
    train_loader=Data.DataLoader(dataset=train_data,batch_size=64,shuffle=True,num_workers=1)
    

    搭建网络并可视化结构

    我们首先搭建如下的网络

    class FullyConnectedNuralNetwork(nn.Module):
        def __init__(self):
            super(FullyConnectedNuralNetwork,self).__init__()
            self.hidden1=nn.Sequential(
                    nn.Linear(in_features=9,out_features=100,bias=True),
                    nn.ReLU())
            self.hidden2=nn.Sequential(
                    nn.Linear(in_features=100,out_features=100,bias=True),
                    nn.ReLu())
            self.hidden3=nn.Sequential(
                    nn.Linear(in_features=100,out_features=50,bias=True),
                    nn.ReLU())
            self.predict=nn.Sequential(
                    nn.Linear(in_features=50,out_features=1,bias=True),
                    nn.ReLU())
        def forward(self,x):
            x=self.hidden1(x)
            x=self.hidden2(x)
            x=self.hidden3(x)
            x=self.predict(x)
            return x
    

    接下来使用torchviz中的make_dot来进行可视化

    from torchviz import make_dot
    fcNet=FullyConnectedNuralNetwork()
    x=torch.randn(size=(1,9)).requires_grad_(True)
    y=fcNet(x)
    fcNetArchitecture=make_dot(y,params=dict(list(fcNet.named_parameters())+[('x',x)]))
    fcNetArchitecture.directory='/home/jack/图片/houseNet.png'
    fcNetArchitecture.view()
    

    在这里插入图片描述

    训练网络

    老生长谈,上代码

    from sklearn.metrics import accuracy_score
    logStep=25
    train_loss_all=[]
    for epoch in range(30):
        train_loss=0
        train_num=0
        for step,(batch_x,batch_y) in enumerate(train_loader):
            output=fcNet(batch_x)
            loss=lossFunc(output,batch_y)
            optimizerAdam.zero_grad()
            loss.backward()
            optimizerAdam.step()
            
            train_loss_=loss.item()*batch_x.size(0)
            train_num+=batch_x.size(0)
        train_loss_all.append(train_loss/train_num)
    

    由于是回归问题,最后的输出是一个值,因此直接记录每次的损失即可

    (未完待续)
    最近大二刚开学,作业有点多,诸位看官见谅,最后一个训练的代码得到的训练结果有问题,还没debug,过几天有时间了再写
    本教程会一直持续到使用Pytorch实现各种网络

    展开全文
  • 深度学习初步,全连接神经网络,MLP从原理到实现(二)原理部分,过拟合,激活函数,batchsize和epochs,训练DL模型的建议 深度学习初步,全连接神经网络,MLP从原理到实现(三)实现部分,用java实现MLP 下面的...

    其他两篇:

    深度学习初步,全连接神经网络,MLP从原理到实现(二)原理部分,过拟合,激活函数,batchsize和epochs,训练DL模型的建议

    深度学习初步,全连接神经网络,MLP从原理到实现(三)实现部分,用java实现MLP

    下面的内容主要是李宏毅老师的机器学习课程,加上自己的整理和补充,文章有点长,有一定的ml基础,认真读就能搞懂,数学部分建议自己手写推导。如果对反向传播部分没有理解,强烈建议多听几遍李宏毅老师机器学习中的bp部分。b站就有资源。

    1.多层全连接神经网络

    如图是一个多层全连接神经网络,input层是输入层,Layer[1]Layer[L-1]是隐层,Layer[L]是输出层,层与层之前每两两个单元(神经元或者输出/输入单元)之间存在连接,代表着一个权重,单个神经元干什么事呢?

    前一层的输出作为当前层的输入,用权重与输入之间的乘积和+偏置的值Z作为到激活函数的输入,激活函数的值输出到下一层,这里Z的计算和回归中没有区别,如果激活函数是sigmoid就成了logistic回归。

    变量命名约定和矩阵化运算:

    所有变量上标代表所处的神经网络的第几层

    表示L-1层神经元jl层中神经元i连接的权重

    将l-1和l之间的权重排列成矩阵:

    这样看矩阵中行的大小就是第L层的神经元个数,矩阵的列就是第L-1层的神经元个数,矩阵中的一行表示了l层中神经元i所连接的l-1层的所有权重。

    考虑偏置:

    表示第l层第i个神经元和上一层l-1的偏置,这样l层的所有偏置值构成一个向量。

    前面提到Z值是输入和权重的乘积和加上偏置。

    这里用表示这个值,这也是激活函数的输入值

    那么l层第i个神经元的z值可以表示为:

     

    这样,l层所有神经元Z值可以矩阵化运算

    输入到激活函数,其输出值将作为l+1层的输入

    矩阵运算可以并行,所以可以使用gpu加速。

     

    问题:

    (1)将多个线性层叠在一起意味着什么?为什么效果好?

    单层线性模型表达不够强,我认为一定程度上参数越多对数据拟合越好,越能深层次挖掘数据的特征,这就好像CRF和HMM的对比,CRF参数更多,效果往往也更好,而CRF这些特征组合都是人为定义的。多层神经网络中可以把中间的隐层认为是一个Feature extractor(特征提取器),不必像CRF那样去自己定义特征,实际上要定义好的有效的特征是很难的,比如面对音频,图像这种数据定义特征就很麻烦,使用深度学习的方法比传统机器学习方法就好得多。自然语言人是能够理解的,所以在nlp中人为定义的特征就可以达到比较好的效果。

     

     

    (2)深度学习的“深”

    举例:ImgNet比赛的神经网络深度

    可以看到随着层数越多错误率不断下降,一定是这样吗?为什么往宽度走,也就是降低层次,提升单层的神经元的数量

     

    (3).仅仅是多层全连接的神经网络就需要调整很多参数。多少层?每层神经元多少个?使用什么激活函数?优化算法?代价函数?

     

    2.多层全连接神经网络中的反向传播

    损失函数有很多均方误差,交叉熵损失函数等等。

    把所有样本的损失值加起来为总的损失,参数即为神经网络中的权重,将总的损失优化到最小即为最终的权重参数,优化使用梯度下降,只不过可能是各种梯度下降的变形。

    如何计算用于更新参数的偏微分 是一个重要的问题。

     

    补充:链式求导法则

    要计算 这里L是总的损失,这里求导举例只举例单个样本对参数求导,总的直接所有样本加起来就行,所以以l代表单个样本的损失值。

    反向传播:

    为了使用梯度下降,需要求出梯度,也就是损失函数L关于权重w的一阶导数。设有N个样本,那么:

    因为多个样本和单个样本求梯度没什么差别,所以下面的例子以求单个样本的损失函数(以l表示)对w的导数为例。类似的,专注损失l对某个特定的w的导数而不是所有w,因为其他w的求法都可以类似得到。

    对于这样一个简单的nn结构:

    关注左上角的局部部分:

    损失函数l是在NN的输出端形成的,要求出l对w1的导数,就要利用开始提到的链式求导法则。

    Z的值直接影响到了 ,所以链式求导从这里开始。

    因为:

    很容易直接得到就是x1,因为这里是输入层后的隐层,所以是x1,如果不是,直观的后面任意层的 就是前一层的输入a

    没有 这么容易计算,因为z还影响了下一层的输入a,而a又进一步影响后面层的w,这种影响一直延续下去直到输出层。

     

    仔细想想这里的Z就类似上图种的s,只不过NN结构中,Z影响到的变量要比图中的s更多。

    接着,继续对 展开,Z紧接着送到了激活函数σ中,产生了a。所以:

     

    就是激活函数的导数,写成

    继续写出

    根据链式法则:

    所以:

    如果z'和z''不是输出层,那么这个过程还有继续进行下去。我们把这个过程看作逆向的:

    我们将求 这个过程反过来看:

    比如:

    我们要求 ,那么可以分为2个步骤,

    前向传播求出

    反向传播求

    就是上一层的输出,本层的输入

    需要从输出层开始计算。

    有了 那么前面的 就可以反向回去。

    比如:

    这样从后往前计算就可以算出所有的 ,最后将 乘起来就可以得到 。(注意这里的思维要想成所有的w)

     

    下面举一个实际的例子:

     

    NN结构如图,规定激活函数使用sigmoid,损失函数使用交叉熵,输出层[y1,y2]使用softmax。输入单个样本x1,x2=1,2,y=[1,0](one-hot编码表示类别是y1)。

    补充:softmax和交叉熵输出层的求导。

    参考:https://blog.csdn.net/qian99/article/details/78046329

    最后一层softmax做激活函数,那么输出a的表达式为:

    z就是上一层的输入和权重的乘积求和再加上b

    激活函数σ(z):

    损失函数:

    这里l是单个样本,求和是因为多个类别,比如总共有3个类别,如果某个样本的真实类别是2,那么标签是一个向量[0 1 0],遍历就是要遍历这个向量, 就是指不同类别的真实值(这里就只有y2=1,其他为0), 就是经过softmax后不同类别的概率分布。

    要求的是:

    这里 代表单个样本的损失,如果是多个样本只需要求和:

     

    因为 直接影响了a的值,而因为softmax的特效,所有a的分母部分都包含了 影响了所有a的值:

    根据链式法则:

     

    先来计算 ,因为 ,只对 求偏导,所以其他 均当作常数项。那么:

    再计算 ,需要分情况讨论,因为j=i时,a的分子部分含有

    当i=j:

    当i≠j时:

     

     

    将上面2种情况组合起来:

    所以最后:

    有了上面的例子开始计算:

    输如样本x=[1,2],y=[1,0],权重初始如图,偏置b都为0.1

    (1)先进行一次前向传播,计算所有的神经元输出输出a:

    (2)反向传播计算梯度

    符号说明:

    表示第l(不包含输入层)层第i(从上往下数)个单元产生的z值

    表示第l层第x个单元与第l-1层第y个单元之间连接的权重。

    计算

    第3层:

    第2层:

    第1层:

    有了 ,计算 就很简单了:比如:

    (3)向量化/矩阵化运算

    但是这样串行的思想不利用计算,需要把上面的计算过程向量化矩阵化。

    1)a的计算

    其他层的计算类似,输入x变为输入上一层的输出a

    2)

    其他情况类似推广。

     

    3)

     

          

    其他情况类似推广。

    可以计算梯度后就可以更新参数了。

    感谢观看,觉得不错的话可以考虑支持下我,用我的AI大师码0415在滴滴云上购买GPU/vGPU/机器学习产品可享受9折优惠,点击www.didiyun.com前往滴滴云官网。
    GPU:https://www.didiyun.com/production/gpu.html
    VGPU:https://www.didiyun.com/production/vgpu.html
    机器学习工作室(DAI):https://www.didiyun.com/production/dai.html

    展开全文
  • 所谓全连接神经网络,就是由全连接层组成的网络。简单的全连接层网络一般分为三层,分别是输入层,隐含层,输出层。当然在输出层后面还可以添加分类层,或者损失函数等特殊处理层。 对于全连接神经网络来说,网络中...
  • 全连接神经网络(fully connected neural network),顾名思义,就是相邻两层之间任意两个节点之间都有连接。全连接神经网络是最为普通的一种模型(比如和CNN相比),由于是全连接,所以会有更多的权重值和连接,因此...
  • 卷积神经网络架构

    万次阅读 多人点赞 2018-11-20 17:14:48
    卷积神经网络在图像分类数据集上有非常突出的表现,由于一般正常的图像信息过大,如果使用全连接神经网络,需要设置大量的权值w和basic值,这样会导致运算效率较低,还容易导致过分拟合的问题。 1.全连接神经网络和...
  • 为何叫pytorch 按照官网安装,一般是两行命令,第一行装的是...torch自称是神经网络届的numpy,numpy会把array放到CPU中加速计算,torch会把tensor放到GPU中加速计算。torch和numpy有很多用法是一样的,只不过num...
  • 中显示的全连接神经网络结构和卷积神经网络的结构直观上差异比较大,但实际上它们的整体架构是非常相似的。从中可以看出,卷积神经网络也是通过一层一层的节点组织起来的。和全连接神经网络一样, 卷积神经...
  • CNN神经网络图像分类---全流程

    千次阅读 2019-07-24 22:01:35
    Hello,又是一个分享的日子,上期博主介绍了CNN神经网络文本分类----招聘信息分类,并介绍了文本在进入神经网络前的预处理工作。今天博主给大家分享的是用CNN...
  • 写在前面的话:离上一次写博客已经有些日子了,以前的工程都是在caffe平台下做的,caffe平台虽然挺好用的,但是caffe主要用于做CNN,对于其它的网络模型用起来不太方便,所以博主转战tensorflow,Google对待...
  • 0, 0, 1, 0]] * 80 +\ [[0, 0, 0, 0, 1]] * 80) 我们采用三层前向神经网络来优化这个任务, 其中每层的神经元个数取20, 初始化取 xavier initialization,优化处理器取 GradientDescentOptimizer, 学习率取 0.001, ...
  • 除了代码外,还提供《卷积神经网络(CNN)详解与代码实现》文档和《Notes on Convolutional Neural Networks》文档,其中:《卷积神经网络(CNN)详解与代码实现》主要从卷积神经网络结构、代码实现流程图以及介绍、代码...
  • 全连接神经网络与卷积神经网络的结构
  • 全连接的BP神经网络

    万次阅读 2016-04-01 10:30:45
    给出了某个全连接神经网络图。 1前向传播 1.1前向传播 分别计算第l层神经元的输入和输出; 1.1.1偏执项为1时 向量整体形式: 分量形式:   1.1.2偏执项为b时 向量整体形式: 分量形式:  
  • 反向传播算法推导-全连接神经网络

    千次阅读 2018-07-07 10:33:51
    其它机器学习、深度学习算法的全面系统讲解可以阅读《机器学习-原理、算法与应用》...全连接神经网络(多层感知器模型,MLP),卷积神经网络(CNN),循环神经网络(RNN)中都有它的实现版本。算法从多元复合函数求...
  • 随着神经网络的不断发展,越来越多的人工神经网络模型也被创造出来了,其中,具有代表性的就是前馈型神经网络模型、反馈型神经网络模型以及网络. 1.前馈型神经网络模型 前馈神经网络(FeedforwardNeuralNetwork...
  • 包括:全连接前馈神经网络,卷积神经网络 表示:有向无环 信息传播:朝着一个方向(反向传播和这个不是同一个概念) 三.反馈网络 输入:向量或向量序列 包括:循环神经网络,Hopfieid网...
  • BP神经网络简单流程

    万次阅读 多人点赞 2017-12-01 09:47:29
    一、BP神经网络的概念  BP神经网络是一种多层的前馈神经网络,其主要的特点是:信号是前向传播的,而误差是反向传播的。具体来说,对于如下的只含一个隐层的神经网络模型: (三层BP神经网络模型) BP神经网络的...
  • 一、序言二、训练流程1、数据集引入2、构建网络(1)四层卷积神经网络(2)两层全连接层网络 3、模型训练4、模型评估 三、总结 一、序言    本文承接第一部分,基于对卷积神经网络网络组成的认识,开始学习如何去...
  • 嵌入算法到图神经网络

    千次阅读 多人点赞 2019-08-13 15:12:25
    图神经网络,广泛应用于社交关系、知识图谱、推荐系统、蛋白质分子建模,同样源自于对传统领域的创新,它的前身是嵌入算法;而嵌入算法又以数据作为载体。这一关系,将贯穿本文始末,成为我们
  • 全连接网络原理

    千次阅读 2019-11-16 14:09:28
    全连接网络原理 上一期介绍了只包含单隐层的浅层全连接网络,本期介绍更具有普遍性的深层全连接网络。推荐先看一下上期的内容,将更有助于理解。...下为一个2分类问题的四层结构全连接网络。 2. 原...
  • 使用卷积神经网络进行图像分类

    千次阅读 多人点赞 2021-02-23 22:36:21
    介绍卷积神经网络属于深度学习的子域。深度学习中的算法以与人脑相同的方式来处理信息,但其规模很小,因为我们的大脑太复杂了(我们的大脑大约有860亿个神经元)。为什么使用CNN进行图像分类?...
  • 反馈神经网络算法

    万次阅读 多人点赞 2019-01-17 17:23:37
    典型的卷积神经网络,开始阶段都是卷积层以及池化层的相互交替使用,之后采用全连接层将卷积和池化后的结果特征全部提取进行概率计算处理。 在具体的误差反馈和权重更新的处理上,不论是全连接层的更新还是卷积层的...
  • 这篇文章将逐一介绍下面这张图片中的27种神经网络类型,并尝试解释如何使用它们。准备好了吗?让我们开始吧! 神经网络的种类越来越多,可以说是在呈指数级地增长。我们需要一个一目了然的图表,在这些新出现的网络...
  • 利用神经网络进行波士顿房价预测

    千次阅读 2021-05-17 21:51:52
    前一阵学校有五一数模节校赛,和朋友一起参加做B题,波士顿房价预测,算是第一次自己动手实现一个简单的小网络吧,虽然很简单,但还是想记录一下。 题目介绍 ​    波士顿住房数据由哈里森和鲁宾...
  • 对于刚接触神经网络的人,理解了网络层级之后就是要自己搭建网络,设置参数,这个时候就需要计算参数,特征尺寸,输出维度等,这个其实看一遍流程,动手测试一下就懂了,所以我也在这里记录一下。 不同的框架,...
  • 长文详解图神经网络

    千次阅读 2020-08-17 22:55:56
    因此,本文试图沿着图神经网络的历史脉络,从最早基于不动点理论的图神经网络(Graph Neural Network, GNN)一步步讲到当前用得最火的卷积神经网络(Graph Convolutional Neural Network, GCN), 期望通过本文带给...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,886
精华内容 7,154
关键字:

全连接神经网络流程图