激活函数(activation function)的作用是去线性化,神经网络节点的计算就是加权求和,再加上偏置项:
这是一个线性模型,将这个计算结果传到下一个节点还是同样的线性模型。只通过线性变换,所有的隐含层的节点就无存在的意义。原因如下:假设每一层的权值矩阵用 W ( i ) W^{(i)} W(i) 表示,那么存在一个 W ′ W' W′ 使得:
那么,n层隐含层就可以全部变成一个隐含层,隐含层的数量就没有任何意义。所以使用激活函数将其去线性化。这样可以使 W ′ = W ( 1 ) W ( 2 ) . . . W ( n ) W'=W^{(1)}W^{(2)}...W^{(n)} W′=W(1)W(2)...W(n) 不再成立,每层隐含层都有其存在的意义。
该函数输入为任意形状,输出形状与输入形状保持一致,此操作是将所有元素映射到(0,1)范围内,推导如下:
三种用法:
1. torch.tanh(Tensor)
2. F.tanh(Tensor)
3. tanh = torch.nn.Tanh(); tanh(Tensor) # 先定义类,再调用
>>> import torch
>>> import torch.nn.functional as F
>>> inp=torch.tensor(10,dtype=torch.float32) # 标量、向量(一维)、多维tensor均可
# 第一种用法
>>> torch.sigmoid(inp)
tensor(1.0000)
# 第二种用法,目前已经被丢弃
>>> F.sigmoid(inp)
UserWarning: nn.functional.sigmoid is deprecated. Use torch.sigmoid instead. warnings.warn("nn.functional.sigmoid is deprecated. Use torch.sigmoid instead.")
tensor(1.0000)
# 第三种用法
>>> torch.nn.Sigmoid(inp) # 报错
TypeError: __init__() takes 1 positional argument but 2 were given
# 这种情况下,需要先对类实例化,也就是这样:
>>> sigmoid = torch.nn.Sigmoid()
>>> sigmoid(inp)
tensor(1.0000)
>>> import torch
>>> import torch.nn.functional as F
>>> inp=torch.tensor([10,20,5,3],dtype=torch.float32) # 向量(一维)、多维tensor均可
# 第一种用法
>>> torch.softmax(inp, dim = 0) # 须指明dim(维度)
tensor([4.5398e-05, 9.9995e-01, 3.0589e-07, 4.1397e-08])
# 第二种用法
>>> F.sigmoid(inp, dim = 0)
tensor([4.5398e-05, 9.9995e-01, 3.0589e-07, 4.1397e-08])
# 第三种用法,跟sigmoid类似
>>> softmax = torch.nn.Softmax(dim = 0) # 默认维度dim为0,也可以传其他维度
>>> softmax(inp)
tensor([4.5398e-05, 9.9995e-01, 3.0589e-07, 4.1397e-08])
softmax0 = torch.nn.Softmax(dim=0)
softmax1 = torch.nn.Softmax(dim=1)
inp = torch.tensor([[1., 4., 8.],
[8., 0., 5.]])
print("inp:",inp)
out0 = softmax0(inp)
print("out:",out0)
total_sum0 = torch.sum(out0)
print("sum:",total_sum0)
# print-------------------
inp: tensor([[1., 4., 8.],
[8., 0., 5.]])
out: tensor([[9.1105e-04, 9.8201e-01, 9.5257e-01],
[9.9909e-01, 1.7986e-02, 4.7426e-02]])
sum: tensor(3.)
print("inp:",inp)
out1 = softmax1(inp)
print("out:",out1)
total_sum1 = torch.sum(out1)
print("sum:",total_sum1)
# print------------------
inp: tensor([[1., 4., 8.],
[8., 0., 5.]])
out: tensor([[8.9468e-04, 1.7970e-02, 9.8114e-01],
[9.5227e-01, 3.1945e-04, 4.7411e-02]])
sum: tensor(2.)
1. F.elu(Tensor, alpha=1.0, inplace=False) # 直接调用
2. torch.nn.ELU( # 先定义类,再调用
alpha=1.0, # alpha默认为1
inplace=False) # 该参数可选,默认为False,若为True则表示输入变量在内存中存储的值被计算结果覆盖
1)使用方法
import torch.nn.functional as F
import torch
# 第一种用法
elu = torch.nn.ELU() # 先定义类
elu(Tensor) # 再调用
# 第二种用法
F.elu(Tensor, alpha=1.0, inplace=False)
# 1.标量
inp=torch.tensor(-2.5,dtype=torch.float32)
# tensor(-0.9179, device='cuda:0')
# 2.向量/列表
inp=torch.tensor([10,-2.5])
# tensor([10.0000, -0.9179])
# 3.二维数组
inp=torch.tensor([[1,-2.5],
[0,10]])
# tensor([[ 1.0000, -0.9179],
# [ 0.0000, 10.0000]])
2)inplace参数验证
import torch
import torch.nn as nn
inp=torch.tensor(-2.5,dtype=torch.float32).to(device)
elu=nn.ELU(inplace=False)
print("inp address:",id(inp)) # 查看变量在内存中的位置
out=elu(inp)
print("out address:",id(out))
print(out) # tensor(-0.9179, device='cuda:0')
print(inp) # 验证elu运算之后inp变量值是否被覆盖
# print------------
# inp address: 1892728046504
# out address: 1892728156304
# tensor(-0.9179, device='cuda:0')
# tensor(-2.5000, device='cuda:0')
elu=nn.ELU(inplace=True)
inp=torch.tensor(-2.5,dtype=torch.float32).to(device)
print("inp address:",id(inp)) # 查看变量在内存中的位置
out=elu(inp)
print("out address:",id(out))
print(out) # tensor(-0.9179, device='cuda:0')
print(inp) # 验证elu运算之后inp变量值是否被覆盖
# print----------
# inp address: 1924575957856
# out address: 1924575957856
# tensor(-0.9179, device='cuda:0')
# tensor(-0.9179, device='cuda:0')
两种用法同ELU,这里只介绍其中一种。
import torch.nn.functional as F
import torch
# 两种用法同ELU,这里只介绍其中一种
relu=torch.nn.ReLU()
# 1.标量
# inp=torch.tensor(2.5)
# out: tensor(2.5000)
# 2.向量
# inp=torch.tensor([2.5,0,-10,25])
# out: tensor([ 2.5000, 0.0000, 0.0000, 25.0000])
# 3.二维数组
inp=torch.tensor([[2.5,0],
[-10,25]])
# out: tensor([[ 2.5000, 0.0000],
# [ 0.0000, 25.0000]])
out=relu(inp)
print("out:",out)
f ( x ) = m i n ( m a x ( 0 , x ) , 6 ) f(x) = min(max(0, x), 6) f(x)=min(max(0,x),6)
用法,同ELU和ReLU。
import torch
relu=torch.nn.ReLU6()
# 1.标量
inp=torch.tensor(2.5)
# out: tensor(2.5000)
# 2.向量
# inp=torch.tensor([2.5,0,-10,25])
# out: tensor([ 2.5000, 0.0000, 0.0000, 6.0000])
# 3.二维数组
inp=torch.tensor([[2.5,0],
[-10,25]])
# out: tensor([[ 2.5000, 0.0000],
# [ 0.0000, 6.0000]])
out=relu(inp)
print("out:",out)
总之,Leaky ReLU函数是一种新的神经网络单元激活函数,它可以改善深度神经网络的性能,利用它改善梯度消失和抖动的问题,并可以更好地拟合模型。虽然Leaky ReLU函数有许多优点,但它也有一些缺点,在使用Leaky ReLU函数时,应该注意避免出现这些缺点。
注意此时,调用的第一种方法应该是:F.leaky_relu(),注意下划线。其余的使用方法和上面三种 LU 函数没有区别。
这里只介绍第二种方法:也就是先定义类,后调用。
torch.nn.LeakyReLU(negative_slope=0.01, inplace=False)
import torch
relu=torch.nn.LeakyReLU()
# 1.标量
# inp=torch.tensor(2.5)
# out: tensor(2.5000)
# 2.向量
# inp=torch.tensor([2.5,0,-100,25])
# out: tensor([ 2.5000, 0.0000, -1.0000, 25.0000])
# 3.二维数组
inp=torch.tensor([[2.5,0],
[-100,25]])
# out: tensor([[ 2.5000, 0.0000],
# [ -1.0000, 25.0000]])
out=relu(inp)
print("out:",out)
该函数使用方法和sigmoid类似,也有三种使用方法:
1. torch.tanh(Tensor)
2. F.tanh(Tensor)
3. tanh = torch.nn.Tanh(); tanh(Tensor)
下面只介绍第三种:
tanh=nn.Tanh()
# 1.标量
inp=torch.tensor(2.5)
# out: tensor(0.9866)
# 2.向量
# inp=torch.tensor([2.5,0,-10,25])
# out: tensor([ 0.9866, 0.0000, -1.0000, 1.0000])
# 3.二维数组
# inp=torch.tensor([[2.5,0],
# [-10,25]])
# out: tensor([[ 0.9866, 0.0000],
# [-1.0000, 1.0000]])
out=tanh(inp)
print("out:",out)
That’s all. 欢迎指正。