प्रौद्योगिकी साझेदारी

आद्यतः एव तंत्रिकाजालस्य परिकल्पना : हस्तलिखिताङ्कपरिचयस्य साक्षात्कारः

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

प्रस्तावना

तंत्रिकाजालस्य अधिकाधिकं अवगमनाय हस्तलिखित-अङ्क-परिचयस्य लघु-कार्यात् तंत्रिका-जालस्य कार्य-सिद्धान्तं सामान्य-प्रक्रिया च स्तर-स्तरं अवगन्तुं अतीव उचितम्

अयं लेखः हस्तलेखेन संख्यापरिचयकार्यं सम्पन्नं करिष्यति यत् मानकफीडफोरवर्ड-तंत्रिकाजालस्य डिजाइनं, कार्यान्वयनम्, प्रशिक्षणं च कथं करणीयम् इति व्याख्यायते, यत् तंत्रिकाजालस्य अधिकविशिष्टं बोधात्मकं च अवगमनं भवति

अवलोकनम्

विशेषतः अस्माकं 3-स्तरीयं तंत्रिकाजालं परिकल्पयितुं प्रशिक्षितुं च आवश्यकम् अस्ति एतत् तंत्रिकाजालं तंत्रिकाजालद्वारा गणनायाः अनन्तरं चित्रे स्थापितानां संख्यानां पहिचानं करिष्यति, तस्मात् अङ्कीयप्रतिमानां वर्गीकरणं साक्षात्करोति।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

अस्मिन् क्रमे मुख्यतया त्रयः पक्षाः व्याख्याताः सन्ति : तंत्रिकाजालस्य परिकल्पना कार्यान्वयनञ्च, प्रशिक्षणदत्तांशस्य निर्माणं प्रसंस्करणं च, आदर्शप्रशिक्षणपरीक्षणप्रक्रिया च

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

तंत्रिकाजालस्य परिकल्पना कार्यान्वयनञ्च

चित्रदत्तांशसंसाधितुं तंत्रिकाजालस्य परिकल्पनाय प्रथमं निवेशप्रतिबिम्बदत्तांशस्य आकारं प्रारूपं च स्पष्टीकर्तुं आवश्यकम् ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

वयं यत् चित्रं संसाधितुं गच्छामः तत् २८ × २८ पिक्सेलस्य आकारस्य ग्रे-चैनल-प्रतिबिम्बम् (MNIST-दत्तांशसमूहस्य एव प्रारूपम्) अस्ति ।

अस्मिन् ग्रे चित्रे २८ समाविष्टाः सन्ति२८ = ७८४ दत्तांशबिन्दवः, अस्माभिः प्रथमं १ यावत् समतलं कर्तव्यम्आकारस्य सदिशः ७८४:

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

ततः एतत् सदिशं तंत्रिकाजाले निवेशयन्तु वयं प्रतिबिम्बस्य अनुरूपं सदिशं x संसाधितुं त्रिस्तरीयं तंत्रिकाजालं उपयुञ्ज्महे निवेशस्तरस्य x मध्ये 784-आयामी प्रतिबिम्बसदिशं प्राप्तुं आवश्यकम् अस्ति तंत्रिकाजालं प्राप्तुं न्यूरॉन्सं, अतः निवेशस्तरस्य ७८४ न्यूरॉन्साः सन्ति:

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

गुप्तस्तरस्य उपयोगः विशेषतानिष्कासनार्थं भवति, निवेशविशेषतासदिशं उच्चस्तरीयविशेषतासदिशेषु संसाधयति ।

यतः हस्तलिखितं अङ्कप्रतिबिम्बं जटिलं नास्ति, अत्र वयं गुप्तस्तरस्य न्यूरॉन्-सङ्ख्यां २५६ इति सेट् कुर्मः, येन निवेशस्तरस्य गुप्तस्तरस्य च मध्ये ७८४*२५६ आकारस्य रेखीयस्तरः भविष्यति:

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

इदं ७८४-आयामीं निवेशसदिशं २५६-आयामीं निर्गमसदिशं परिवर्तयितुं शक्नोति, यत् निर्गमस्तरं प्रति अग्रे प्रसारितं भविष्यति ।

