深度學習 tensor及其相關操作

?

目錄

Tensor

概念

數據類型

創建tensor

基本創建方式

1、?torch.tensor()

2、torch.Tensor()

3、torch.IntTensor() 等

創建線性張量和隨機張量

1、創建線性張量

2、創建隨機張量

切換設備

類型轉換

與 Numpy 數據轉換

1、張量轉 Numpy

2、Numpy 轉張量

tensor常見操作

1、獲取元素值

2、元素值運算

3、tensor相乘

4、形狀操作

view():

reshape():

5、維度轉換

transpose(dim0, dim1):兩個維度轉換

permute(dim0, dim1, ... , dimN):重排所有維度

6、升維降維

unsqueeze():升維

squeeze():降維


PyTorch是一個基于Python的深度學習框架,它提供了一種靈活、高效、易于學習的方式來實現深度學習模型,最初由Facebook開發,被廣泛應用于計算機視覺、自然語言處理、語音識別等領域。PyTorch提供了許多高級功能,如自動微分(automatic differentiation)自動求導(automatic gradients)等,這些功能可以幫助我們更好地理解模型的訓練過程,并提高模型訓練效率。

沒錯苯人開始 pytorch的學習了,這篇來寫一下 Torch 的一些基本API。

Tensor

概念

?PyTorch會將數據全都封裝成張量(Tensor)進行計算,所謂張量就是元素為相同類型的多維矩陣,或者多維數組,通俗來說可以看作是擴展了標量、向量、矩陣的更高維度的數組。張量的維度決定了它的形狀(Shape),例如:

  • 標量?是 0 維張量,如 a = torch.tensor(5)

  • 向量 是 1 維張量,如?b = torch.tensor([1, 2, 3])

  • 矩陣 是 2 維張量,如 c = torch.tensor([[1,2], [3,4]])

  • 更高維度的張量,如3維、4維等,通常用于表示圖像、視頻數據等復雜結構。

數據類型

? PyTorch中有3種數據類型:浮點數類型、整數類型、布爾類型。其中,浮點數和整數又分為8位、16位、32位、64位,加起來共9種。為什么要分這么多種類型呢是因為場景不同,對數據的精度和速度要求不同。通常,移動或嵌入式設備追求速度,對精度要求相對低一些。精度越高,往往效果也越好,自然硬件開銷就比較高。

創建tensor

以下講的創建 tensor 的函數中有兩個有默認值的參數 dtype device, 分別代表數據類型和計算設備,可以通過屬性 dtype 和 device 獲取,如 print(t1.dtype)

基本創建方式

1、?torch.tensor()

代碼示例:

def test1():# 創建張量t1 = torch.tensor(88) #創建標量t2 = torch.tensor(np.random.randn(3, 2)) #用numpy隨機數組創建1維張量t3 = torch.tensor([[1, 2, 3], [4, 5, 6]]) #創建2維張量print(t1)print(t2)print(t2.shape)print(t3)print(t3.shape)

運行結果:

注意,如果出現?UserWarning: Failed to initialize NumPy: _ARRAY_API not found 錯誤,一般是因為 numpy和pytorch版本不兼容,可以降低 numpy版本,直接卸載重裝,最好是1.x版本

2、torch.Tensor()

代碼示例:

def test2():#torch.Tenor()創建張量t1 = torch.Tensor(3) #根據形狀創建print(t1)t2 = torch.Tensor([[1,2,3],[4,5,6]]) #根據具體的值創建print(t2)print(t2.shape)

運行結果:

這里可以看到,當傳入的是一個整數時,tensor() 是直接創建標量,而 Tensor() 則是初始化一個形狀為該整數的張量。除此之外,它倆的區別還在于:

