提交 38c2ecde 编写于 作者: W wizardforcel

2021-01-17 16:32:15

上级 27bb5cf1
......@@ -77,17 +77,18 @@
当我们希望引起您对代码块特定部分的注意时,相关行或项目以粗体显示:
word_1 =“猫”
**word_2 ='dog'**
word_3 =“鸟”
```py
word_1 = 'cat'
word_2 = 'dog'
word_3 = 'bird'
```
任何命令行输入或输出的编写方式如下:
$ mkdir flaskAPI
$ cd flaskAPI
```py
$mkdir flaskAPI
$cd flaskAPI
```
**粗体**:表示新术语,重要单词或您在屏幕上看到的单词。 例如,菜单或对话框中的单词会出现在这样的文本中。 这是一个示例:“从**管理**面板中选择**系统信息**。”
......
......@@ -16,25 +16,29 @@
像大多数 Python 软件包一样,PyTorch 的安装非常简单。 这样做有两种主要方法。 首先,要使用命令行中的`pip`简单地安装。 只需键入以下命令:
点安装火炬 torchvision
```py
pip install torch torchvision
```
尽管此安装方法很快,但建议使用 Anaconda 进行安装,因为它包括运行 PyTorch 所需的所有依赖项和二进制文件。 此外,稍后将需要 Anaconda 使用 CUDA 在 GPU 上启用训练模型。 可以在 Anaconda 中通过在命令行中输入以下内容来安装 PyTorch:
康达安装火炬 torchvision -c pytorch
```py
conda install torch torchvision -c pytorch
```
要检查 PyTorch 是否正常工作,我们可以打开 Jupyter 笔记本并运行一些简单的命令:
1. 要在 PyTorch 中定义一个张量,我们可以执行以下操作。
进口火炬
x = torch.tensor([1.,2。])
打印(x)
```py
import torch
x = torch.tensor([1.,2.])
print(x)
```
结果为以下输出:
**![Figure 2.1 – Tensor output ](img/B12365_02_1.png)**
![Figure 2.1 – Tensor output ](img/B12365_02_1.png)
图 2.1 –张量输出
......@@ -42,11 +46,11 @@
2. 我们可以使用标准的 Python 运算符来执行乘法等基本操作。
x = torch.tensor([1。,2.])
y = torch.tensor([3。,4.])
打印(x * y)
```py
x = torch.tensor([1., 2.])
y = torch.tensor([3., 4.])
print(x * y)
```
结果为以下输出:
......@@ -56,19 +60,22 @@
3. 我们也可以从一个张量中选择单个元素,如下。
x = torch.tensor([[1。,2。],[5。,3。],[0。,4.]])
打印(x [0] [1])
```py
x = torch.tensor([[1., 2.],[5., 3.],[0., 4.]])
print(x[0][1])
```
结果为以下输出:
![Figure 2.3 – Tensor selection output ](img/B12365_02_3.jpg)
![Figure 2.3 – Tensor selection output ](img/B12365_02_3.jpg)
图 2.3 –张量选择输出
图 2.3 –张量选择输出
但是,请注意,与 NumPy 数组不同,从张量对象中选择单个元素会返回另一个张量。 为了从张量返回单个值,可以使用`.item()`函数:
打印(x [0] [1] .item())
```py
print(x[0][1].item())
```
结果为以下输出:
......@@ -86,7 +93,9 @@
您可以通过键入以下命令来检查任何张量的大小:
形状
```py
x.shape
```
结果为以下输出:
......@@ -119,21 +128,29 @@ GPU 最初是为了有效地渲染图形而创建的,但是由于深度学习
1. 首先,为了在 PyTorch 上实际启用 CUDA 支持,您将必须从源代码构建 PyTorch。 有关如何完成此操作的详细信息,请参见以下网址:https://github.com/pytorch/pytorch#from-source。
2. 然后,要在 PyTorch 代码中实际使用 CUDA,我们必须在 Python 代码中键入以下内容。
cuda = torch.device('cuda')
```py
cuda = torch.device('cuda')
```
这会将我们的默认 CUDA 设备的名称设置为`'cuda'`。
3. 然后,我们可以通过在任何张量操作中手动指定设备参数来执行对这个设备的操作。
x = torch.tensor([5。,3.],device = cuda)
```py
x = torch.tensor([5., 3.], device=cuda)
```
另外,我们可以通过调用`cuda`方法来做到这一点:
y = torch.tensor([4.,2.])。cuda()
```py
y = torch.tensor([4., 2.]).cuda()
```
4. 然后,我们可以运行一个简单的操作,以确保这是正确的工作。
```py
x * y
```
结果为以下输出:
......@@ -180,19 +197,20 @@ PyTorch 与其他深度学习框架之间的另一个主要区别是语法。 Py
1. 首先,我们需要加载我们的训练数据集,如下。
火车= pd.read_csv(“ train.csv”)
train_labels = train ['label']。values
train = train.drop(“ label”,axis = 1).values.reshape(len(train),1,28,28)
```py
train = pd.read_csv("train.csv")
train_labels = train['label'].values
train = train.drop("label",axis=1).values.reshape(len(test),1,28,28)
```
请注意,我们将输入重塑为`[1, 1, 28, 28]`,每个张量为 1,000 张图像 由 28x28 像素组成。
2. 接下来,我们将我们的训练数据和训练标签转换为 PyTorch 张量,以便它们可以被输入到神经网络中。
X =火炬张量(train.astype(float))
y = Torch.Tensor(train_labels).long()
```py
X = torch.Tensor(train.astype(float))
y = torch.Tensor(train_labels).long()
```
注意这两个张量的数据类型。 浮点张量由 32 位浮点数组成,而长张量由 64 位整数组成。 为了使 PyTorch 能够计算梯度,我们的`X`功能必须为浮点数,而我们的标签必须为该分类模型中的整数(因为我们正在尝试预测 1、2、3 和 等等),因此 1.5 的预测就没有意义。
......@@ -200,19 +218,15 @@ PyTorch 与其他深度学习框架之间的另一个主要区别是语法。 Py
接下来,我们可以开始构造实际的神经网络分类器:
类 MNISTClassifier(nn.Module):
def __init __():
super().__ init __()
self.fc1 = nn.Linear(784,392)
self.fc2 = nn.Linear(392,196)
self.fc3 = nn.Linear(196,98)
self.fc4 = nn.Linear(98,10)
```py
class MNISTClassifier(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 392)
        self.fc2 = nn.Linear(392, 196)
        self.fc3 = nn.Linear(196, 98)
        self.fc4 = nn.Linear(98, 10)
```
我们像从 Python PyTorch 中继承`nn.Module`一样,在 Python 中构建普通类,从而构建分类器。 在我们的`__init__`方法中,我们定义了神经网络的每一层。 在这里,我们定义了大小可变的全连接线性层。
......@@ -230,7 +244,9 @@ self.fc4 = nn.Linear(98,10)
在我们的`MNISTClassifier`类的`__init__`方法中,我们还定义了一种 dropout 方法,以帮助规范网络:
self.dropout = nn.Dropout(p = 0.2)
```py
self.dropout = nn.Dropout(p=0.2)
```
辍学是一种规范化我们的神经网络以防止过拟合的方法。 在每个训练纪元上,对于已应用丢包的层中的每个节点,都有可能(此处定义为`p`= 20% )该层内的每个节点将不用于训练/反向传播 。 这意味着,在训练时,我们的网络会针对过拟合变得健壮,因为在训练过程的每次迭代中都不会使用每个节点。 这可以防止我们的网络过于依赖网络中特定节点的预测。
......@@ -238,17 +254,14 @@ self.dropout = nn.Dropout(p = 0.2)
接下来,我们在分类器中定义正向传递:
def forward(self,x):
x = x.view(x.shape [0],-1)
x = self.dropout(F.relu(self.fc1(x)))
x = self.dropout(F.relu(self.fc2(x)))
x = self.dropout(F.relu(self.fc3(x)))
x = F.log_softmax(self.fc4(x),dim = 1)
```py
def forward(self, x):
        x = x.view(x.shape[0], -1)
        x = self.dropout(F.relu(self.fc1(x)))
        x = self.dropout(F.relu(self.fc2(x)))
        x = self.dropout(F.relu(self.fc3(x)))
        x = F.log_softmax(self.fc4(x), dim=1)
```
分类器中的`forward()`方法是我们在其中应用激活函数并定义在我们的网络中应用 dropout 的位置的方法。 我们的`forward()`方法定义了输入将通过网络的路径。 首先,它获取我们的输入`x`,并将其整形以在网络中使用,并将其转换为一维向量。 然后,我们将其通过我们的第一个全连接层,并将其包装在 **ReLU** 激活函数中,以使其为非线性。 我们也将其包装在我们的[drop]中,如`__init__`方法中所定义。 我们对网络中的所有其他层重复此过程。
......@@ -258,15 +271,17 @@ x = F.log_softmax(self.fc4(x),dim = 1)
接下来,我们定义我们的模型参数:
型号= MNISTClassifier()
loss_function = nn.NLLLoss()
opt = optim.Adam(model.parameters(),lr = 0.001)
```py
model = MNISTClassifier()
loss_function = nn.NLLLoss()
opt = optim.Adam(model.parameters(), lr=0.001)
```
我们将`MNISTClassifier`类的实例初始化为模型。 我们还将的损失定义为**负对数似然损失**
损失(y)= -log(y)
```py
Loss(y) = -log(y)
```
假设我们的图像为 7。如果我们以概率 1 预测类别 7,则损失为`-log(1) = 0`,但是如果我们仅以概率 0.7 预测类别 7,则损失为 将是`-log(0.7) = 0.3`。 这意味着我们与正确预测的距离越远,损失就越接近无穷大:
......@@ -284,31 +299,37 @@ opt = optim.Adam(model.parameters(),lr = 0.001)
1. 首先,创建一个循环,为我们训练的每一个纪元运行一次。在这里,我们将在 50 个 epoch 中运行我们的训练循环。我们首先将输入的图像张量和输出的标签张量转化为 PyTorch 变量。一个**变量**是一个 PyTorch 对象,它包含一个`backward()`方法,我们可以使用该方法通过我们的网络进行反向传播。
对于范围(50)中的时代:
图片=变量(X)
标签=变量(y)
```py
for epoch in range(50):
    images = Variable(X)
    labels = Variable(y)
```
2. 接下来,我们在优化器上调用`zero_grad()`,将计算出的梯度设为零。在 PyTorch 中,梯度是在每次反向传播时累计计算的。虽然这在某些模型中很有用,例如在训练 RNNs 时,但对于我们的示例,我们希望在每个纪元后从头开始计算梯度,因此我们确保在每次通过后将梯度重置为零。
opt.zero_grad()
```py
opt.zero_grad()
```
3. 接下来,我们使用模型的当前状态对我们的数据集进行预测。这实际上是我们的正向传递,因为我们然后使用这些预测来计算我们的损失。
输出=模型(图像)
```py
outputs = model(images)
```
4. 使用输出和我们数据集的真实标签,我们使用定义的损失函数计算我们模型的总损失,在这种情况下,它是负对数似然。在计算出这个损失后,我们就可以调用`backward()`,通过网络反推我们的损失。然后,我们使用`step()`来使用我们的优化器,以便相应地更新我们的模型参数。
损失= loss_function(输出,标签)
loss.backward()
opt.step()
```py
loss = loss_function(outputs, labels)
loss.backward()
opt.step()
```
5. 最后,在每个纪元完成后,我们打印总损失。我们可以观察到这一点,以确保我们的模型正在学习。
打印('Epoch [% d /% d]损失:% .4f'% (epoch + 1,50,loss.data.item()))
```py
print ('Epoch [%d/%d] Loss: %.4f' %(epoch+1, 50, loss.data.item()))
```
一般而言,我们预计损失会在每个时期减少。 我们的输出将如下所示:
......@@ -320,23 +341,25 @@ opt = optim.Adam(model.parameters(),lr = 0.001)
现在我们的模型已经过训练,我们可以使用它对看不见的数据进行预测。 我们首先从读取我们的测试数据集(该数据未用于训练我们的模型):
测试= pd.read_csv(“ test.csv”)
test_labels = test ['label']。values
测试= test.drop(“ label”,axis = 1).values.reshape(len(test),1,28,28)
X_test =火炬张量(test.astype(float))
y_test = torch.Tensor(test_labels).long()
```py
test = pd.read_csv("test.csv")
test_labels = test['label'].values
test = test.drop("label",axis=1).values.reshape(len(test),1,28,28)
X_test = torch.Tensor(test.astype(float))
y_test = torch.Tensor(test_labels).long()
```
在这里,我们执行与加载训练数据集时相同的步骤:重新整形测试数据并将其转换为 PyTorch 张量。 接下来,要使用我们训练有素的模型进行预测,我们只需运行以下命令:
preds =模型(X_test)
```py
preds = model(X_test)
```
与我们在模型中训练数据的正向传递上计算输出的方式相同,现在我们将测试数据传递通过模型并获得预测。 我们可以像这样查看其中一张图像的预测:
打印(preds [0])
```py
print(preds[0])
```
结果为以下输出:
......@@ -348,19 +371,15 @@ preds =模型(X_test)
现在,我们可以构造一个摘要 DataFrame,其中包含我们的真实测试数据标签以及模型预测的标签:
_,projectionlabel = torch.max(preds.data,1)
projectionlabel = projectionlabel.tolist()
projectionlabel = pd.Series(predictionlabel)
test_labels = pd.Series(test_labels)
pred_table = pd.concat([predictionlabel,test_labels],axis = 1)
pred_table.columns = ['预测值','真实值']
显示(pred_table.head())
```py
_, predictionlabel = torch.max(preds.data, 1)
predictionlabel = predictionlabel.tolist()
predictionlabel = pd.Series(predictionlabel)
test_labels = pd.Series(test_labels)
pred_table = pd.concat([predictionlabel, test_labels], axis=1)
pred_table.columns =['Predicted Value', 'True Value']
display(pred_table.head())
```
结果为以下输出:
......@@ -374,11 +393,11 @@ pred_table.columns = ['预测值','真实值']
既然我们已经从模型中获得了一些预测,我们就可以使用这些预测来评估模型的质量。 如上一章所述,评估模型性能的一种基本方法是**准确率**。 在这里,我们只是将正确的预测(预测的图像标签等于实际的图像标签)计算为模型做出的预测总数的百分比:
preds = len(预测标签)
正确= len([如果 x == y,则为 zip(预测标签,test_labels)中的 x,y 为 1)
打印((正确/偏好)* 100)
```py
preds = len(predictionlabel)
correct = len([1 for x,y in zip(predictionlabel, test_labels)               if x==y])
print((correct/preds)*100)
```
结果为以下输出:
......@@ -398,31 +417,26 @@ preds = len(预测标签)
1. 首先,我们将每个句子拆分成一个单词列表,并将每个句子的语言作为标签。我们取一部分句子来训练我们的模型,并在一边保留一小部分作为我们的测试集。我们这样做是为了在训练完模型后,可以评估模型的性能。
(“这是我最喜欢的章节”。lower()。split(),\
“英语”),
(“我在图书馆”。lower()。Split(),“西班牙语”)
```py
("This is my favourite chapter".lower().split(),\
"English"),
("Estoy en la biblioteca".lower().split(), "Spanish")
```
请注意,我们还将每个单词转换为小写,这将阻止单词在单词袋中重复计算。 如果我们有单词`book`和单词`Book`,我们希望将它们视为相同的单词,因此将它们转换为小写。
2. 接下来,我们建立我们的单词索引,它只是一个语料库中所有单词的字典,然后为每个单词创建一个唯一的索引值。这可以通过一个简短的`for`循环轻松完成。
```py
word_dict = {}
我= 0
用于单词,training_data + test_data 中的语言:
逐字逐句:
如果单词不在 word_dict 中:
word_dict [word] = i
我+ = 1
打印(word_dict)
i = 0
for words, language in training_data + test_data:
    for word in words:
        if word not in word_dict:
            word_dict[word] = i
            i += 1
print(word_dict)
```
结果为以下输出:
......@@ -436,51 +450,44 @@ preds = len(预测标签)
在这里,我们定义分类器,以使其由单个线性层组成,该线性层具有对数 softmax 激活函数,近似于逻辑回归。 通过在此处添加额外的线性层,我们可以轻松地将其扩展到作为神经网络运行,但是单层参数将达到我们的目的。 请密切注意线性层的输入和输出大小:
corpus_size = len(word_dict)
语言= 2
label_index = {“西班牙文”:0,“英语”:1}
BagofWordsClassifier 类(nn.Module):
def __init __(自身,语言,语料库大小):
超级(BagofWordsClassifier,self).__ init __()
self.linear = nn.Linear(corpus_size,语言)
def forward(自己,bow_vec):
返回 F.log_softmax(self.linear(bow_vec),dim = 1)
```py
corpus_size = len(word_dict)
languages = 2
label_index = {"Spanish": 0, "English": 1}
class BagofWordsClassifier(nn.Module):  
    def __init__(self, languages, corpus_size):
        super(BagofWordsClassifier, self).__init__()
        self.linear = nn.Linear(corpus_size, languages)
    def forward(self, bow_vec):
        return F.log_softmax(self.linear(bow_vec), dim=1)
```
输入的长度为`corpus_size`,这只是我们的语料库中唯一词的总数。 这是因为对模型的每个输入都是一个词袋表示,由每个句子中的单词计数组成,如果给定单词​​未出现在我们的句子中,则计数为 0。 我们的输出大小为 2,这是我们可以预测的语言数量。 我们的最终预测将包括我们的句子是英语的概率与我们的句子是西班牙文的概率,而我们的最终预测是概率最高的那个。
4. 接下来,我们定义一些实用函数。我们首先定义`make_bow_vector`,它将句子转化为一个词袋的表示。我们首先创建一个由所有零组成的向量。然后,我们对它们进行循环,对于句子中的每一个词,我们将该词在词袋向量中的索引数增加 1。最后,我们使用`.view()`对这个向量进行重塑,以便进入我们的分类器。
def make_bow_vector(句子,word_index):
word_vec = torch.zeros(corpus_size)
对于句子中的单词:
word_vec [word_dict [word]] + = 1
返回 word_vec.view(1,-1)
```py
def make_bow_vector(sentence, word_index):
    word_vec = torch.zeros(corpus_size)
    for word in sentence:
        word_vec[word_dict[word]] += 1
    return word_vec.view(1, -1)
```
5. 同样,我们定义了`make_target`,它只是简单地取句子(西班牙语或英语)的标签,并返回其相关索引(`0``1`)。
def make_target(label,label_index):
返回 torch.LongTensor([label_index [label]])
```py
def make_target(label, label_index):
    return torch.LongTensor([label_index[label]])
```
6. 现在我们可以创建一个模型的实例,准备进行训练。我们还将我们的损失函数定义为负对数似然,因为我们使用的是对数 softmax 函数,然后定义我们的优化器,以便使用标准的**随机梯度下降****SGD**)。
模型= BagofWordsClassifier(语言,语料库大小)
loss_function = nn.NLLLoss()
优化程序= optim.SGD(model.parameters(),lr = 0.1)
```py
model = BagofWordsClassifier(languages, corpus_size)
loss_function = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)
```
现在,我们准备训练模型。
......@@ -492,27 +499,20 @@ preds = len(预测标签)
然后使用此预测,获取我们的预测标签和实际标签,并在两者上调用定义的`loss_function`,以获取此句子的损失度量。 通过向后调用`backward()`,我们通过模型反向传播此损失,并在优化器上调用`step()`,从而更新模型参数。 最后,我们每 10 个训练步骤打印一次损失:
对于范围(100)中的时代:
对于句子,在 training_data 中标记:
model.zero_grad()
bow_vec = make_bow_vector(句子,word_dict)
目标= make_target(标签,标签索引)
log_probs =模型(bow_vec)
损失= loss_function(log_probs,目标)
loss.backward()
Optimizer.step()
如果时代% 10 == 0:
print('Epoch:',str(epoch + 1),',Loss:'+ str(loss.item()))
```py
for epoch in range(100):
    for sentence, label in training_data:
        model.zero_grad()
        bow_vec = make_bow_vector(sentence, word_dict)
        target = make_target(label, label_index)
        log_probs = model(bow_vec)
        loss = loss_function(log_probs, target)
        loss.backward()
        optimizer.step()
        
    if epoch % 10 == 0:
        print('Epoch: ',str(epoch+1),', Loss: ' + str(loss.item()))
```
结果为以下输出:
......@@ -525,27 +525,20 @@ print('Epoch:',str(epoch + 1),',Loss:'+ str(loss.item())
1. 我们根据未接受模型训练的测试数据中的几句话来评估模型。 在这里,我们首先设置`torch.no_grad()`,这将停用 **autograd** 引擎,因为由于我们不再训练模型,因此不再需要计算梯度。 接下来,我们将测试句子转换为词袋向量,并将其输入模型以获取预测。
2. 然后我们只需打印出句子、句子的真实标签,再打印出预测的概率。注意,我们将预测值从对数概率转化回概率。我们为每个预测得到两个概率,但如果我们参考标签索引,我们可以看到第一个概率(索引 0)对应的是西班牙语,而另一个概率对应的是英语。
def make_predictions(data):
使用 torch.no_grad():
句子=数据[0]
标签=数据[1]
bow_vec = make_bow_vector(句子,word_dict)
log_probs =模型(bow_vec)
打印(句子)
打印(标签+':')
打印(np.exp(log_probs))
make_predictions(test_data [0])
make_predictions(test_data [1])
```py
def make_predictions(data):
    with torch.no_grad():
        sentence = data[0]
        label = data[1]
        bow_vec = make_bow_vector(sentence, word_dict)
        log_probs = model(bow_vec)
        print(sentence)
        print(label + ':')
        print(np.exp(log_probs))
        
make_predictions(test_data[0])
make_predictions(test_data[1])
```
结果为以下输出:
......@@ -557,27 +550,20 @@ print('Epoch:',str(epoch + 1),',Loss:'+ str(loss.item())
3. 在这里,我们定义了一个函数,它将一个词作为输入,并返回层内每个参数的权重。对于一个给定的词,我们从我们的字典中得到这个词的索引,然后从模型内的相同索引中选择这些参数。请注意,我们的模型会返回两个参数,因为我们是在做两个预测,即模型对西班牙语预测的贡献和模型对英语预测的贡献。
def return_params(word):
索引= word_dict [word]
对于 model.parameters()中的 p:
昏暗= len(p.size())
如果暗淡== 2:
打印(单词+':')
print('西班牙参数='+ str(p [0] [index] .item()))
print('英文参数='+ str(p [1] [index] .item()))
打印('\ n')
return_params(“我是”)
return_params('book')
```py
def return_params(word):
    index = word_dict[word]
    for p in model.parameters():
        dims = len(p.size())
        if dims == 2:
            print(word + ':')
            print('Spanish Parameter = ' + str(p[0][index].item()))
            print('English Parameter = ' + str(p[1][index].item()))
            print('\n')
            
return_params('estoy')
return_params('book')
```
结果为以下输出:
......@@ -589,9 +575,10 @@ print('Epoch:',str(epoch + 1),',Loss:'+ str(loss.item())
我们可以证明我们的模型仅基于对其进行了训练而学习。 如果我们尝试预测尚未训练过的单词,则可以看到它无法做出准确的决定。 在这种情况下,我们的模型认为英语单词`not`是西班牙语:
new_sentence =([[“ not”],“英语”)
make_predictions(new_sentence)
```py
new_sentence = (["not"],"English")
make_predictions(new_sentence)
```
结果为以下输出:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册