यतो हि अङ्कीयप्रतिबिम्बं अन्ततः ० तः ९ पर्यन्तं दशसंभाव्यसङ्ख्यारूपेण ज्ञास्यति, अतः निर्गमस्तरस्य एतेषां दशसङ्ख्यानां अनुरूपं १० न्यूरॉन् परिभाषितुं आवश्यकं भवति:

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

गुप्तस्तरस्य निर्गमस्तरस्य च मध्ये रेखीयस्तरस्य माध्यमेन २५६-आयामी सदिशस्य गणनायाः अनन्तरं १०-आयामी निर्गमफलं प्राप्यते अयं १०-आयामी सदिशः १० सङ्ख्यानां भविष्यवाणीस्कोरं प्रतिनिधियति

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

10 संख्यानां पूर्वानुमानितसंभावनां निरन्तरं प्राप्तुं अस्माकं आउटपुट् लेयरस्य आउटपुट् इत्येतत् softmax लेयर इत्यत्र अपि इनपुट् करणीयम् अस्ति softmax लेयर इत्यनेन 10-आयामी सदिशं 10 संभाव्यतामूल्येषु P0 तः P9 पर्यन्तं परिवर्तयिष्यति संभाव्यता मूल्यं संख्यायाः अनुरूपं भवति अर्थात् निवेशप्रतिबिम्बं निश्चितसङ्ख्या अस्ति इति संभावना तदतिरिक्तं P0 तः P9 पर्यन्तं 10 संभाव्यतामूल्यानां योगः 1 भवति ।एतत् the softmax कार्य: 1.1.

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

उपरिष्टाद् तंत्रिकाजालस्य डिजाइनविचारः अस्ति तदनन्तरं वयं तस्य कार्यान्वयनार्थं PyTorch framework इत्यस्य उपयोगं कुर्मः ।

प्रथमं अस्माकं तंत्रिकाजालं कार्यान्वितम् : १.

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

कोडः अधोलिखितरूपेण दर्शयतु:

import torch
from torch import nn


# 定义神经网络
class NetWork(nn.Module):
    def __init__(self):
        super().__init__()
        # 线性层1,输入层和隐藏层之间的线性层
        self.layer1 = nn.Linear(784, 256)
        # 线性层2,隐藏层和输出层之间的线性层
        self.layer2 = nn.Linear(256, 10)
        # 这里没有直接定义 softmax 层
        # 这是因为后面会使用 CrossEntropyLoss 损失函数
        # 在这个损失函数中会实现 softmax 的计算

    def forward(self, x):
        x = x.view(-1, 28 * 28)  # 使用view 函数将 x 展平
        x = self.layer1(x)  # 将 x 输入至 layer1
        x = torch.relu(x)  # 使用 ReLu 函数激活
        return self.layer2(x)  # 输入至 layer2 计算结果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

दत्तांशनिर्माणं प्रसंस्करणं च प्रशिक्षणम्

तदनन्तरं दत्तांशसमूहं सज्जीकरोतु : १.

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

दत्तांशसमूहं प्राप्तुं भवान् PyTorch आधिकारिकजालस्थलात् डाउनलोड् कर्तुं निम्नलिखितपद्धतिं अपि उपयोक्तुं शक्नोति:

# 准备数据集
train_data = torchvision.datasets.MNIST(root='data', train=True, download=True)
test_data = torchvision.datasets.MNIST(root='data', train=False, download=True)
  • 1
  • 2
  • 3

एवं प्रकारेण डाउनलोड् कृतं दत्तांशं स्वयमेव train_data तथा test_data इत्यत्र संगृहीतं भविष्यति तदनुरूपं वयं कोड् मध्ये निर्दिष्टे निर्देशिकायां एकं टूल् संकुलं डाउनलोड् भविष्यति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

परन्तु एषा सार्वभौमिकपद्धतिः नास्ति भविष्ये कार्ये अध्ययने च बहवः दत्तांशसमूहाः भविष्यन्ति येषां संचालनं प्रक्रिया च अस्माभिः स्वयमेव करणीयम्, ये उपर्युक्तवत् सुविधाजनकाः न भविष्यन्ति, अतः अत्र अधिकसामान्यविधिः प्रवर्तते। यत् आधिकारिकजालस्थलात् देशीदत्तांशं डाउनलोड् कर्तुं भवति दत्तांशसमूहः, हाँ, चित्राणां समूहः अस्ति!

