PyTorch零基礎(chǔ)入門(mén)之構(gòu)建模型基礎(chǔ)
一、神經(jīng)網(wǎng)絡(luò)的構(gòu)造
- PyTorch中神經(jīng)網(wǎng)絡(luò)構(gòu)造一般是基于
Module
類的模型來(lái)完成的,它讓模型構(gòu)造更加靈活。Module
類是nn
模塊里提供的一個(gè)模型構(gòu)造類,是所有神經(jīng)網(wǎng)絡(luò)模塊的基類,我們可以繼承它來(lái)定義我們想要的模型。 - 下面繼承
Module
類構(gòu)造多層感知機(jī)。這里定義的 MLP 類重載了Module
類的init
函數(shù)和forward
函數(shù)。它們分別用于創(chuàng)建模型參數(shù)和定義前向計(jì)算。前向計(jì)算也即正向傳播。
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 09:43:21 2021 @author: 86493 """ import torch from torch import nn class MLP(nn.Module): # 聲明帶有模型參數(shù)的層,此處聲明了2個(gè)全連接層 def __init__(self, **kwargs): # 調(diào)用MLP父類Block的構(gòu)造函數(shù)來(lái)進(jìn)行必要的初始化 # 這樣在構(gòu)造實(shí)例時(shí)還可以指定其他函數(shù) super(MLP, self).__init__(**kwargs) self.hidden = nn.Linear(784, 256) self.act = nn.ReLU() self.output = nn.Linear(256, 10) # 定義模型的前向計(jì)算 # 即如何根據(jù)輸入x計(jì)算返回所需要的模型輸出 def forward(self, x): o = self.act(self.hidden(x)) return self.output(o) X = torch.rand(2, 784) net = MLP() print(net) print('-' * 60) print(net(X))
結(jié)果為:
MLP(
(hidden): Linear(in_features=784, out_features=256, bias=True)
(act): ReLU()
(output): Linear(in_features=256, out_features=10, bias=True)
)
------------------------------------------------------------
tensor([[ 0.1836, 0.1946, 0.0924, -0.1163, -0.2914, -0.1103, -0.0839, -0.1274,
0.1618, -0.0601],
[ 0.0738, 0.2369, 0.0225, -0.1514, -0.3787, -0.0551, -0.0836, -0.0496,
0.1481, 0.0139]], grad_fn=<AddmmBackward>)
注意:
(1)上面的MLP類不需要定義反向傳播函數(shù),系統(tǒng)將通過(guò)自動(dòng)求梯度而自動(dòng)生成反向傳播所需的backward
函數(shù)。
(2)將數(shù)據(jù)X傳入實(shí)例化MLP類后得到的net對(duì)象,會(huì)做一次前向計(jì)算,并且net(X)
會(huì)調(diào)用MLP
類繼承自父類Module
的call
函數(shù)——該函數(shù)調(diào)用我們定義的子類MLP
的forward
函數(shù)完成前向傳播計(jì)算。
(3)這里沒(méi)將Module類命名為L(zhǎng)ayer(層)或者M(jìn)odel(模型)等,是因?yàn)樵擃愂且粋€(gè)可供自由組建的部件, 它的子類既可以是一個(gè)層(如繼承父類nn
的子類線性層Linear
),也可以是一個(gè)模型(如此處的子類MLP
),也可以是模型的一部分。
二、神經(jīng)網(wǎng)絡(luò)中常見(jiàn)的層
有全連接層、卷積層、池化層與循環(huán)層等,下面學(xué)習(xí)使用Module
定義層。
2.1 不含模型參數(shù)的層
下面構(gòu)造的 MyLayer 類通過(guò)繼承 Module 類自定義了一個(gè)將輸入減掉均值后輸出的層,并將層的計(jì)算定義在了 forward 函數(shù)里。這個(gè)層里不含模型參數(shù)。
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 10:19:59 2021 @author: 86493 """ import torch from torch import nn class MyLayer(nn.Module): def __init__(self, **kwargs): # 調(diào)用父類的方法 super(MyLayer, self).__init__(**kwargs) def forward(self, x): return x - x.mean() # 測(cè)試,實(shí)例化該層,做前向計(jì)算 layer = MyLayer() layer1 = layer(torch.tensor([1, 2, 3, 4, 5], dtype = torch.float)) print(layer1)
結(jié)果為:
tensor([-2., -1., 0., 1., 2.])
2.2 含模型參數(shù)的層
可以自定義含模型參數(shù)的自定義層。其中的模型參數(shù)可以通過(guò)訓(xùn)練學(xué)出。
Parameter
類其實(shí)是 Tensor
的子類,如果一個(gè) Tensor
是 Parameter
,那么它會(huì)自動(dòng)被添加到模型的參數(shù)列表里。所以在自定義含模型參數(shù)的層時(shí),我們應(yīng)該將參數(shù)定義成 Parameter
,除了直接定義成 Parameter
類外,還可以使用 ParameterList
和 ParameterDict
分別定義參數(shù)的列表和字典。
PS:下面出現(xiàn)torch.mm
是將兩個(gè)矩陣相乘,如
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 10:56:03 2021 @author: 86493 """ import torch a = torch.randn(2, 3) b = torch.randn(3, 2) print(torch.mm(a, b)) # 效果相同 print(torch.matmul(a, b)) #tensor([[1.8368, 0.4065], # [2.7972, 2.3096]]) #tensor([[1.8368, 0.4065], # [2.7972, 2.3096]])
(1)代碼栗子1
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 10:33:04 2021 @author: 86493 """ import torch from torch import nn class MyListDense(nn.Module): def __init__(self): super(MyListDense, self).__init__() # 3個(gè)randn的意思 self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)]) self.params.append(nn.Parameter(torch.randn(4, 1))) def forward(self, x): for i in range(len(self.params)): # mm是指矩陣相乘 x = torch.mm(x, self.params[i]) return x net = MyListDense() print(net)
打印得:
MyListDense(
(params): ParameterList(
(0): Parameter containing: [torch.FloatTensor of size 4x4]
(1): Parameter containing: [torch.FloatTensor of size 4x4]
(2): Parameter containing: [torch.FloatTensor of size 4x4]
(3): Parameter containing: [torch.FloatTensor of size 4x1]
)
)
(2)代碼栗子2
這回用變量字典:
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 11:03:29 2021 @author: 86493 """ import torch from torch import nn class MyDictDense(nn.Module): def __init__(self): super(MyDictDense, self).__init__() self.params = nn.ParameterDict({ 'linear1': nn.Parameter(torch.randn(4, 4)), 'linear2': nn.Parameter(torch.randn(4, 1)) }) # 新增 self.params.update({'linear3': nn.Parameter(torch.randn(4, 2))}) def forward(self, x, choice = 'linear1'): return torch.mm(x, self.params[choice]) net = MyDictDense() print(net)
打印得:
MyDictDense(
(params): ParameterDict(
(linear1): Parameter containing: [torch.FloatTensor of size 4x4]
(linear2): Parameter containing: [torch.FloatTensor of size 4x1]
(linear3): Parameter containing: [torch.FloatTensor of size 4x2]
)
)
2.3 二維卷積層
二維卷積層將輸入和卷積核做互相關(guān)運(yùn)算,并加上一個(gè)標(biāo)量偏差來(lái)得到輸出。卷積層的模型參數(shù)包括了卷積核和標(biāo)量偏差。在訓(xùn)練模型的時(shí)候,通常我們先對(duì)卷積核隨機(jī)初始化,然后不斷迭代卷積核和偏差。
卷積窗口形狀為 p × q p \times q p×q 的卷積層稱為 p × q p \times q p×q 卷積層。同樣, p × q p \times q p×q 卷積或 p × q p \times q p×q 卷積核說(shuō)明卷積核的高和寬分別為 p p p 和 q q q。
(1)填充可以增加輸出的高和寬。這常用來(lái)使輸出與輸入具有相同的高和寬。
(2)步幅可以減小輸出的高和寬,例如輸出的高和寬僅為輸⼊入的高和寬的 ( 為大于1的整數(shù))。
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 11:20:57 2021 @author: 86493 """ import torch from torch import nn # 卷積運(yùn)算(二維互相關(guān)) def corr2d(X, K): h, w = K.shape X, K = X.float(), K.float() Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1)) for i in range(Y.shape[0]): for j in range(Y.shape[1]): Y[i, j] = (x[i: i + h, j: j + w] * K).sum() return Y # 二維卷積層 class Conv2D(nn.Module): def __init__(self, kernel_size): super(Conv2D, self).__init__() self.weight = nn.Parameter(torch.randn(kernel_size)) self.bias = nn.Parameter(torch.randn(1)) def forward(self, x): return corr2d(x, self.weight) + self.bias conv2d = nn.Conv2d(in_channels = 1, out_channels = 1, kernel_size = 3, padding = 1) print(conv2d)
得:
Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
填充(padding)是指在輸入高和寬的兩側(cè)填充元素(通常是0元素)。
下個(gè)栗子:創(chuàng)建一個(gè)高和寬為3的二維卷積層,設(shè)輸入高和寬兩側(cè)的填充數(shù)分別為1。給定一高和寬都為8的input,輸出的高和寬會(huì)也是8。
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 11:54:29 2021 @author: 86493 """ import torch from torch import nn # 定義一個(gè)函數(shù)計(jì)算卷積層 # 對(duì)輸入和輸出左對(duì)應(yīng)的升維和降維 def comp_conv2d(conv2d, X): # (1, 1)代表批量大小和通道數(shù) X = X.view((1, 1) + X.shape) Y = conv2d(X) # 排除不關(guān)心的前2維:批量和通道 return Y.view(Y.shape[2:]) # 注意這里是兩側(cè)分別填充1行或列,所以在兩側(cè)共填充2行或列 conv2d = nn.Conv2d(in_channels = 1, out_channels = 1, kernel_size = 3, padding = 1) X = torch.rand(8, 8) endshape = comp_conv2d(conv2d, X).shape print(endshape) # 使用高為5,寬為3的卷積核,在高和寬兩側(cè)填充數(shù)為2和1 conv2d = nn.Conv2d(in_channels = 1, out_channels = 1, kernel_size = (5, 3), padding = (2, 1)) endshape2 = comp_conv2d(conv2d, X).shape print(endshape2)
結(jié)果為:
torch.Size([8, 8])
torch.Size([8, 8])
stride
在二維互相關(guān)運(yùn)算中,卷積窗口從輸入數(shù)組的最左上方開(kāi)始,按從左往右、從上往下 的順序,依次在輸⼊數(shù)組上滑動(dòng)。我們將每次滑動(dòng)的行數(shù)和列數(shù)稱為步幅(stride)。
# 步幅stride conv2d = nn.Conv2d(in_channels = 1, out_channels = 1, kernel_size = (3, 5), padding = (0, 1), stride = (3, 4)) endshape3 = comp_conv2d(conv2d, X).shape print(endshape3) # torch.Size([2, 2])
2.4 池化層
- 池化層每次對(duì)輸入數(shù)據(jù)的一個(gè)固定形狀窗口(又稱池化窗口)中的元素計(jì)算輸出。不同于卷積層里計(jì)算輸入和核的互相關(guān)性,池化層直接計(jì)算池化窗口內(nèi)元素的最大值或者平均值。該運(yùn)算也 分別叫做最大池化或平均池化。
- 在二維最大池化中,池化窗口從輸入數(shù)組的最左上方開(kāi)始,按從左往右、從上往下的順序,依次在輸入數(shù)組上滑動(dòng)。當(dāng)池化窗口滑動(dòng)到某⼀位置時(shí),窗口中的輸入子數(shù)組的最大值即輸出數(shù)組中相應(yīng)位置的元素。
下面把池化層的前向計(jì)算實(shí)現(xiàn)在pool2d
函數(shù)里。
最大池化:
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 18:49:27 2021 @author: 86493 """ import torch from torch import nn def pool2d(x, pool_size, mode = 'max'): p_h, p_w = pool_size Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1)) for i in range(Y.shape[0]): for j in range(Y.shape[1]): if mode == 'max': Y[i, j] = X[i: i + p_h, j: j + p_w].max() elif mode == 'avg': Y[i, j] = X[i: i + p_h, j: j + p_w].mean() return Y X = torch.Tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) end = pool2d(X, (2, 2)) # 默認(rèn)是最大池化 # end = pool2d(X, (2, 2), mode = 'avg') print(end)
tensor([[4., 5.],
[7., 8.]])
平均池化:
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 18:49:27 2021 @author: 86493 """ import torch from torch import nn def pool2d(x, pool_size, mode = 'max'): p_h, p_w = pool_size Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1)) for i in range(Y.shape[0]): for j in range(Y.shape[1]): if mode == 'max': Y[i, j] = X[i: i + p_h, j: j + p_w].max() elif mode == 'avg': Y[i, j] = X[i: i + p_h, j: j + p_w].mean() return Y X = torch.FloatTensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) # end = pool2d(X, (2, 2)) # 默認(rèn)是最大池化 end = pool2d(X, (2, 2), mode = 'avg') print(end)
結(jié)果如下,注意上面如果mode是avg模式(平均池化)時(shí),不能寫(xiě)X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
,否則會(huì)報(bào)錯(cuò)Can only calculate the mean of floating types. Got Long instead.
。把tensor
改成Tensor
或FloatTensor
后就可以了(Tensor是FloatTensor的縮寫(xiě))。
tensor([[2., 3.],
[5., 6.]])
三、LeNet模型栗子
一個(gè)神經(jīng)網(wǎng)絡(luò)的典型訓(xùn)練過(guò)程如下:
1 定義包含一些可學(xué)習(xí)參數(shù)(或者叫權(quán)重)的神經(jīng)網(wǎng)絡(luò)
2. 在輸入數(shù)據(jù)集上迭代
3. 通過(guò)網(wǎng)絡(luò)處理輸入
4. 計(jì)算 loss (輸出和正確答案的距離)
5. 將梯度反向傳播給網(wǎng)絡(luò)的參數(shù)
6. 更新網(wǎng)絡(luò)的權(quán)重,一般使用一個(gè)簡(jiǎn)單的規(guī)則:weight = weight - learning_rate * gradient
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 19:21:19 2021 @author: 86493 """ import torch import torch.nn as nn import torch.nn.functional as F class LeNet(nn.Module): # 需要把網(wǎng)絡(luò)中具有可學(xué)習(xí)參數(shù)的層放在構(gòu)造函數(shù)__init__ def __init__(self): super(LeNet, self).__init__() # 輸入圖像channel:1;輸出channel:6 # 5*5卷積核 self.conv1 = nn.Conv2d(1, 6, 5) self.conv2 = nn.Conv2d(6, 16, 5) # an affine operation:y = Wx + b self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): # 2 * 2 最大池化 x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # 如果是方陣,則可以只使用一個(gè)數(shù)字進(jìn)行定義 x = F.max_pool2d(F.relu(self.conv2(x)), 2) # 做一次flatten x = x.view(-1, self.num_flat_features(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x def num_flat_features(self, x): # 除去批處理維度,得到其他所有維度 size = x.size()[1:] num_features = 1 # 將剛才得到的維度之間相乘起來(lái) for s in size: num_features *= s return num_features net = LeNet() print(net) # 一個(gè)模型的可學(xué)習(xí)參數(shù)可以通過(guò)`net.parameters()`返回 params = list(net.parameters()) print("params的len:", len(params)) # print("params:\n", params) print(params[0].size()) # conv1的權(quán)重 print('-' * 60) # 隨機(jī)一個(gè)32×32的input input = torch.randn(1, 1, 32, 32) out = net(input) print("網(wǎng)絡(luò)的output為:", out) print('-' * 60) # 隨機(jī)梯度的反向傳播 net.zero_grad() # 清零所有參數(shù)的梯度緩存 end = out.backward(torch.randn(1, 10)) print(end) # None
print的結(jié)果為:
LeNet(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
params的len: 10
torch.Size([6, 1, 5, 5])
------------------------------------------------------------
網(wǎng)絡(luò)的output為: tensor([[ 0.0904, 0.0866, 0.0851, -0.0176, 0.0198, 0.0530, 0.0815, 0.0284,
-0.0216, -0.0425]], grad_fn=<AddmmBackward>)
------------------------------------------------------------
None
三點(diǎn)提醒:
(1)只需要定義 forward
函數(shù),backward
函數(shù)會(huì)在使用autograd
時(shí)自動(dòng)定義,backward
函數(shù)用來(lái)計(jì)算導(dǎo)數(shù)。我們可以在 forward
函數(shù)中使用任何針對(duì)張量的操作和計(jì)算。
(2)在backward
前最好net.zero_grad()
,即清零所有參數(shù)的梯度緩存。
(3)torch.nn
只支持小批量處理 (mini-batches)。整個(gè) torch.nn
包只支持小批量樣本的輸入,不支持單個(gè)樣本的輸入。比如,nn.Conv2d
接受一個(gè)4維的張量,即nSamples x nChannels x Height x Width
如果是一個(gè)單獨(dú)的樣本,只需要使用input.unsqueeze(0)
來(lái)添加一個(gè)“假的”批大小維度。
torch.Tensor
:一個(gè)多維數(shù)組,支持諸如backward()
等的自動(dòng)求導(dǎo)操作,同時(shí)也保存了張量的梯度。nn.Module
:神經(jīng)網(wǎng)絡(luò)模塊。是一種方便封裝參數(shù)的方式,具有將參數(shù)移動(dòng)到GPU、導(dǎo)出、加載等功能。nn.Parameter
:張量的一種,當(dāng)它作為一個(gè)屬性分配給一個(gè)Module
時(shí),它會(huì)被自動(dòng)注冊(cè)為一個(gè)參數(shù)。autograd.Function
:實(shí)現(xiàn)了自動(dòng)求導(dǎo)前向和反向傳播的定義,每個(gè)Tensor
至少創(chuàng)建一個(gè)Function
節(jié)點(diǎn),該節(jié)點(diǎn)連接到創(chuàng)建Tensor
的函數(shù)并對(duì)其歷史進(jìn)行編碼。
四、AlexNet模型栗子
# -*- coding: utf-8 -*- """ Created on Sat Oct 16 21:00:39 2021 @author: 86493 """ import torch from torch import nn class AlexNet(nn.Module): def __init__(self): super(AlexNet, self).__init__() self.conv = nn.Sequential( # in_channels,out_channels,kernel_size,stride,padding nn.Conv2d(1, 96, 11, 4), nn.ReLU(), # kernel_size, stride nn.MaxPool2d(3, 2), # 見(jiàn)笑卷積窗口,但使用padding=2來(lái)使輸入和輸出的高寬相同 # 且增大輸出通道數(shù) nn.Conv2d(96, 256, 5, 1, 2), nn.ReLU(), nn.MaxPool2d(3, 2), # 連續(xù)3個(gè)卷積層,且后面使用更小的卷積窗口 # 除了最后的卷積層外,進(jìn)一步增大了輸出 # 注:前2個(gè)卷積層后不使用池化層來(lái)減少輸入的高和寬 nn.Conv2d(256, 384, 3, 1, 1), nn.ReLU(), nn.Conv2d(384, 383, 3, 1, 1), nn.ReLU(), nn.Conv2d(384, 256, 3, 1, 1), nn.ReLU(), nn.MaxPool2d(3, 2) ) # 這里的全連接層的輸出個(gè)數(shù)比LeNet中的大數(shù)倍。 # 使用丟棄層來(lái)緩解過(guò)擬合 self.fc = nn.Sequential( nn.Linear(256 *5 * 5, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 4086), nn.ReLU(), nn.Dropout(0.5), # 輸出層,下次會(huì)用到Fash-MNIST,所以此處類別設(shè)為10, # 而非論文中的1000 nn.Linear(4096, 10), ) def forward(self, img): feature = self.conv(img) output = self.fc(feature.view(img.shape[0], -1)) return output net = AlexNet() print(net)
可以看到該網(wǎng)絡(luò)的結(jié)構(gòu):
AlexNet( (conv): Sequential( (0): Conv2d(1, 96, kernel_size=(11, 11), stride=(4, 4)) (1): ReLU() (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (3): Conv2d(96, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (4): ReLU() (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (6): Conv2d(256, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (7): ReLU() (8): Conv2d(384, 383, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (9): ReLU() (10): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU() (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) ) (fc): Sequential( (0): Linear(in_features=6400, out_features=4096, bias=True) (1): ReLU() (2): Dropout(p=0.5, inplace=False) (3): Linear(in_features=4096, out_features=4086, bias=True) (4): ReLU() (5): Dropout(p=0.5, inplace=False) (6): Linear(in_features=4096, out_features=10, bias=True) ) )
Reference
(1)官方文檔:https://pytorch.org/docs/stable/_modules/torch/nn/modules/conv.html#Conv2d
(2)datawhale notebook
到此這篇關(guān)于PyTorch零基礎(chǔ)入門(mén)之構(gòu)建模型基礎(chǔ)的文章就介紹到這了,更多相關(guān)PyTorch 構(gòu)建模型基礎(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python字典取值全攻略之高效、簡(jiǎn)潔地獲取字典值的多種技巧
這篇文章主要給大家介紹了關(guān)于Python字典取值全攻略之高效、簡(jiǎn)潔地獲取字典值的多種技巧,dictionary(字典)是除列表以外Python之中最靈活的數(shù)據(jù)類型,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12python數(shù)據(jù)可視化Seaborn繪制山脊圖
這篇文章主要介紹了利用python數(shù)據(jù)可視化Seaborn繪制山脊圖,山脊圖一般由垂直堆疊的折線圖組成,這些折線圖中的折線區(qū)域間彼此重疊,此外它們還共享相同的x軸.下面來(lái)看看具體的繪制過(guò)程吧,需要的小伙伴可以參考一下2022-01-01Python技巧之變長(zhǎng)和定長(zhǎng)序列拆分
這篇文章主要給大家分享的是Python技巧之變長(zhǎng)和定長(zhǎng)序列拆分,Python中的任何序列(可迭代的對(duì)象)都可以通過(guò)賦值操作進(jìn)行拆分,包括但不限于元組、列表、字符串、文件、迭代器、生成器等。想了解更多詳細(xì)的小伙伴請(qǐng)參考下面文章內(nèi)容2021-12-12pygame學(xué)習(xí)筆記之設(shè)置字體及顯示中文
游戲界面中文字也是非常常見(jiàn)的元素之一,pygame專門(mén)提供了Font模塊來(lái)支持文字的顯示,下面這篇文章主要給大家介紹了關(guān)于pygame學(xué)習(xí)筆記之設(shè)置字體及顯示中文的相關(guān)資料,需要的朋友可以參考下2022-07-07教你使用Python寫(xiě)一個(gè)簡(jiǎn)單的JSONParser
這篇文章主要介紹了教你使用Python寫(xiě)一個(gè)簡(jiǎn)單的JSONParser,它的整個(gè)效果,有點(diǎn)類似于 python 標(biāo)準(zhǔn)庫(kù) json 的 json.load() 方法,需要的朋友可以參考下2023-04-04Python基于遞歸和非遞歸算法求兩個(gè)數(shù)最大公約數(shù)、最小公倍數(shù)示例
這篇文章主要介紹了Python基于遞歸和非遞歸算法求兩個(gè)數(shù)最大公約數(shù)、最小公倍數(shù),涉及Python遞歸算法、流程循環(huán)控制進(jìn)行數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2018-05-05Python可視化神器pyecharts之繪制地理圖表練習(xí)
這篇文章主要介紹了Python可視化神器pyecharts之繪制地理圖表,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07Pandas DataFrame中實(shí)現(xiàn)取單個(gè)值的讀取和修改
這篇文章主要介紹了Pandas DataFrame中實(shí)現(xiàn)取單個(gè)值的讀取和修改,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10