【解讀Spikingjelly】使用單層全連接SNN識別MNIST

原文檔:使用單層全連接SNN識別MNIST — spikingjelly alpha 文檔

代碼地址:完整的代碼位于activation_based.examples.lif_fc_mnist.py

GitHub - fangwei123456/spikingjelly: SpikingJelly is an open-source deep learning framework for Spiking Neural Network (SNN) based on PyTorch.

ZhengyuanGao/spikingjelly: 開源脈沖神經網絡深度學習框架 - spikingjelly - OpenI - 啟智AI開源社區提供普惠算力! (pcl.ac.cn)a

本文補充一些細節代碼以解決運行報錯問題,并提供可視化代碼,解釋核心代碼作用以輔助SNN初學者快速入門!

目錄

1.網絡定義

2.主函數

2.1參數設置

2.2主循環

?3.可視化

?3.1準確率

?3.2測試圖片與發放脈沖

3.3脈沖發放與電壓

4.完整代碼?

lif_fc_mnist.py(為減少運行耗時,迭代次數設置為1)

lif_fc_mnist_test.py


1.網絡定義

class SNN(nn.Module):def __init__(self, tau):super().__init__()self.layer = nn.Sequential(layer.Flatten(),layer.Linear(28 * 28, 10, bias=False),neuron.LIFNode(tau=tau, surrogate_function=surrogate.ATan()),)def forward(self, x: torch.Tensor):return self.layer(x)

(1)super:繼承父類torch.nn.Module的初始化方法

(2)Sequential:順序方式連接網絡結構,首先將輸入展平為一維,定義全連接層,輸入格式28*28,輸出10個神經元。Neuron.LIFNode為脈沖神經元層,用于對全連接層的激活,指定膜時間常數與替代函數(解決不可導問題)

(3)forward:重寫前向傳播函數,返回網絡輸出結果

2.主函數

2.1參數設置

(1)使用命令行設置LIF神經網絡的超參數

parser = argparse.ArgumentParser(description='LIF MNIST Training')parser.add_argument('-T', default=100, type=int, help='simulating time-steps')parser.add_argument('-device', default='cuda:0', help='device')parser.add_argument('-b', default=64, type=int, help='batch size')parser.add_argument('-epochs', default=100, type=int, metavar='N',help='number of total epochs to run')parser.add_argument('-j', default=4, type=int, metavar='N',help='number of data loading workers (default: 4)')
# 添加 default='./MNIST' 以解決無下載所需文件夾問題----------------------------------------parser.add_argument('-data-dir', type=str, default='./MNIST', help='root dir of MNIST dataset')
# -----------------------------------------------------------------------------------------parser.add_argument('-out-dir', type=str, default='./logs', help='root dir for saving logs and checkpoint')parser.add_argument('-resume', type =str, help='resume from the checkpoint path')parser.add_argument('-amp', action='store_true', help='automatic mixed precision training')parser.add_argument('-opt', type=str, choices=['sgd', 'adam'], default='adam', help='use which optimizer. SGD or Adam')parser.add_argument('-momentum', default=0.9, type=float, help='momentum for SGD')parser.add_argument('-lr', default=1e-3, type=float, help='learning rate')parser.add_argument('-tau', default=2.0, type=float, help='parameter tau of LIF neuron')

注:在代碼上述標記位置添加? default='./MNIST' 以解決無下載所需文件夾問題

超參數含義如下圖所示:

(2) 參數代入:是否自動混合精度訓練(PyTorch的自動混合精度(AMP) - 知乎 (zhihu.com))

scaler = Noneif args.amp:scaler = amp.GradScaler()

(3)參數代入:優化器類型

optimizer = Noneif args.opt == 'sgd':optimizer = torch.optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum)elif args.opt == 'adam':optimizer = torch.optim.Adam(net.parameters(), lr=args.lr)else:raise NotImplementedError(args.opt)