वयं डाउनलोड् कृतं दत्तांशं निम्नलिखितयोः पुटयोः रक्षामः ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

वयं क्रमशः ट्रेन् तथा टेस्ट् इति द्वयोः निर्देशिकायोः दत्तांशं रक्षामः, यत्र ट्रेन् मध्ये ६०,००० दत्तांशः भवति तथा च टेस्ट् मध्ये १०,००० दत्तांशः भवति, येषां उपयोगः क्रमशः मॉडल् प्रशिक्षणाय परीक्षणाय च भवति

रेलयानस्य परीक्षणनिर्देशिकायोः द्वयोः अपि दश उपनिर्देशिकाः सन्ति, उपनिर्देशिकानां नामानि च चित्रे विद्यमानसङ्ख्याभिः सह सङ्गच्छन्ति । यथा, ३ सङ्ख्यायाः चित्रं ३ इति पुटे रक्षितं भवति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

यत्र चित्रस्य नाम यादृच्छिकं तारहस्ताक्षरम् अस्ति ।

दत्तांशसज्जीकरणं सम्पन्नं कृत्वा दत्तांशपठनकार्यं कार्यान्वितं भवति आरम्भकानां केवलं एतत् भागं शिक्षमाणानां सामान्यदत्तांशसंसाधनप्रक्रियायाः ज्ञानं भवति ।

संहिता निम्नलिखितरूपेण कार्यान्वितः भवति ।

# 首先实现图像的预处理pipeline
transform = torchvision.transforms.Compose([
    torchvision.transforms.Grayscale(num_output_channels=1),  # 转换为单通道灰度图像
    torchvision.transforms.ToTensor()  # 转换为PyTorch支持的张量
])

# 这是方式一准备数据集的方式嗷
train_data = torchvision.datasets.MNIST(root='data', train=True, download=True, transform=transform)
test_data = torchvision.datasets.MNIST(root='data', train=False, download=True, transform=transform)

# 下面这是方式二准备数据集的方式
# 使用 ImageFolder 函数读取数据文件夹,构建数据集 dataset
# 这个函数会将保存数据的文件夹的名字,作为数据的标签,组织数据
# 例如,对于名字为 3 的文件夹
# 就会将 3 作为文件夹中图像数据的标签,和图像配对用于后续的训练,使用起来非常方便
train_dataset = torchvision.datasets.ImageFolder(root='./mnist/train', transform=transform)
test_dataset = torchvision.datasets.ImageFolder(root='./mnist/test', transform=transform)

# 不管使用哪种准备数据集的方式,最后的效果都是一样的
# 打印它们的长度看一下
print(len(train_data))
print(len(test_data))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

धावनपरिणामान् अवलोकयन्तु :

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

भवान् द्रष्टुं शक्नोति यत् प्रशिक्षणदत्तांशः परीक्षणदत्तांशः च प्राप्तौ, यत् अस्माभिः पूर्वं यत् उक्तं तस्य पूर्णतया सङ्गतम् अस्ति ।

ततः वयं लघु-बैच-दत्तांश-पठनं कार्यान्वितुं train_loader इत्यस्य उपयोगं कुर्मः:

# 使用 train_loader 实现小批量的数据读取
# 这里设置小批量的大小,batch_size = 64。
# 也就是每个批次包括 64 个数据
train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)
# 打印 train_loader 的长度
print(" train loader length: ", len(train_loader))
# 60000 个训练数据,如果每个小批量读入 64 个样本,那么 60000 个数据会被分为 938 组
# 计算 938 * 64 = 60032,这说明最后一组会不够 64 个数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

धावनस्य परिणामाः निम्नलिखितरूपेण सन्ति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

ततः वयं train_loader इत्यस्य माध्यमेन लूप् कृत्वा प्रत्येकं लघु-समूहं दत्तांशं प्राप्तुं शक्नुमः:

# 循环遍历 train_loader
# 每一次循环,都会取出 64 个图像数据,作为一个小批量 batch
for batch_idx, (data, label) in enumerate(train_loader):
    if batch_idx == 3:  # 打印前三个 batch 观察
        break
    print("batch_idx: ", batch_idx)
    print("data.shape: ", data.shape)  # 数据的尺寸
    print("label: ", label.shape)  # 图像中的数字
    print(label)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

