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 计算结果
तदनन्तरं दत्तांशसमूहं सज्जीकरोतु : १.
दत्तांशसमूहं प्राप्तुं भवान् PyTorch आधिकारिकजालस्थलात् डाउनलोड् कर्तुं निम्नलिखितपद्धतिं अपि उपयोक्तुं शक्नोति:
# 准备数据集
train_data = torchvision.datasets.MNIST(root='data', train=True, download=True)
test_data = torchvision.datasets.MNIST(root='data', train=False, download=True)
एवं प्रकारेण डाउनलोड् कृतं दत्तांशं स्वयमेव 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))
धावनपरिणामान् अवलोकयन्तु :
भवान् द्रष्टुं शक्नोति यत् प्रशिक्षणदत्तांशः परीक्षणदत्तांशः च प्राप्तौ, यत् अस्माभिः पूर्वं यत् उक्तं तस्य पूर्णतया सङ्गतम् अस्ति ।
ततः वयं लघु-बैच-दत्तांश-पठनं कार्यान्वितुं 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 个数据
धावनस्य परिणामाः निम्नलिखितरूपेण सन्ति ।
ततः वयं 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 . इदं पायथन् इत्यस्य अन्तःनिर्मितं कार्यम् अस्ति, यत् एकं पारयोग्यं दत्तांशवस्तु (यथा सूची, ट्युपल्, अथवा स्ट्रिंग्) अनुक्रमणिकाक्रमे संयोजयितुं, एकस्मिन् समये दत्तांशं दत्तांशं च उपलिपिं सूचीतुं, अर्थात् प्राप्तुं प्रयुक्तं भवति अनुक्रमणिका मूल्यं च एकस्मिन् समये। अत्र, 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') # 最后保存训练好的模型
धावनप्रभावः निम्नलिखितरूपेण भवति ।
मध्यं परित्यजन्तु...
अन्तिमहानिमूल्यं अतीव अतीव लघु, ०.०२३९ इति द्रष्टुं शक्यते ।
अन्तिमः सोपानः परीक्षणम् अस्ति परीक्षणप्रक्रिया मूलतः प्रशिक्षणस्य समाना अस्ति कोडः निम्नलिखितरूपेण अस्ति ।
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))
धावनस्य परिणामाः निम्नलिखितरूपेण सन्ति ।
परीक्षणस्य सटीकता ९८% इति द्रष्टुं शक्यते, यत् अद्यापि अतीव उच्चम् अस्ति ।
उपर्युक्तं तंत्रिकाजालस्य डिजाइनं प्रशिक्षणं च आद्यतः एव भवति ।
उपर्युक्तं प्रत्येकस्य कार्यात्मकभागस्य अनुसारं व्याख्यातं वर्णितं च, यत् किञ्चित् भ्रान्तिकं भवितुम् अर्हति ।
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') # 最后保存训练好的模型
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))