?(4)是否恢復斷點訓練(if args.resume:從斷點處開始繼續訓練模型)

    if args.resume:checkpoint = torch.load(args.resume, map_location='cpu')net.load_state_dict(checkpoint['net'])optimizer.load_state_dict(checkpoint['optimizer'])start_epoch = checkpoint['epoch'] + 1max_test_acc = checkpoint['max_test_acc']

?(5)泊松編碼

encoder = encoding.PoissonEncoder()

2.2主循環

(1)在主循環之前補充創建兩個空數組,用于保存訓練過程中的準確率,以便后續繪制曲線

?(2)加載訓練數據(測試數據代碼大同小異,不另外分析)

        for img, label in train_data_loader:optimizer.zero_grad()img = img.to(args.device)label = label.to(args.device)label_onehot = F.one_hot(label, 10).float()
  1. 循環讀取訓練數據,在每次循環前,清空優化器梯度
  2. 將img、label放置到GPU上訓練
  3. 對標簽進行獨熱編碼,10個類別(獨熱編碼(One-Hot Encoding) - 知乎 (zhihu.com))

(3)判斷是否使用混合精度訓練

            if scaler is not None:with amp.autocast():out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_fr = out_fr / args.Tloss = F.mse_loss(out_fr, label_onehot)scaler.scale(loss).backward()scaler.step(optimizer)scaler.update()else:out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_fr = out_fr / args.Tloss = F.mse_loss(out_fr, label_onehot)loss.backward()optimizer.step()

如果使用:
???- 用amp.autocast()包裹前向計算,使其在浮點16位計算
???- 用scaler縮放損失scale(loss)
???- 損失回傳
???- 通過scaler更新優化器

如果不使用混合精度:
???- 正常進行前向計算
???- 損失函數計算
???- 反向傳播
???- 優化器更新

(4)重置網絡

functional.reset_net(net)

SNN中的脈沖神經元在前向傳播時會積累狀態,比如膜電位、釋放的脈沖等。重置可以清空這些狀態,使網絡回到初始狀態。

(5)在下圖位置添加對應代碼保存.npy文件

?3.可視化

?3.1準確率

?在examples文件夾下創建一個.py文件,用于對結果的可視化

?代碼如下:

import numpy as np
import matplotlib.pyplot as plttest_accs = np.load("./train_accs.npy")
x = []
y = []
maxy = -1
maxx = -1
for t in range(len(test_accs)):if test_accs[t] > maxy:maxy = test_accs[t]maxx = tx.append(t)y.append(test_accs[t])
plt.plot(x, y)
# plt.plot(test_accs)
plt.xlabel('Iteration')
plt.ylabel('Acc')
plt.title('Train Acc')
plt.annotate(r'(%d,%f)' % (maxx, maxy), xy=(maxx, maxy), xycoords='data', xytext=(+10, +20), fontsize=16,arrowprops=dict(arrowstyle='->'), textcoords='offset points')
plt.show()
test_accs = np.load("./test_accs.npy")
x = []
y = []
maxy = -1
maxx = -1
for t in range(len(test_accs)):if test_accs[t] > maxy:maxy = test_accs[t]maxx = tx.append(t)y.append(test_accs[t])
# plt.plot(x, y)
plt.plot(test_accs)
plt.xlabel('Epoch')
plt.ylabel('Acc')
plt.title('Test Acc')
plt.annotate(r'(%d,%f)' % (maxx, maxy), xy=(maxx, maxy), xycoords='data', xytext=(+10, +20), fontsize=16,arrowprops=dict(arrowstyle='->'), textcoords='offset points')
plt.show()

效果:

?

?3.2測試圖片與發放脈沖

?添加如下代碼至main()函數的末尾:

 img = img.cpu().numpy().reshape(28, 28)plt.subplot(221)plt.imshow(img)plt.subplot(222)plt.imshow(img, cmap='gray')plt.subplot(223)plt.imshow(img, cmap=plt.cm.gray)plt.subplot(224)plt.imshow(img, cmap=plt.cm.gray_r)plt.show()