अत्र उपरिष्टात् लूप् स्टेट्मेण्ट् इत्यस्य सरलं व्याख्यानं अस्ति यत् स्पष्टतरं करिष्यति:

गणना () 1 . इदं पायथन् इत्यस्य अन्तःनिर्मितं कार्यम् अस्ति, यत् एकं पारयोग्यं दत्तांशवस्तु (यथा सूची, ट्युपल्, अथवा स्ट्रिंग्) अनुक्रमणिकाक्रमे संयोजयितुं, एकस्मिन् समये दत्तांशं दत्तांशं च उपलिपिं सूचीतुं, अर्थात् प्राप्तुं प्रयुक्तं भवति अनुक्रमणिका मूल्यं च एकस्मिन् समये। अत्र, train_loader इत्यस्मिन् प्रत्येकं बैच् इत्यस्य माध्यमेन पुनरावृत्तिः कर्तुं तस्य उपयोगः भवति, यत्र batch_idx वर्तमान बैच् इत्यस्य अनुक्रमणिका अस्ति (0 तः आरभ्य), (data, label) वर्तमान बैच् इत्यस्य डाटा तथा लेबल् अस्ति ।

batch_idx कृते, (दत्तांश, लेबल) enumerate (train_loader): अस्य लूप् स्टेट्मेण्ट् इत्यस्य अर्थः अस्ति यत् train_loader इत्यस्मिन् प्रत्येकस्य बैच् इत्यस्य कृते लूप् बॉडी इत्यस्मिन् कोड् निष्पादितः भवति ।प्रत्येकं लूप् पुनरावृत्तौ batch_idx वर्तमान बैचस्य अनुक्रमणिका भवति, (data, label) वर्तमान बैचस्य दत्तांशः लेबलं च भवति . दत्तांशः प्रायः बहुविधदत्तांशबिन्दवः युक्तः टेन्सरः भवति, प्रत्येकं दत्तांशबिन्दुः नमूना भवति लेबलं एतेषां दत्तांशबिन्दूनां अनुरूपं लेबल टेन्सरः भवति, यस्य उपयोगः पर्यवेक्षितशिक्षणे लक्ष्यमूल्येन भवति

धावनप्रभावः निम्नलिखितरूपेण भवति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

धावनपरिणामात् द्रष्टुं शक्यते- १.

1. batch_idx = 0 इत्यस्य अर्थः अस्ति यत् एतत् दत्तांशस्य प्रथमः समूहः अस्ति

2. data.shape इत्यनेन दत्तांशस्य परिमाणं [64, 1, 28, 28] इति सूचयति ।

उपरिष्टात् आकारस्य अर्थः अस्ति यत् प्रत्येकं दत्तांशसमूहे ६४ चित्राणि सन्ति, प्रत्येकस्मिन् चित्रे १ ग्रे चैनल् भवति, चित्रस्य आकारः २८*२८ भवति ।

3. label.shape इत्यस्य अर्थः अस्ति यत् बैच् मध्ये 64 सङ्ख्याः सन्ति तथा च तेषां अनुरूपं लेबल् इत्यस्य कुलसंख्या 64. प्रत्येकस्य सङ्ख्यायाः लेबलं भवति ।

भेदं प्रति ध्यानं ददातु केवलं ९ वास्तविकलेबलवर्गाः भवितुमर्हन्ति, यतः संख्याः केवलं १ तः ९ पर्यन्तं भवन्ति, अत्र च ६४ लेबलमूल्यानि सन्ति इति अर्थः ।

4. टेन्सर-सरणिः एतेषु 64 डिजिटल-प्रतिमेषु प्रत्येकस्य अनुरूपं लेबल-मूल्यं प्रतिनिधियति ।

प्रशिक्षणं परीक्षणप्रक्रिया च आदर्शं कुर्वन्तु

पूर्वसज्जतां कृत्वा वयं मॉडलस्य प्रशिक्षणं परीक्षणं च आरभुं शक्नुमः ।

अत्र प्रशिक्षणसङ्केतः अस्ति : १.

# 在使用 PyTorch 训练模型时,需要创建三个对象
model = NetWork()  # 1、模型本身,它就是我们设计的神经网络
optimizer = torch.optim.Adam(model.parameters())  # 2、优化器,优化模型中的参数
criterion = nn.CrossEntropyLoss()  # 3、损失函数,分类问题使用交叉熵损失误差

