零基础学习人工智能—Python—Pytorch学习(六)
前言
本文主要讲神经网络的上半部分。
这篇文章开始有很多公式了,这些公式都很简单,但是如果是不经常在脑海里思考公式的人,那可能需要多花点时间做一下自我训练,个人感觉,也就几天时间,就能把自己感觉给调整出来。
习惯了公式看下面内容就会轻松很多,另外如果要深入学习人工智能,熟练的认知公式也是个必须的事情。
另外,我发现我前面文章写的有歧义的地方还是挺多,虽然,已经改了一部分,但,可能还有没发现的,大家看的时候尽量多理解着看吧。
本着目的是学会使用神经网络的开发,至于数学的部分,就能过就过吧。
神经网络
先学个例子
先结合以前的知识理解一个例子,理解了这个例子,后面理解神经网络就容易多了。
class NeuralNet1(nn.Module):
def __init__(self, input_size, hidden_size):
super(NeuralNet1,self).__init__()
self,linear1 = nn.Linear(input_size, hidden_size) # x的列 转成 隐藏层的列
self.relu = nn.ReLU() #使用了ReLU(Rectified Linear Unit) 作为激活函数
self.linear2 = nn.Linear(hidden_size,1) #隐藏层的列转成1列
def forward(self, x):
out = self.linear1(x)
out = self.relu(out)
out = self.linear2(out)# sigmoid at the end
y_pred = torch.sigmoid(out)
return y_pred
model=NeuralNet1(input_size=28*28,hidden_size=5)
criterion =nn.BCELoss()
结合我们之前的知识,上面代码就是定义了一个类,该类继承了Module。
然后初始化函数接受了两参数,俩参数分别是x列,和隐藏层列,然后定义三个对象linear1,linear2,relu。
然后forward就是执行,中间的转换逻辑是x列转成hidden列,hidden列转1列,这中间再加一个激活函数,我们先不管激活函数是什么,反正,代码结构,大概就是这样的逻辑。
criterion =nn.BCELosS()是定义损失函数,BCELoss 的全称是 Binary Cross Entropy Loss(二元交叉熵损失)。
ps:大家有没有注意到,自从我们开始使用model后,就再也没使用 requires_grad来开启张量计算了,这是因为model在计算的时候自己就开了【torch.tensor(0.0, requires_grad=True)】
激活函数
激活函数其实也是函数,就是把x进行一下数据转换。
我们上篇文章已经使用过了Sigmoid把数据转换成百分比了。
下面看一下最受欢迎的激活函数都有什么,如下:
# Most popular activationfunctions
# 1. Step function
# 2. Sigmoid
# 3. TanH
# 4. ReLU (不知道用什么,就用这个)
# 5. Leaky ReLU6. Softmax
各个激活函数x转换成y的模式
激活函数使用参考下面代码
import torch
import torch.nn as nn
import numpy as np
import torch.nn.functional as F #nn不好使时,在这里找激活函数
# 方法1 (create nn modules)
class NeuralNet(nn.Module):
def __init__(self, input_size, hidden_size):
super(NeuralNet, self)._init ()
self.linear1 =nn.Linear(input_size,hidden_size)
self.relu = nn.ReLU()
self.linear2 =nn.inear(hidden_size,1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
out = self.linear1(x)
out = self.relu(out)
out = self.linear2(out)
out = self.sigmoid(out)
return out
# 方法2 (use activation functions directly in forward pass)
class NeuralNet(nn.Module):
def __init__(self, input_size, hidden_size):
super(NeuralNet,self).__init__()
self.linear1 =nn.Linear(input_size,hidden_size)
self.linear2 =nn.Linear(hidden_size,1)
def forward(self,x):
# F.leaky_relu() #leaky_relu使用方法
out = torch.relu(self.linear1(x))
out = torch.sigmoid(self.linear2(out))
return out
函数
我们先对下面函数进行一下逻辑理解。
sigmoid,MSELoss,BCELoss
前面我们使用了MSELoss做损失函数,他的逻辑是求y预测和y差的平方的均值,如下图:
后面我们的例子里,就把MSELoss换成了BCELoss,当时我们就是把他当做一个求损失值的函数,没研究他的逻辑。
BCELoss的全称是 Binary Cross Entropy Loss(二元交叉熵损失)他的公式是这样的。
经过这个转换y_pred的值范围已经是(0, 1)了。
后来在写例子的时候,在前向传播的时候,又增加了torch.sigmoid做数据转换。
sigmoid的公式是这样的。
softmax和cross_entropy
cross_entropy是 交叉熵损失函数,他的公式是这样的。
结合代码理解。
下面代码是一个正向传播,这个传播就直接使用了nn.CrossEntropyLoss(交叉熵损失函数)了。
通过正向传播,我们对x进行了一次预测。
x = np.array([2.0, 1.0, 0.1])
loss = nn.CrossEntropyLoss()
Y= torch.tensor([0]) #这y是一行一列矩阵,但值0表示类别,如0=猫,1=狗,2=兔子
#nsamples x nclasses=1x3 1行3列
Y_pred_good = torch.tensor([[2.0,1.0, 0.1]]) # 这个预测的y里,2最大,2的索引是0.所以,这个预测的y最可能是猫
Y_pred_bad = torch.tensor([[0.5,2.0,0.3]]) # 这个预测的y里,2最大,2的索引是1.所以,这个预测的y最可能是狗
l1= loss(Y_pred_good, Y)
l2 = loss(Y_pred_bad, Y)
print(l1.item())
print(l2.item())
_,predictions1 = torch.max(Y_pred_good, 1)
_,predictions2 = torch.max(Y_pred_bad, 1)
print(predictions1)
print(predictions2)
多个类别的预测如下:
x = np.array([2.0, 1.0, 0.1])
loss = nn.CrossEntropyLoss()
Y= torch.tensor([2,0,1]) #这y是一行三列矩阵,但值表示的含义是类别,如2,0,1=猫,0,1,2=狗,2,1,0=兔子
#nsamples x nclasses=3x3 3行3列
Y_pred_good = torch.tensor([[2.0,1.0, 2.1],[2.0,1.0, 0.1],[2.0,3.0, 0.1]]) # 这个预测的y里,三个张量的最大值的索引分别是 2,0,1 ,他跟上面的猫的类别一致,所以是猫这个类别,因为Y的值就代表猫,所以这个是一个好的预测
Y_pred_bad = torch.tensor([[0.5,2.0,0.3],[0.5,2.0,0.3],[0.5,2.0,0.3]]) # 这个预测跟Y不匹配,所以是个不好的预测
l1 = loss(Y_pred_good, Y)
l2 = loss(Y_pred_bad, Y)
print(l1.item())
print(l2.item())
_,predictions1 = torch.max(Y_pred_good, 1) #values, indices = torch.max(input, dim)
_,predictions2 = torch.max(Y_pred_bad, 1)
print(predictions1)
print(predictions2)
Softmax 激活函数
假设你有一个模型输出的向量 [2.0, 1.0, 0.1],应用 Softmax 函数可以将其转换为 [0.7, 0.2, 0.1],表示各个类别的概率分布。
公式如下:
结合代码理解,这也是个正向传播,通过计算,将向量转换成了0~1之间的数。
# 之前把预测的y都转成了0~1之间的概率值,现在可以用softmax处理
# softmax
def softmax(x):
return np.exp(x)/np.sum(np.exp(x), axis=0)
x = np.array([2.0, 1.0, 0.1])
outputs = softmax(x)
print('softmax numpy:', outputs)
torch的softmax使用。
x= torch.tensor([2.0,1.0,0.1])
outputs = torch.softmax(x, dim=0)
print(outputs)
CrossEntropyLoss内部会先申请Softmax函数的执行,在调用自己的计算逻辑(就是对数计算那一套)。
Dataset
这段代码是Dataset和DataLoader的逻辑,简单理解一下即可。
dataset是可以使用索引获取样本和标签。
# https://gist.github.com/tijptjik/9408623 下获取wine.csv
import torch
import torchvision
from torch.utils.data import Dataset, DataLoader
import numpy as np
import math
import os
class WineDataset(Dataset):
def __init__(self, transform=None):
# data loading
# 获取脚本所在的目录
script_dir = os.path.dirname(__file__)
# 构建文件的完整路径
file_path = os.path.join(script_dir, 'wine.csv')
xy = np.loadtxt(file_path, delimiter=",", dtype=np.float32, skiprows=1)
self.x = xy[:, 1:]
self.y = xy[:, [0]] # nsamples, 1
self.n_samples = xy.shape[0]
self.transform = transform
def __getitem__(self, index):
sample = self.x[index], self.y[index]
if (self.transform):
sample = self.transform(sample)
return sample
def __len__(self):
return self.n_samples
class ToTensor:
def __call__(self, sample):
inputs, targets = sample
return torch.from_numpy(inputs), torch.from_numpy(targets)
dataset = WineDataset(transform=ToTensor())
first_data = dataset[0]
feautres, labels = first_data
print(feautres)
print(type(feautres), type(labels))
dataloader也是一个迭代器,用于将 Dataset 中的数据按批次(batch)加载,并支持打乱(shuffle)、多线程加速(num_workers)等功能。
dataloader = DataLoader(dataset=dataset, batch_size=4, shuffle=True, num_workers=2)
for data, labels in dataloader:
print(data, labels)
传送门:
零基础学习人工智能—Python—Pytorch学习(一)
零基础学习人工智能—Python—Pytorch学习(二)
零基础学习人工智能—Python—Pytorch学习(三)
零基础学习人工智能—Python—Pytorch学习(四)
零基础学习人工智能—Python—Pytorch学习(五)
零基础学习人工智能—Python—Pytorch学习(六)
零基础学习人工智能—Python—Pytorch学习(七)
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!