效果:?

3.3脈沖發放與電壓

?新建文件夾,運行如下代碼:

    test_spike = np.load("./s_t_array.npy")test_mem = np.load('./v_t_array.npy')visualizing.plot_2d_heatmap(array=np.asarray(test_mem), title='Membrane Potentials', xlabel='Simulating Step',ylabel='Neuron Index', int_x_ticks=True, x_max=100, dpi=200)visualizing.plot_1d_spikes(spikes=np.asarray(test_spike), title='Membrane Potentials', xlabel='Simulating Step',ylabel='Neuron Index', dpi=200)plt.show()

效果:

4.完整代碼?

lif_fc_mnist.py(為減少運行耗時,迭代次數設置為1)

import os
import time
import argparse
import sys
import datetimeimport torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data as data
from torch.cuda import amp
from torch.utils.tensorboard import SummaryWriter
import torchvision
import numpy as np
import matplotlib.pyplot as pltfrom spikingjelly.activation_based import neuron, encoding, functional, surrogate, layerclass SNN(nn.Module):def __init__(self, tau):super().__init__()self.layer = nn.Sequential(layer.Flatten(),layer.Linear(28 * 28, 10, bias=False),neuron.LIFNode(tau=tau, surrogate_function=surrogate.ATan()),)def forward(self, x: torch.Tensor):return self.layer(x)def main():''':return: None* :ref:`API in English <lif_fc_mnist.main-en>`.. _lif_fc_mnist.main-cn:使用全連接-LIF的網絡結構,進行MNIST識別。\n這個函數會初始化網絡進行訓練,并顯示訓練過程中在測試集的正確率。* :ref:`中文API <lif_fc_mnist.main-cn>`.. _lif_fc_mnist.main-en:The network with FC-LIF structure for classifying MNIST.\nThis function initials the network, starts trainingand shows accuracy on test dataset.'''parser = argparse.ArgumentParser(description='LIF MNIST Training')parser.add_argument('-T', default=100, type=int, help='simulating time-steps')parser.add_argument('-device', default='cuda:0', help='device')parser.add_argument('-b', default=64, type=int, help='batch size')# 100parser.add_argument('-epochs', default=1, type=int, metavar='N',help='number of total epochs to run')parser.add_argument('-j', default=4, type=int, metavar='N',help='number of data loading workers (default: 4)')parser.add_argument('-data-dir', type=str, default='./MNIST', help='root dir of MNIST dataset')parser.add_argument('-out-dir', type=str, default='./logs', help='root dir for saving logs and checkpoint')parser.add_argument('-resume', type =str, help='resume from the checkpoint path')parser.add_argument('-amp', action='store_true', help='automatic mixed precision training')parser.add_argument('-opt', type=str, choices=['sgd', 'adam'], default='adam', help='use which optimizer. SGD or Adam')parser.add_argument('-momentum', default=0.9, type=float, help='momentum for SGD')parser.add_argument('-lr', default=1e-3, type=float, help='learning rate')parser.add_argument('-tau', default=2.0, type=float, help='parameter tau of LIF neuron')args = parser.parse_args()print(args)net = SNN(tau=args.tau)print(net)net.to(args.device)# 初始化數據加載器train_dataset = torchvision.datasets.MNIST(root=args.data_dir,train=True,transform=torchvision.transforms.ToTensor(),download=True)test_dataset = torchvision.datasets.MNIST(root=args.data_dir,train=False,transform=torchvision.transforms.ToTensor(),download=True)train_data_loader = data.DataLoader(dataset=train_dataset,batch_size=args.b,shuffle=True,drop_last=True,num_workers=args.j,pin_memory=True)test_data_loader = data.DataLoader(dataset=test_dataset,batch_size=args.b,shuffle=False,drop_last=False,num_workers=args.j,pin_memory=True)scaler = Noneif args.amp:scaler = amp.GradScaler()start_epoch = 0max_test_acc = -1optimizer = Noneif args.opt == 'sgd':optimizer = torch.optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum)elif args.opt == 'adam':optimizer = torch.optim.Adam(net.parameters(), lr=args.lr)else:raise NotImplementedError(args.opt)if args.resume:checkpoint = torch.load(args.resume, map_location='cpu')net.load_state_dict(checkpoint['net'])optimizer.load_state_dict(checkpoint['optimizer'])start_epoch = checkpoint['epoch'] + 1max_test_acc = checkpoint['max_test_acc']out_dir = os.path.join(args.out_dir, f'T{args.T}_b{args.b}_{args.opt}_lr{args.lr}')if args.amp:out_dir += '_amp'if not os.path.exists(out_dir):os.makedirs(out_dir)print(f'Mkdir {out_dir}.')with open(os.path.join(out_dir, 'args.txt'), 'w', encoding='utf-8') as args_txt:args_txt.write(str(args))writer = SummaryWriter(out_dir, purge_step=start_epoch)with open(os.path.join(out_dir, 'args.txt'), 'w', encoding='utf-8') as args_txt:args_txt.write(str(args))args_txt.write('\n')args_txt.write(' '.join(sys.argv))encoder = encoding.PoissonEncoder()# 創建保存數組train_accs = []test_accs = []for epoch in range(start_epoch, args.epochs):start_time = time.time()net.train()train_loss = 0train_acc = 0train_samples = 0for img, label in train_data_loader:optimizer.zero_grad()img = img.to(args.device)label = label.to(args.device)label_onehot = F.one_hot(label, 10).float()if scaler is not None:with amp.autocast():out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_fr = out_fr / args.Tloss = F.mse_loss(out_fr, label_onehot)scaler.scale(loss).backward()scaler.step(optimizer)scaler.update()else:out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_fr = out_fr / args.Tloss = F.mse_loss(out_fr, label_onehot)loss.backward()optimizer.step()train_samples += label.numel()train_loss += loss.item() * label.numel()train_acc += (out_fr.argmax(1) == label).float().sum().item()functional.reset_net(net)train_time = time.time()train_speed = train_samples / (train_time - start_time)train_loss /= train_samplestrain_acc /= train_sampleswriter.add_scalar('train_loss', train_loss, epoch)writer.add_scalar('train_acc', train_acc, epoch)net.eval()test_loss = 0test_acc = 0test_samples = 0with torch.no_grad():for img, label in test_data_loader:img = img.to(args.device)label = label.to(args.device)label_onehot = F.one_hot(label, 10).float()out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_fr = out_fr / args.Tloss = F.mse_loss(out_fr, label_onehot)test_samples += label.numel()test_loss += loss.item() * label.numel()test_acc += (out_fr.argmax(1) == label).float().sum().item()functional.reset_net(net)test_time = time.time()test_speed = test_samples / (test_time - train_time)test_loss /= test_samplestest_acc /= test_sampleswriter.add_scalar('test_loss', test_loss, epoch)writer.add_scalar('test_acc', test_acc, epoch)save_max = Falseif test_acc > max_test_acc:max_test_acc = test_accsave_max = Truecheckpoint = {'net': net.state_dict(),'optimizer': optimizer.state_dict(),'epoch': epoch,'max_test_acc': max_test_acc}if save_max:torch.save(checkpoint, os.path.join(out_dir, 'checkpoint_max.pth'))torch.save(checkpoint, os.path.join(out_dir, 'checkpoint_latest.pth'))print(args)print(out_dir)print(f'epoch ={epoch}, train_loss ={train_loss: .4f}, train_acc ={train_acc: .4f}, test_loss ={test_loss: .4f}, test_acc ={test_acc: .4f}, max_test_acc ={max_test_acc: .4f}')print(f'train speed ={train_speed: .4f} images/s, test speed ={test_speed: .4f} images/s')print(f'escape time = {(datetime.datetime.now() + datetime.timedelta(seconds=(time.time() - start_time) * (args.epochs - epoch))).strftime("%Y-%m-%d %H:%M:%S")}\n')#     保存數據至數組train_accs = np.append(train_accs, train_acc)test_accs = np.append(test_accs, test_acc)# print(train_accs)# 寫入npynp.save("./test_accs.npy", test_accs)np.save("./train_accs.npy", train_accs)# 保存繪圖用數據net.eval()# 注冊鉤子output_layer = net.layer[-1] # 輸出層output_layer.v_seq = []output_layer.s_seq = []def save_hook(m, x, y):m.v_seq.append(m.v.unsqueeze(0))m.s_seq.append(y.unsqueeze(0))output_layer.register_forward_hook(save_hook)with torch.no_grad():img, label = test_dataset[0]img = img.to(args.device)out_fr = 0.for t in range(args.T):encoded_img = encoder(img)out_fr += net(encoded_img)out_spikes_counter_frequency = (out_fr / args.T).cpu().numpy()print(f'Firing rate: {out_spikes_counter_frequency}')output_layer.v_seq = torch.cat(output_layer.v_seq)output_layer.s_seq = torch.cat(output_layer.s_seq)v_t_array = output_layer.v_seq.cpu().numpy().squeeze()  # v_t_array[i][j]表示神經元i在j時刻的電壓值np.save("v_t_array.npy",v_t_array)s_t_array = output_layer.s_seq.cpu().numpy().squeeze()  # s_t_array[i][j]表示神經元i在j時刻釋放的脈沖,為0或1np.save("s_t_array.npy",s_t_array)img = img.cpu().numpy().reshape(28, 28)plt.subplot(221)plt.imshow(img)plt.subplot(222)plt.imshow(img, cmap='gray')plt.subplot(223)plt.imshow(img, cmap=plt.cm.gray)plt.subplot(224)plt.imshow(img, cmap=plt.cm.gray_r)plt.show()if __name__ == '__main__':main()