# 开始训练模型
for epoch in range(10):  # 外层循环,代表了整个训练数据集的遍历次数
    # 整个训练集要循环多少轮,是10次还是20次还是100次都是有可能的
    # 内层循环使用train_loader 进行小批量的数据读取
    for batch_idx, (data, label) in enumerate(train_loader):
        # 内层每循环一次,就会进行一次梯度下降算法
        # 包括五个步骤:
        output = model(data)  # 1、计算神经网络的前向传播结果
        loss = criterion(output, label)  # 2、计算 output 和标签 label 之间的误差损失 loss
        loss.backward()  # 3、使用 backward 计算梯度
        optimizer.step()  # 4、使用 optimizer.step 更新参数
        optimizer.zero_grad()  # 5、将梯度清零
        # 这五个步骤是使用 PyTorch 框架训练模型的定式,初学的时候记住就可以了
        # 每迭代 100 个小批量,就打印一次模型的损失,观察训练的过程
        if batch_idx % 100 == 0:
            print(f"Epoch {epoch + 1} / 10 "
                  f"| Batch {batch_idx} / {len(train_loader)}"
                  f"| Loss: {loss.item():.4f}")

torch.save(model.state_dict(), 'mnist.pth')  # 最后保存训练好的模型
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

धावनप्रभावः निम्नलिखितरूपेण भवति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
मध्यं परित्यजन्तु...
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

अन्तिमहानिमूल्यं अतीव अतीव लघु, ०.०२३९ इति द्रष्टुं शक्यते ।

अन्तिमः सोपानः परीक्षणम् अस्ति परीक्षणप्रक्रिया मूलतः प्रशिक्षणस्य समाना अस्ति कोडः निम्नलिखितरूपेण अस्ति ।

model = NetWork()  # 定义神经网络模型
model.load_state_dict(torch.load('mnist.pth'))  # 加载刚刚训练好的模型文件

right = 0  # 保存正确识别的数量
for i, (x, y) in enumerate(test_data):
    output = model(x)  # 将其中的数据 x 输入到模型中
    predict = output.argmax(1).item()  # 选择概率最大的标签作为预测结果
    # 对比预测值 predict 和真实标签 y
    if predict == y:
        right += 1
    else:
        # 将识别错误的样例打印出来
        print(f"wrong case: predict = {predict}, but y = {y}")

# 计算出测试结果
sample_num = len(test_data)
accuracy = right * 1.0 / sample_num
print("test accuracy = %d / %d = %.3lf" % (right, sample_num, accuracy))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

धावनस्य परिणामाः निम्नलिखितरूपेण सन्ति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

परीक्षणस्य सटीकता ९८% इति द्रष्टुं शक्यते, यत् अद्यापि अतीव उच्चम् अस्ति ।

उपर्युक्तं तंत्रिकाजालस्य डिजाइनं प्रशिक्षणं च आद्यतः एव भवति ।

सारांशः तथा कोडसंक्षेपः

उपर्युक्तं प्रत्येकस्य कार्यात्मकभागस्य अनुसारं व्याख्यातं वर्णितं च, यत् किञ्चित् भ्रान्तिकं भवितुम् अर्हति ।

प्रशिक्षण संहिता

import torch
import torchvision.datasets
from torch import nn


# ----------------1、定义神经网络-------------------
class NetWork(nn.Module):
    def __init__(self):
        super().__init__()
        # 线性层1,输入层和隐藏层之间的线性层
        self.layer1 = nn.Linear(784, 256)
        # 线性层2,隐藏层和输出层之间的线性层
        self.layer2 = nn.Linear(256, 10)
        # 这里没有直接定义 softmax 层
        # 这是因为后面会使用 CrossEntropyLoss 损失函数
        # 在这个损失函数中会实现 softmax 的计算

    def forward(self, x):
        x = x.view(-1, 28 * 28)  # 使用view 函数将 x 展平
        x = self.layer1(x)  # 将 x 输入至 layer1
        x = torch.relu(x)  # 使用 ReLu 函数激活
        return self.layer2(x)  # 输入至 layer2 计算结果


# ----------------2、图像预处理-------------------
# 实现图像的预处理的pipeline
transform = torchvision.transforms.Compose([
    torchvision.transforms.Grayscale(num_output_channels=1),  # 转换为单通道灰度图像
    torchvision.transforms.ToTensor()  # 转换为PyTorch支持的张量
])

