神经网络-万能近似定理的探索

神经网络-万能近似定理的探索

对于这个实验博主想说,其实真的很有必要去好好做一下,很重要的一个实验。

1.理论介绍

万能近似定理: ⼀个前馈神经⽹络如果具有线性层和⾄少⼀层具有 “挤压” 性质的激活函数(如 sigmoid 等),给定⽹络⾜够数量的隐藏单元,它可以以任意精度来近似任何从⼀个有限维空间到另⼀个有限维空间的 borel 可测函数。

在这里插入图片描述
在这里插入图片描述

我们可以通过两个 sigmoid 函数 (y = sigmoid(w⊤x + b)) ⽣成⼀个 tower,如图:
在这里插入图片描述
我们构造多个这样的 tower 近似任意函数:
在这里插入图片描述

2.数据集介绍

使用PyTorch库来执行数值计算,首先通过 torch.linspace 函数创建了一个从0到3的等差数列,其元素数量由变量 sample_num 决定。接着定义了一个多项式函数 function,它接受一个参数 x 并返回 x + x**3 + 3 的值。最后,代码通过将 x_data 作为输入应用 function 函数,计算并存储了每个数据点对应的函数值到 y_real 变量中,从而实现了对一系列数据点的生成。


sample_num=300
torch.manual_seed(10)

x_data=torch.linspace(0,3,sample_num)


def function(x):
  return x+x**3+3



y_real=function(x_data)

3.实验过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所有代码如下:

#coding=gbk

import torch
from torch.autograd import Variable
from torch.utils import data
import matplotlib.pyplot as plt

neuron_num=200
batch=50
learn_rating=0.005
epoch=1000


#print(x_data)

sample_num=50
torch.manual_seed(10)

x_data=torch.linspace(0,3,sample_num)


def function(x):
  return x+x**3+3



y_real=function(x_data)
#print(y_real)

wz=torch.rand(neuron_num)
#print(wz)
w=torch.normal(0,1,size=(neuron_num,))
b=torch.normal(0,1,size=(neuron_num,))
w2=torch.normal(0,1,size=(neuron_num,))
b2=torch.normal(0,1,size=(1,))
#print(w,b)


def sampling(sample_num):
   
    #print(data_size)
    index_sequense=torch.randperm(sample_num)
    return index_sequense
def activation_function(x):
    return 1/(1+torch.sigmoid(-x))


def activation_function2(x):
   
   # print(x.size())
    a=torch.rand(x.size())
    for i in range(x.size(0)):
        if x[i]<=0:
            a[i]=0.0
        else:
            a[i]=x[i]
    return a
def hidden_layer(w,b,x):
   # print("x:",x)
    return activation_function2(w*x+b)

def  fully_connected_layer(w2,b2,x):
    return torch.dot(w2,x)+b2

def net(w,b,w2,b2,x):
    #print("w",w)
    #print("b",b)
    o1=hidden_layer(w,b,x)
    #print("o1",o1)
    #print("w2",w2)
    #print("b2",b2)
    o2=fully_connected_layer(w2,b2,o1)
 #   print("o2",o2)

    return o2

def get_grad(w,b,w2,b2,x,y_predict,y_real):
  

    o2=hidden_layer(w,b,x)

    l_of_w2=-(y_real-y_predict)*o2
    l_of_b2=-(y_real-y_predict)

    a=torch.rand(o2.size())
    for i in range(o2.size(0)):
        if o2[i]<=0:
            a[i]=0.0
        else:
            a[i]=1
    l_of_w=-(y_real-y_predict)*torch.dot(w2,a)*x
    l_of_b=-(y_real-y_predict)*torch.dot(w2,a)

    return l_of_w2,l_of_b2,l_of_w,l_of_b

def loss_function(y_predict,y_real):
    #print(y_predict,y_real)
    return torch.pow(y_predict-y_real,2)
loss_list=[]

torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def train():
    global w,w2,b,b2
    index=0
    index_sequense=sampling(sample_num)
    for i in range(epoch):
        
        
   
        W_g=torch.zeros(neuron_num)
        b_g=torch.zeros(neuron_num)
        W2_g=torch.zeros(neuron_num)
        b2_g=torch.zeros(1)
        loss=torch.tensor([0.0])
           
        for k in range(batch):
              try:
                   # print("x",x_data[index],index)
                   # print("w",w)
                        y_predict=net(w,b,w2,b2,x_data[index_sequense[index]])

                        get_grad(w,b,w2,b2,x_data[index_sequense[index]],y_predict,y_real[index_sequense[index]])
                      
                        l_of_w2,l_of_b2,l_of_w,l_of_b= get_grad(w,b,w2,b2,x_data[index_sequense[index]],y_predict,y_real[index_sequense[index]])
                        W_g=W_g+l_of_w
                        b_g=b_g+l_of_b
                        b2_g=b2_g+l_of_b2
                        W2_g=W2_g+l_of_w2
                        loss=loss+loss_function(y_predict,y_real[index_sequense[index]])
                        index=index+1
              except:
                        index=0
                      #  index_sequense=sampling(sample_num)
        print("****************************loss is :",loss/batch)
        loss_list.append(loss/batch)
     
        W_g=W_g/batch
        b_g=b_g/batch
        b2_g=b2_g/batch
        W2_g=W2_g/batch
        w=w-learn_rating*W_g
        b=b-learn_rating*b_g
        w2=w2-learn_rating*W2_g
        b2=b2-learn_rating*b2_g
y_predict=net(w,b,w2,b2,x_data[0])
train()
y_predict=[]
for i in range(sample_num):
  y_predict.append(net(w,b,w2,b2,x_data[i]))

epoch_list=list(range(epoch))
plt.plot(epoch_list,loss_list,label='SGD')
plt.title("loss")
plt.legend()

plt.show()

plt.plot(x_data,y_real,label='real')
plt.plot(x_data,y_predict,label='predict')
plt.title(" Universal Theorem of Neural Networks")
plt.legend()
plt.show()
print(w,b,w2,b2)

4.总结

(1)相比较之下,tanh函数比sigmoid函数效果要好很多,但是如果,神经元数量足够,训练足够充分,两者效果会差不多。在训练不够充分,神经元不够多,学习率等条件限制下,tanh函数表现更好。
(2)神经元数量越多的情况下,模型性能在不断提升,但是学习越来越慢,如果采用随机梯度下降或者小批量梯度下降,最好增加神经元,否则,学习最终性能会受到很大限制。
(3)对于不同数量的神经元,最优学习率是在变化的。
(4)如果采用随机梯度下降或者小批量梯度下降,样本不能反应总体规律,那么网络要足够大,才能进行规律的总结,否则,最好采用批量梯度下降去处理问题。
(5)不同的超参数设置,最终学习的性能会有瓶颈,需要进行学习策略,超参数的调节,才能不断提高模型效果。

相关推荐

  1. 万能近似定理

    2024-06-18 11:38:04       21 阅读
  2. 一个万能在线图片格式转换网站

    2024-06-18 11:38:04       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-18 11:38:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-18 11:38:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-18 11:38:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-18 11:38:04       20 阅读

热门阅读

  1. 如何在pandas创建一个seris结构?

    2024-06-18 11:38:04       9 阅读
  2. 使用 Web Share API 分享内容

    2024-06-18 11:38:04       9 阅读
  3. MLIR。

    2024-06-18 11:38:04       5 阅读
  4. 高级优化理论与方法(十五)

    2024-06-18 11:38:04       6 阅读
  5. Linux 网络请求工具:curl

    2024-06-18 11:38:04       4 阅读
  6. 系统日志排查:Linux应急响应与溯源技术

    2024-06-18 11:38:04       8 阅读
  7. Python - 一个恶意脚本

    2024-06-18 11:38:04       6 阅读
  8. Git 克隆 GitHub 仓库时遇到了 SSL 证书问题

    2024-06-18 11:38:04       8 阅读