lif_fc_mnist_test.py

import numpy as np
import matplotlib.pyplot as plttest_accs = np.load("./train_accs.npy")
x = []
y = []
maxy = -1
maxx = -1
for t in range(len(test_accs)):if test_accs[t] > maxy:maxy = test_accs[t]maxx = tx.append(t)y.append(test_accs[t])
plt.plot(x, y)
# plt.plot(test_accs)
plt.xlabel('Iteration')
plt.ylabel('Acc')
plt.title('Train Acc')
plt.annotate(r'(%d,%f)' % (maxx, maxy), xy=(maxx, maxy), xycoords='data', xytext=(+10, +20), fontsize=16,arrowprops=dict(arrowstyle='->'), textcoords='offset points')
plt.show()
test_accs = np.load("./test_accs.npy")
x = []
y = []
maxy = -1
maxx = -1
for t in range(len(test_accs)):if test_accs[t] > maxy:maxy = test_accs[t]maxx = tx.append(t)y.append(test_accs[t])
# plt.plot(x, y)
plt.plot(test_accs)
plt.xlabel('Epoch')
plt.ylabel('Acc')
plt.title('Test Acc')
plt.annotate(r'(%d,%f)' % (maxx, maxy), xy=(maxx, maxy), xycoords='data', xytext=(+10, +20), fontsize=16,arrowprops=dict(arrowstyle='->'), textcoords='offset points')
plt.show()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36269.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36269.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36269.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【自用】終端設備(ESP32-S3)連接云服務器 HomeAssistant + MQTT 物聯網平臺