# ----------------3、数据集准备-------------------
# 准备训练数据集
train_data = torchvision.datasets.MNIST(root='data', train=True, download=True, transform=transform)

# ----------------4、数据集加载-------------------
# 使用 train_loader 实现小批量的数据读取
# 这里设置小批量的大小,batch_size = 64。
# 也就是每个批次包括 64 个数据
train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)

# ----------------5、训练神经网络-------------------
# 在使用 PyTorch 训练模型时,需要创建三个对象
model = NetWork()  # 1、模型本身,它就是我们设计的神经网络
optimizer = torch.optim.Adam(model.parameters())  # 2、优化器,优化模型中的参数
criterion = nn.CrossEntropyLoss()  # 3、损失函数,分类问题使用交叉熵损失误差

# 开始训练模型
for epoch in range(10):  # 外层循环,代表了整个训练数据集的遍历次数
    # 整个训练集要循环多少轮,是10次还是20次还是100次都是有可能的
    # 内层循环使用train_loader 进行小批量的数据读取
    for batch_idx, (data, label) in enumerate(train_loader):
        # 内层每循环一次,就会进行一次梯度下降算法
        # 包括五个步骤:
        output = model(data)  # 1、计算神经网络的前向传播结果
        loss = criterion(output, label)  # 2、计算 output 和标签 label 之间的误差损失 loss
        loss.backward()  # 3、使用 backward 计算梯度
        optimizer.step()  # 4、使用 optimizer.step 更新参数
        optimizer.zero_grad()  # 5、将梯度清零
        # 这五个步骤是使用 PyTorch 框架训练模型的定式,初学的时候记住就可以了
        # 每迭代 100 个小批量,就打印一次模型的损失,观察训练的过程
        if batch_idx % 100 == 0:
            print(f"Epoch {epoch + 1} / 10 "
                  f"| Batch {batch_idx} / {len(train_loader)}"
                  f"| Loss: {loss.item():.4f}")

torch.save(model.state_dict(), 'mnist.pth')  # 最后保存训练好的模型

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

परीक्षणसङ्केतः

import torch
import torchvision.datasets
from torch import nn


# ----------------1、定义神经网络-------------------
class NetWork(nn.Module):
    def __init__(self):
        super().__init__()
        # 线性层1,输入层和隐藏层之间的线性层
        self.layer1 = nn.Linear(784, 256)
        # 线性层2,隐藏层和输出层之间的线性层
        self.layer2 = nn.Linear(256, 10)
        # 这里没有直接定义 softmax 层
        # 这是因为后面会使用 CrossEntropyLoss 损失函数
        # 在这个损失函数中会实现 softmax 的计算

    def forward(self, x):
        x = x.view(-1, 28 * 28)  # 使用view 函数将 x 展平
        x = self.layer1(x)  # 将 x 输入至 layer1
        x = torch.relu(x)  # 使用 ReLu 函数激活
        return self.layer2(x)  # 输入至 layer2 计算结果


# ----------------2、图像预处理-------------------
# 实现图像的预处理的pipeline
transform = torchvision.transforms.Compose([
    torchvision.transforms.Grayscale(num_output_channels=1),  # 转换为单通道灰度图像
    torchvision.transforms.ToTensor()  # 转换为PyTorch支持的张量
])

# ----------------3、数据集准备-------------------
# 准备测试数据集
test_data = torchvision.datasets.MNIST(root='data', train=False, download=True, transform=transform)

# ----------------4、测试神经网络-------------------
model = NetWork()  # 定义神经网络模型
model.load_state_dict(torch.load('mnist.pth'))  # 加载刚刚训练好的模型文件

right = 0  # 保存正确识别的数量
for i, (x, y) in enumerate(test_data):
    output = model(x)  # 将其中的数据 x 输入到模型中
    predict = output.argmax(1).item()  # 选择概率最大的标签作为预测结果
    # 对比预测值 predict 和真实标签 y
    if predict == y:
        right += 1
    else:
        # 将识别错误的样例打印出来
        print(f"wrong case: predict = {predict}, but y = {y}")

# 计算出测试结果
sample_num = len(test_data)
accuracy = right * 1.0 / sample_num
print("test accuracy = %d / %d = %.3lf" % (right, sample_num, accuracy))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55