特性torch.Tensor()torch.tensor()
數據類型推斷強制轉為 torch.float32根據輸入數據自動推斷(如整數→int64
顯式指定 dtype不支持支持(如 dtype=torch.float64
設備指定不支持支持(如 device='cuda'
輸入為張量時的行為創建新副本(不繼承原屬性)默認共享數據(除非 copy=True
推薦使用場景需要快速創建浮點張量需要精確控制數據類型或設備

一般是使用 torch.tensor() 更多,更安全、功能更全,可避免未初始化張量的隱患。

3、torch.IntTensor() 等

?用于創建指定類型的張量,諸如此類還有 torch.FloatTensor(32位浮點數)、 torch.DoubleTensor(64位浮點數)、torch.ShortTensor(16位整數)、?torch.LongTensor(64位整數)......等。如果數據類型不匹配,那么在創建的過程中會進行類型轉換,防止數據丟失。

代碼示例:

def test3():#創建指定類型的張量tt1 = torch.IntTensor(3,3)print(tt1)tt2 = torch.FloatTensor(3, 3)print(tt2, tt2.dtype)tt3 = torch.DoubleTensor(3, 3)print(tt3, tt3.dtype)tt4 = torch.LongTensor(3, 3)print(tt4, tt4.dtype)tt5 = torch.ShortTensor(3, 3)print(tt5, tt5.dtype)

運行結果就不貼了

創建線性張量和隨機張量

1、創建線性張量

可使用 torch.arange() 和 torch.linspace() 創建一維線性張量

torch.arange(start, end, step):生成一個等間隔的一維張量(序列),區間為 [start, end)(左閉右開),步長由 step 決定。

torch.linspace(start, end, step):生成一個在區間 [start, end](左右均閉合)內均勻分布的 steps 個元素的一維張量(相當于等差數列)

代碼示例如下:

def test4():# 創建線性張量t1 = torch.arange(0, 10, step=2)print(t1)t2 = torch.linspace(1, 2, steps=5)print(t2)

運行結果:

2、創建隨機張量

使用torch.randn 和 torch.randint 創建隨機張量。

torch.randn(size, ?dtype?, device?, requires_grad) :生成服從標準正態分布(均值為 0,標準差為 1)的隨機張量,size 可以傳元組或者直接傳數字,生成的都是二維張量;后兩個參數就不過多介紹;requires_grad 表示是否需要計算梯度,默認為False,這個參數很重要,可能下一篇會說。

torch.randint(low, high, size):在指定的[ low, high)范圍內生成離散的、均勻分布的整數,low 為最小值,high 為最大值,size 為張量的形狀

另外還要介紹一下隨機數種子:隨機數種子(Random Seed)?是控制計算機生成“隨機數”的一個關鍵參數,它的存在讓“隨機”變得可復現,設置種子后算法會固定從同一個“起點”開始計算,生成的隨機序列完全一致,至于設置什么數字并不重要,只是不同的數字生成的數字序列不同罷了,API為??torch.manual_seed()

代碼實例:

def test5():'''創建隨機張量'''torch.manual_seed(42)# 設置隨機數種子t1 = torch.randn(2,3) #生成隨機張量,標準正態分布,均值 0,標準差 1t2 = torch.rand(2,3) #生成隨機張量,均勻分布,范圍在 [0, 1)t3 = torch.randint(0, 10, (2, 3)) #在0到10內(不包括10)生成 2x3 的張量print(t1)print(t2)print(t3)

運行結果:

這里因為設置了隨機數種子所以每次輸出的結果都相同,如果將第一行注釋掉,每次生成的張量就不一樣了,同時注意一下 size 有沒有括號都是生成的二維數組,當然也可以生成三維張量,例如

torch.rand(2, 3, 4)

切換設備

tensor 相關操作默認在cpu上運行,但是可以顯式地切換到GPU,且不同設備上的數據是不能相互運算的。切換操作如下:

def test6():'''切換設備'''t1 = torch.tensor([1,2,3])print(t1.shape, t1.dtype, t1.device)#切換到GPU 方法一device = "cuda" if torch.cuda.is_available() else "cpu"print(t1.device)# 切換到GPU 方法二 to()方法t1 = t1.to(device="cuda")print(t1.device)

運行結果:

因為苯人電腦沒有顯卡所以轉不過去,這里只是一個代碼示范

或者直接用 cuda 進行轉換:

t1 = t1.cuda()

當然也可以直接在 GPU 上創建張量:

data = torch.tensor([1, 2, 3], device='cuda')
print(data.device)

類型轉換

?在寫代碼時,類型的不同有時也會導致各種錯誤,所以類型的轉換也是很重要的,有三種類型轉換的方法:

def test7():'''類型轉換'''t1 = torch.tensor([1,2,3])print(t1.dtype) #torch.int64# 1、使用 type() 進行轉換t1 = t1.type(torch.float32)print(t1.dtype) #torch.float32# 2、使用類型方法轉換t1 = t1.float()print(t1.dtype)  # float32t1 = t1.half()print(t1.dtype)  # float16t1 = t1.double()print(t1.dtype)  # float64t1 = t1.long()print(t1.dtype)  # int64t1 = t1.int()print(t1.dtype)  # int32# 3、使用 dtype 屬性指定t1 = torch.tensor([1,2,3], dtype=torch.float32)print(t1.dtype) #torch.float32

與 Numpy 數據轉換

1、張量轉 Numpy

淺拷貝:內存共享,修改 Numpy數組也會改變原張量,API:numpy()

深拷貝:內存不共享,相當于建了一個獨立的副本,API:numpy().copy()

代碼示例(淺拷貝):

def test8():'''張量轉numpy'''#淺拷貝t1 = torch.tensor([[1,2,3], [4,5,6],[7,8,9]])t2 = t1.numpy() 轉 numpyprint(t1)print(f't2:{t2}')t2[0][1] = 666 #內存共享print(t1)print(f't2:{t2}')

運行結果:

可以看到,t1 轉成 t2 后,修改 t2 還是會改變 t1,如果想要避免內存共享可以用深拷貝:

    #深拷貝# t2 = t1.numpy().copy()

其他同上

2、Numpy 轉張量

同樣分為內存共享和內存不共享:

淺拷貝:內存共享,修改 tensor 也會改變原數組,API:torch.from_numpy()

深拷貝:內存不共享,相當于建了一個獨立的副本,API:torch.tensor()

代碼示例(深拷貝):

'''numpy轉張量'''# 深拷貝n1 = np.array([[11,22,33],[44,55,66]])n1_tensor = torch.tensor(n1) #轉張量print(f'n1:{n1}')print(f'n1_tensor:{n1_tensor}')n1_tensor[0][1] = 88 #內存不共享print(f'n1:{n1}')print(f'n1_tensor:{n1_tensor}')

運行結果:

可以看到,修改 n1_tensor 不會改變 n1,如果想要淺拷貝的話:

 #淺拷貝# n1_tensor = torch.from_numpy(n1)

tensor常見操作

?接下來介紹一些在深度學習中基本的 tensor 操作:

1、獲取元素值

我們可以把只含有單個元素的 tensor 轉換為Python數值,這和 tensor 的維度無關,但若有多個元素則會報錯,且僅適用于 CPU張量。

API為 item():

def test9():'''獲取元素值'''t1 = torch.tensor([[[18]]])t2 = torch.tensor([20,13])print(t1.item())print(t2.item())

運行結果:

可以看到佑報錯,這就是因為 t2 含有不止一個元素所以不能用 item()

2、元素值運算

?常見的加、減、乘、除、次方、取反、開方等各種操作,但是也分是否修改原始值

不修改原始值代碼示例:

'''元素值運算'''t1 = torch.randint(0, 10, (2,3))print(f't1:{t1}')print(t1.add(1))print(t1.sub(1))print(t1.mul(2))print(t1.div(2))print(f't1:{t1}')

運行結果:

可以看到,經過加減乘除后 t1 的元素并沒有被改變

修改原始值:

t2 = torch.randint(0, 10, (2, 3))print(f't2:{t2}')t2.add_(1)print(f't2:{t2}')

運行結果:

可以看到 t2 已被改變,所以帶下劃線 “_” 的運算會改變原始值

3、tensor相乘

tensor 之間的乘法有兩種,一種是矩陣乘法,還有一種是阿達瑪積。

矩陣乘法是線性代數中的一種基本運算,用于將兩個矩陣相乘,生成一個新的矩陣。

舉個例子,假設有兩個矩陣:

  • 矩陣 A的形狀為 m×n(m行 n列)。

  • 矩陣 B的形狀為 n×p(n行 p列)。

則矩陣?A和 B的乘積 C=A×B,是一個形狀為 m×p的矩陣,可以理解為前一個矩陣控制行數,后一個矩陣控制列數,計算公式為:

要求如果第一個矩陣的shape是 (N, M),那么第二個矩陣 shape必須是 (M, P),最后兩個矩陣點積運算的shape為 (N, P),而在 pytorch 中,使用 matmul() 或者 @ 來完成 tensor 的乘法

代碼示例如下:

import torchdef test1():'''矩陣乘法'''t1 = torch.tensor([[1,2,3],[4,5,6]])t2 = torch.tensor([[7,8],[9,10],[11,12]])# 兩種方法print(t1 @ t2)print(t1.matmul(t2))if __name__ == '__main__':test1()

運行結果:

下面介紹阿達瑪積。阿達瑪積是指兩個形狀相同的矩陣或張量對應位置的元素相乘。它與矩陣乘法不同,矩陣乘法是線性代數中的標準乘法,而阿達瑪積是逐元素操作。

假設有兩個形狀相同的矩陣 A和 B,則它們的阿達瑪積 C=A°B定義為:

在 pytorch 中,可以使用 * 或者 mul() 來實現,代碼如下:

'''阿達瑪積'''t3 = torch.tensor([[1,2,3],[4,5,6]])t4 = torch.tensor([[7,8,9],[11,22,33]])#兩種方法print(t3 * t4)print(t3.mul(t4))

運行結果:

4、形狀操作

?在 PyTorch 中,張量的形狀操作是非常重要的,因為它允許你靈活地調整張量的維度和結構,以適應不同的計算需求。 下面介紹兩種方法:

view():

快速改變張量的形狀,但不復制數據,新張量與原始張量共享內存。前提條件是原張量在內存中連續,可用?is_contiguous() 判斷,連續會輸出 True,否則需要先調用?contiguous() 轉成連續的

API為 view(size),size即新形狀,可以是元組或者 -1,單獨的 -1 表示展平向量,放在元組中表示自動計算某一維度的元素數量(必須與總元素一致)

代碼如下:

def test2():'''形狀操作'''# view()t1 = torch.arange(6) #創建一個0到5的一維張量print(t1.is_contiguous())t2 = t1.view(-1) #展平 雖然本來就是一維張量t3 = t1.view(2,3) #轉成 2x3 的張量t4 = t1.view(3,-1) #轉成3行 至于幾列由電腦自動計算 只要保證總元素相同print(f't1:{t1}')print(f't2:{t2}')print(f't3:{t3}')print(f't4:{t4}')

運行結果:

若t1 不連續,那么用 t1.contiguous().view() 進行操作

reshape():

更靈活的變形方法,自動處理連續性(如果原始張量不連續,會復制數據),連續的話內存就共享,否則相當于獨立數據。

API為 reshape(size),用法與 view() 相同,這里就不再展示代碼了,看一下兩者的區別吧:
?

特性

view()

reshape()
共享內存總是共享(需連續)可能共享(若連續)或復制
連續性要求必須連續自動處理連續性
使用場景確定張量連續時的高效操作不確定連續性時的通用操作

5、維度轉換

pytorch 中維度轉換分為兩個維度轉換和多個維度轉換,分別用不同的方法:

transpose(dim0, dim1):兩個維度轉換

transpose() 僅用于兩個維度的轉換如矩形轉置,返回的是原張量的視圖,參數 dim0 是要交換的第一個維度,dim1 是要交換的第二個,代碼如下:

    t1 = torch.tensor([[1,2],[3,4]])t2 = t1.transpose(0,1) #交換維度,相當于轉置print(t1)print(t2)

運行結果:

?t2 = t1.transpose(0,1) 表示交換第0維和第1維,第0維表示張量的最外層結構,也就是行方向,第1維就表示列方向,所以交換的是行列方向,就相當于矩陣轉置了

permute(dim0, dim1, ... , dimN):重排所有維度

?permute() 方法自由重新排列所有維度,可一次性交換多個維度,適用于復雜的維度重組(如調整圖像通道順序),代碼如下:

    #多維度重排 permutet3 = torch.rand(2,3,4)t4 = t3.permute(2,1,0)print(t4.shape)

運行結果:

兩者的區別在于:

特性transpose(dim0, dim1)permute(dim0, dim1, ..., dimN)
交換維度數量只能交換兩個維度可以一次性重排所有維度
靈活性
常用場景矩陣轉置、簡單維度交換復雜的維度重組(如NCHW→NHWC)
連續性通常輸出不連續通常輸出不連續

注意,使用了這兩個方法后輸出的新張量通常不連續,所以后續可能要用?contiguous() 轉換

6、升維降維

?升維和降維是常用的操作,需要掌握:

unsqueeze():升維

?升維操作是在一個指定的位置插入一個大小為 1 的新維度,API為 unsqueeze(dim)dim 為指定要增加維度的位置(從 0 開始索引),代碼示例如下:

def test4():'''升維 unsqueeze()'''t1 = torch.rand(2,3,4)t1 = t1.unsqueeze(2)print(t1.shape)

運行結果:

squeeze():降維

?降維是去除不必要的維度,API為 squeeze(dim),dim 是指定要移除的維度。如果指定了 dim,則只移除該維度(前提是該維度大小為 1),如果不指定,則移除所有大小為 1 的維度,代碼示例:
?

'''降維squeeze()'''t2 = torch.tensor([[[1,2,3]]]) #形狀為 (1,1,3)t3 = t2.squeeze() #不指定dimt4 = t2.squeeze(0) #指定dim為0print(t2.shape)print(t3.shape)print(t4.shape)

運行結果:

可以看到,當不指定 dim 時移除了所有大小為1的維度。指定之后只移除了第0維的1。

這篇就到這里,但其實還有很多其他的操作只是我不想寫了[暈],居然寫了8000多字。。下一篇寫啥我也沒想好,先這樣吧(??????)??

以上有問題可以指出

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

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

相關文章

如何將FPGA設計的驗證效率提升1000倍以上(4)

本文為系列文章的完結篇。用戶應用設計中的信號,在經歷編譯器的多次迭代優化之后,在FPGA芯片內部運行時,可能已經被重新命名、“改頭換面”或“機里機氣”。要想以人工經驗進行追蹤,構建目標寄存器信號與RTL設計源碼之間的映射關系…

Linux驅動11 --- buildroot雜項驅動開發方法

目錄 一、Buildroot 1.1介紹 文件系統 1.一個完整的操作系統需要包含大量的文件 2.在嵌入式開發中目前應用最廣泛的文件系統制作工具就是 buildroot,busybox 3.buildroot 制作文件系統(了解) 二、雜項驅動編程 1.1 驅動編程做的內容 2.2…

Unity物理系統由淺入深第三節:物理引擎底層原理剖析

Unity物理系統由淺入深第一節:Unity 物理系統基礎與應用 Unity物理系統由淺入深第二節:物理系統高級特性與優化 Unity物理系統由淺入深第三節:物理引擎底層原理剖析 Unity物理系統由淺入深第四節:物理約束求解與穩定性 Unity 物理…

Docker一鍵安裝中間件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)腳步

1、Docker安裝RocketMq 2、Docker安裝Nginx 3、Docker安裝MySql 4、Docker安裝Minio 5、Docker安裝jenkins 6、Docker安裝Redis 1、Docker安裝RocketMq #!/bin/bash# 定義變量 NAMESRV_CONTAINER"rocketmq-namesrv" BROKER_CONTAINER"rocketmq-broker&quo…

WPF學習筆記(27)科學計算器

科學計算器1. 前端界面2. 功能代碼3. 效果展示1. 前端界面 <Window x:Class"Cal.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http:/…

【Linux系列】unzip file 命令

博客目錄掌握 unzip -o 命令&#xff1a;高效解壓并覆蓋文件的完整指南一、unzip 命令基礎二、-o 選項的核心作用三、典型應用場景四、與其他選項的組合使用五、注意事項與風險防范六、替代方案與高級技巧掌握 unzip -o 命令&#xff1a;高效解壓并覆蓋文件的完整指南 在日常的…

1965–2022年中國大陸高分辨率分部門用水數據集,包含:灌溉用水、工業制造用水、生活用水和火電冷卻

1965–2022年中國大陸高分辨率部門用水數據集 高質量用水數據集對推進變化環境下的水資源研究至關重要。然而&#xff0c;現有中國用水數據通常按行政區劃或流域匯總&#xff0c;時空分辨率不足&#xff0c;難以支撐人類用水模式及時空變化特征的精細化分析。為此&#xff0c;…

git中的指令解釋

在 Git 的 diff 輸出中&#xff0c;---、 和 ... 塊的含義如下&#xff1a; 1. --- a/1.py 和 b/1.py --- a/1.py&#xff1a;表示舊版本的文件路徑&#xff08;通常是工作目錄或上一次提交的版本&#xff09;。 b/1.py&#xff1a;表示新版本的文件路徑&#xff08;通常是暫存…

STM32實現四自由度機械臂(SG90舵機)多功能控制(軟件篇freertos)

書接上回的硬件篇STM32控制四自由度機械臂&#xff08;SG90舵機&#xff09;&#xff08;硬件篇&#xff09;&#xff08;簡單易復刻&#xff09;-CSDN博客 此時硬件平臺已經搭建完畢&#xff0c;軟件總共設計了三種模式&#xff0c;分別為 模式1&#xff1a;搖桿&藍牙模…

docker常用命令集(2)

接前一篇文章&#xff1a;docker常用命令集&#xff08;1&#xff09; 本文內容參考&#xff1a; Docker build 命令 | 菜鳥教程 docker基礎(二)之docker build-CSDN博客 Docker push 命令 | 菜鳥教程 Docker pull 命令 | 菜鳥教程 特此致謝&#xff01; 3. docker build …

舒爾特方格訓練小游戲流量主微信小程序開源

功能特點 游戲核心功能&#xff1a; 隨機生成55舒爾特方格 按順序點擊數字1-25 實時計時和嘗試次數統計 錯誤點擊反饋&#xff08;視覺和觸覺&#xff09; 數據統計&#xff1a; 記錄每次完成時間 保存歷史最佳成績 保存最近5次嘗試記錄 統計嘗試次數&#xff08;錯誤點擊&…

在Spring Boot 開發中 Bean 的聲明和依賴注入最佳的組合方式是什么?

在Spring Boot 開發中&#xff0c;社區和 Spring 官方已經形成了一套非常明確的最佳實踐。這個黃金組合就是&#xff1a; Bean 聲明&#xff1a;使用構造型注解&#xff08;Stereotype Annotations&#xff09;&#xff0c;如 Service, Repository, Component 等。依賴注入&…

Oxygen XML Editor 26.0編輯器

Oxygen XML Editor 26.0編輯器 歡迎使用Oxygen XML Editor 26.0編輯器準備工作安裝javajdk安裝jdk驗證Oxygen XML Editor 26.0安裝歡迎使用Oxygen XML Editor 26.0編輯器 準備工作安裝java Java官網下載地址:https://www.oracle.com/java/technologies/ Oxygen XML Editor 2…

AWS Lambda Container 方式部署 Flask 應用并通過 API Gateway 提供訪問

前言 一年前寫過一篇 Lambda 運行 Flask 應用的博文: https://lpwmm.blog.csdn.net/article/details/139756140 當時使用的是 ZIP 包方式部署應用代碼, 對于簡單的 API 開發用起來還是可以的, 但是如果需要集成到 CI/CD pipeline 里面就有點不太優雅. 本文將介紹使用容器方式…

React虛擬DOM的進化之路

引言 在Web前端開發中&#xff0c;用戶交互的流暢性和頁面性能一直是核心挑戰。早期&#xff0c;開發者直接操作真實DOM&#xff08;Document Object Model&#xff09;時&#xff0c;頻繁的重排&#xff08;reflow&#xff09;和重繪&#xff08;repaint&#xff09;導致性能…

(7)機器學習小白入門 YOLOv:機器學習模型訓練詳解

— (1)機器學習小白入門YOLOv &#xff1a;從概念到實踐 (2)機器學習小白入門 YOLOv&#xff1a;從模塊優化到工程部署 (3)機器學習小白入門 YOLOv&#xff1a; 解鎖圖片分類新技能 (4)機器學習小白入門YOLOv &#xff1a;圖片標注實操手冊 (5)機器學習小白入門 YOLOv&#xff…

初識MySQL(三)之主從配置與讀寫分離實戰

主重復制 主重復制原理master開啟二進制日志記錄slave開啟IO進程&#xff0c;從master中讀取二進制日志并寫入slave的中繼日志slave開啟SQL進程&#xff0c;從中繼日志中讀取二進制日志并進行重放最終&#xff0c;達到slave與master中數據一致的狀態&#xff0c;我們稱作為主從…

RabbitMQ面試精講 Day 2:RabbitMQ工作模型與消息流轉

【RabbitMQ面試精講 Day 2】RabbitMQ工作模型與消息流轉 開篇 歡迎來到"RabbitMQ面試精講"系列的第2天&#xff0c;今天我們將深入探討RabbitMQ的工作模型與消息流轉機制。這是面試中最常被問到的核心知識點之一&#xff0c;90%的RabbitMQ面試都會涉及消息流轉流程…

基于SpringBoot3集成Kafka集群

1. build.gradle依賴引入 implementation org.springframework.kafka:spring-kafka:3.2.02. 新增kafka-log.yml文件 在resource/config下面新增kafka-log.yml&#xff0c;配置主題與消費者組 # Kafka消費者群組 kafka:consumer:group:log-data: log-data-grouptopic:log-data: …

wpf Canvas 導出圖片

在WPF中將Canvas導出為圖片主要涉及以下關鍵步驟和注意事項: ?核心實現方法?使用RenderTargetBitmap將Canvas渲染為位圖,再通過PngBitmapEncoder保存為PNG文件。需注意臨時移除Canvas的布局變換(LayoutTransform)以避免渲染異常?1。示例代碼片段:CanvasExporter.cs pu…