總覽 1.流程概述 2.開始搭建&#xff01; 3. 一、流程概述 0.總體流程 二、開始搭建 1.下載 MQTTX 客戶端&#xff08; 在PC上 &#xff09; https://mqttx.app/zh/downloads 2.新建 MQTTX 連接 0.點擊左側的加號&#xff0c;開始新建連接。 一共需要填寫幾個參數&#…

會玩這 10 個 Linux 命令,一定是個有趣的 IT 男!

Linux當中有很多比較有趣的命令&#xff0c;可以動手看看&#xff0c;很簡單的。 1.rev命令 一行接一行地顛倒所輸入的字符串。 運行&#xff1a; $rev如輸入&#xff1a;shiyanlou shiyanlou2.asciiview命令 1.先安裝aview $sudo apt-get install aview2.再安裝imagema…

vue中封裝自動計算比例滑塊

此插件為另一位漂亮的前端同事小姐姐封裝,覺得非常好用于是決定記載下來,便于復用 如圖需要動態傳入需要分配權重的數組,平均分配可以自動將100%平均分給數組中的值 如果手動拖拽,則會自動計算可拖動最大區域,便于最終總權重必定為100% <el-alert class"merge-alert&…

zookeeper常用命令

zookeeper常用命令 1. 下載安裝2. 配置說明2.1 配置 3. zookeeper的常見命令3.1 server端啟動停止等命令3.2 客戶端連接等命令3.3 客戶端簡單常用命令3.3.1 查看目錄&#xff08;查看數據結構&#xff09;3.3.2 刪除目錄3.3.3 創建目錄3.3.4 創建目錄并寫入值 查看節點值3.3.5…

Apache JMeter:完全指南

Apache JMeter 是一款開源的性能測試工具&#xff0c;可以用于測試 Web 應用程序、FTP 服務器、數據庫等各種類型的服務器。本文將以 JMeter 5.5 為例介紹 JMeter 的使用方法。 下載和安裝 由于 JMeter 是使用 Java 開發的&#xff0c;因此在運行之前必須先安裝 JDK。您可以在…

Android中tools屬性的使用

參考&#xff1a; 1.Android:Tools命名空間原來是有大用處的 2.Android中tools屬性的使用 3.工具屬性參考文檔 4. 命名空間介紹 5. 注解 6. lint 7. 資源壓縮shrink-resources 目錄 一、概述二、引入tools命名空間三、tools 命名空間的作用有哪些&#xff1f;四、tools 命名空間…

年薪6.5萬美元|生物醫學老師獲美國耶魯大學博士后職位

I老師就職于雙非二本院校&#xff0c;希望通過出國研修以提升科研背景&#xff0c;在公派訪學和申請導師出資的博士后之間&#xff0c;其選擇了后者。最終我們落實了美國耶魯大學的職位&#xff0c;頭銜為Associate Research Scientist&#xff08;副研究科學家&#xff09;&am…

Selenium 自動化 | 案例實戰篇

Chrome DevTools 簡介 Chrome DevTools 是一組直接內置在基于 Chromium 的瀏覽器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于幫助開發人員調試和研究網站。 借助 Chrome DevTools&#xff0c;開發人員可以更深入地訪問網站&#xf…

Observability:識別生成式 AI 搜索體驗中的慢速查詢

作者&#xff1a;Philipp Kahr Elasticsearch Service 用戶的重要注意事項&#xff1a;目前&#xff0c;本文中描述的 Kibana 設置更改僅限于 Cloud 控制臺&#xff0c;如果沒有我們支持團隊的手動干預&#xff0c;則無法進行配置。 我們的工程團隊正在努力消除對這些設置的限制…

uniapp動態底部tab欄

實現思路&#xff1a; 創建一個js文件用來存放所有的tabbar,不同的數組表示不同的tabbar組合。 創建一個vue文件用來制作底部tabbar組件。 使用vuex存儲用戶的身份信息,根據身份信息切換tabbar組合。 具體步驟&#xff1a; 新建一個tabbar.js文件&#xff0c;將…

SpringBoot 整合MyBatis

整合MyBatis 官方文檔&#xff1a;http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/ Maven倉庫地址&#xff1a;https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/2.1.3 整合測試 導入 MyBatis 所需要的…

數據結構筆記--優先隊列(大小根堆)經典題型

1--項目的最大利潤 題目描述&#xff1a; 輸入&#xff1a;正數數組 costs&#xff0c;costs[i] 表示項目 i 的花費&#xff1b;正數數組 profits&#xff0c;profits[i] 表示項目 i 的花費&#xff1b;正數 k 表示只能串行完成最多 k 個項目&#xff1b;m 表示擁有的資金&…

MySQL事務:確保數據完整性與并發性的關鍵

MySQL事務&#xff1a;確保數據完整性與并發性的關鍵 MySQL作為一種廣泛使用的開源關系型數據庫管理系統&#xff0c;具備強大的事務支持&#xff0c;以確保數據庫操作的一致性、隔離性和持久性。本文將深入探討MySQL中的事務概念、事務隔離級別以及事務的應用場景&#xff0c…

leetcode 516. 最長回文子序列(JAVA)題解

題目鏈接https://leetcode.cn/problems/longest-palindromic-subsequence/description/?utm_sourceLCUS&utm_mediumip_redirect&utm_campaigntransfer2china 目錄 題目描述&#xff1a; 暴力遞歸&#xff1a; 動態規劃&#xff1a; 題目描述&#xff1a; 給你一個…

Python學習過程筆記:主模塊(main) 異常處理 命令行參數解析 日志記錄 socket模塊 類的私有方法 字節字符串

文章目錄 1.Python中的主程序2.Python中的異常處理3.Python中的命令行參數解析4.Python中的日志記錄5.網絡編程socket模塊6.Python中的私有方法7.Python中的字節字符串 1.Python中的主程序 if __name__ __main__在Python中&#xff0c;if __name__ __main__ 是一個常見的代碼…

百日筑基篇——python爬蟲學習(一)

百日筑基篇——python爬蟲學習&#xff08;一&#xff09; 文章目錄 前言一、python爬蟲介紹二、URL管理器三、所需基礎模塊的介紹1. requests2. BeautifulSoup1. HTML介紹2. 網頁解析器 四、實操1. 代碼展示2. 代碼解釋1. 將大文件劃分為小的文件&#xff08;根據AA的ID數量劃…

簡單認識Zabbix監控系統及配置

文章目錄 一、zabbix概述1、定義2、zabbix監控原理3、監控對象4、zabbix的3種架構&#xff08;1&#xff09; C/S架構&#xff08;2&#xff09;分布式架構&#xff1a;zabbix-proxy-client架構&#xff08;3&#xff09; master-node-client架構 5、zabbix監控模式 二、部署za…

項目實戰 — 消息隊列(8){網絡通信設計①}

目錄 一、自定義應用層協議 &#x1f345; 1、格式定義 &#x1f345; 2、準備工作 &#x1f384;定義請求和響應 &#x1f384; 定義BasicArguments &#x1f384; 定義BasicReturns &#x1f345; 2、創建參數類 &#x1f384; 交換機 &#x1f384; 隊列 &#x1f38…

【網絡】傳輸層——TCP(滑動窗口流量控制擁塞控制延遲應答捎帶應答)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;專欄&#xff1a;《網絡》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交給時間&#xff01; 上篇文章對TCP可靠性機制講解了一部分&#xff0c;這篇文章接著繼續講解。 &#x1f3a8;滑動窗口 在…

Springboot 實踐(2)MyEclipse2019創建項目修改pom文件,加載springboot 及swagger-ui jar包

MyEclipse2019創建工程之后&#xff0c;需要添加Springboot啟動函數、添加application.yml配置文件、修改pom文件添加項目使用的jar包。 添加Springboot啟動函數 創建文件存儲路徑 &#xff08;1&#xff09;右鍵單擊“src/main/java”文件夾&#xff0c;彈出對話框輸入路徑…