深度學習——基于卷積神經網絡實現食物圖像分類(數據增強)

文章目錄
引言
一、項目概述
二、環境準備
三、數據預處理
3.1 數據增強與標準化
3.2 數據集準備
四、自定義數據集類
五、構建CNN模型
六、訓練與評估
6.1 訓練函數
6.2 評估函數
6.3 訓練流程
七、關鍵技術與優化
八、常見問題與解決
九、完整代碼
十、總結
引言
本文將詳細介紹如何使用PyTorch框架構建一個食物圖像分類系統,涵蓋數據預處理、模型構建、訓練和評估全過程。我們將使用自定義的食物數據集,構建一個卷積神經網絡(CNN)模型,并實現完整的訓練流程。

一、項目概述
食物圖像分類是計算機視覺中的一個常見應用場景。在本項目中,我們將構建一個能夠識別20種不同食物的分類系統。整個流程包括:

數據準備與預處理
構建自定義數據集類
設計CNN模型架構
訓練模型并評估性能
優化與結果分析
二、環境準備
首先確保已安裝必要的Python庫:

import torch
import torchvision.models as models
from torch import nn
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import numpy as np
import os



三、數據預處理
3.1 數據增強與標準化
我們為訓練集和驗證集分別定義不同的轉換策略:

data_transforms = {'train': transforms.Compose([transforms.Resize([300,300]),transforms.RandomRotation(45),transforms.CenterCrop(256),transforms.RandomHorizontalFlip(p=0.5),transforms.RandomVerticalFlip(p=0.5),transforms.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.1, hue=0.1),transforms.RandomGrayscale(p=0.1),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),'valid': transforms.Compose([transforms.Resize([256,256]),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),
}



關鍵點解析:

訓練集增強:

隨機旋轉(-45°到45°)
隨機水平和垂直翻轉
色彩抖動(亮度、對比度、飽和度和色調)
隨機灰度化(概率10%)
標準化處理:

使用ImageNet的均值和標準差進行歸一化
有助于模型更快收斂
3.2 數據集準備
我們編寫了一個函數來生成訓練和測試的標注文件:

def train_test_file(root, dir):file_txt = open(dir+'.txt','w')path = os.path.join(root,dir)for roots, directories, files in os.walk(path):if len(directories) != 0:dirs = directorieselse:now_dir = roots.split('\\')for file in files:path_1 = os.path.join(roots,file)file_txt.write(path_1+' '+str(dirs.index(now_dir[-1]))+'\n')file_txt.close()


該函數會遍歷指定目錄,生成包含圖像路徑和對應標簽的文本文件。

四、自定義數據集類
我們繼承PyTorch的Dataset類創建自定義數據集:

class food_dataset(Dataset):def __init__(self, file_path, transform=None):self.file_path = file_pathself.imgs = []self.labels = []self.transform = transformwith open(self.file_path) as f:samples = [x.strip().split(' ') for x in f.readlines()]for img_path, label in samples:self.imgs.append(img_path)self.labels.append(label)def __len__(self):return len(self.imgs)def __getitem__(self, idx):image = Image.open(self.imgs[idx])if self.transform:image = self.transform(image)label = self.labels[idx]label = torch.from_numpy(np.array(label, dtype=np.int64))return image, label



關鍵方法:

__init__: 初始化數據集,讀取標注文件
__len__: 返回數據集大小
__getitem__: 根據索引返回圖像和標簽,應用預處理
五、構建CNN模型
我們設計了一個三層的CNN網絡:

class CNN(nn.Module):def __init__(self):super(CNN,self).__init__()self.conv1 = nn.Sequential(nn.Conv2d(3, 16, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(kernel_size=2))self.conv2 = nn.Sequential(nn.Conv2d(16,32,5,1,2),nn.ReLU(),nn.MaxPool2d(kernel_size=2))self.conv3 = nn.Sequential(nn.Conv2d(32, 64, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(kernel_size=2))self.out = nn.Linear(64*32*32, 20)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = x.view(x.size(0), -1)output = self.out(x)return output


網絡結構分析:

卷積層1:

輸入通道:3 (RGB)
輸出通道:16
卷積核:5×5
輸出尺寸:(16, 128, 128)
卷積層2:

輸入通道:16
輸出通道:32
輸出尺寸:(32, 64, 64)
卷積層3:

輸入通道:32
輸出通道:64
輸出尺寸:(64, 32, 32)
全連接層:

輸入:64×32×32 = 65536
輸出:20 (對應20類食物)
六、訓練與評估
6.1 訓練函數
def train(dataloader, model, loss_fn, optimizer):
model.train()
batch_size_num = 1
for X, y in dataloader:
X, y = X.to(device), y.to(device)
pred = model(X)
loss = loss_fn(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()

loss_value = loss.item()
if batch_size_num % 1 == 0:
print(f"loss: {loss_value:>7f} [number:{batch_size_num}]")
batch_size_num += 1


6.2 評估函數

def Test(dataloader, model, loss_fn):size = len(dataloader.dataset)num_batches = len(dataloader)model.eval()test_loss, correct = 0, 0with torch.no_grad():for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)test_loss += loss_fn(pred, y).item()correct += (pred.argmax(1) == y).type(torch.float).sum().item()test_loss /= num_batchescorrect /= sizeprint(f"Test result: \n Accuracy:{(100*correct)}%, Avg loss:{test_loss}")



6.3 訓練流程

# 初始化模型
model = CNN().to(device)# 定義損失函數和優化器
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 訓練10個epoch
epochs = 10
for t in range(epochs):print(f"epoch {t+1}\n---------------")train(train_dataloader, model, loss_fn, optimizer)# 最終評估
Test(test_dataloader, model, loss_fn)



七、關鍵技術與優化
數據增強:通過多種變換增加數據多樣性,防止過擬合
批標準化:使用ImageNet統計量進行標準化,加速收斂
學習率選擇:使用Adam優化器,初始學習率0.001
設備選擇:自動檢測并使用GPU加速訓練
八、常見問題與解決
內存不足:

減小batch size
使用更小的圖像尺寸
過擬合:

增加數據增強
添加Dropout層
使用L2正則化
訓練不收斂:

檢查學習率
檢查數據預處理
檢查模型結構
九、完整代碼
import torch
import torchvision.models as models
from torch import nn
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import numpy as np
import os

data_transforms = { #字典
'train':
transforms.Compose([ ? ? ? ? ? ?#對圖片預處理的組合
transforms.Resize([300,300]), ? #對數據進行改變大小
transforms.RandomRotation(45), ?#隨機旋轉,-45到45之間隨機選
transforms.CenterCrop(256), ? ? #從中心開始裁剪[256,256]
transforms.RandomHorizontalFlip(p=0.5),#隨機水平翻轉,p是指選擇一個概率翻轉,p=0.5表示百分之50
transforms.RandomVerticalFlip(p=0.5),#隨機垂直翻轉
transforms.ColorJitter(brightness=0.2,contrast=0.1,saturation=0.1,hue=0.1),
transforms.RandomGrayscale(p=0.1),#概率轉換成灰度率,3通道就是R=G=B
transforms.ToTensor(),#數據轉換為tensor
transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])#標準化,均值,標準差
]),
'valid':
transforms.Compose([
transforms.Resize([256,256]),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ?# 標準化,均值,標準差
]),
}
#做了數據增強不代表訓練效果一定會好,只能說大概率會變好
def train_test_file(root,dir):
file_txt = open(dir+'.txt','w')
path = os.path.join(root,dir)
for roots,directories,files in os.walk(path):
if len(directories) !=0:
dirs = directories
else:
now_dir = roots.split('\\')
for file in files:
path_1 = os.path.join(roots,file)
print(path_1)
file_txt.write(path_1+' '+str(dirs.index(now_dir[-1]))+'\n')

? ? file_txt.close()

root = r'.\食物分類\food_dataset'
train_dir = 'train'
test_dir = 'test'
train_test_file(root,train_dir)
train_test_file(root,test_dir)

#Dataset是用來處理數據的
class food_dataset(Dataset): ? ? ? ?# food_dataset是自己創建的類名稱,可以改為你需要的名稱
def __init__(self,file_path,transform=None): ? ?#類的初始化,解析數據文件txt
self.file_path = file_path
self.imgs = []
self.labels = []
self.transform = transform
with open(self.file_path) as f: #是把train.txt文件中的圖片路徑保存在self.imgs
samples = [x.strip().split(' ') for x in f.readlines()]
for img_path,label in samples:
self.imgs.append(img_path) ?#圖像的路徑
self.labels.append(label) ? #標簽,還不是tensor

# 初始化:把圖片目錄加到self
def __len__(self): ?#類實例化對象后,可以使用len函數測量對象的個數
return ?len(self.imgs)

? ? #training_data[1]
def __getitem__(self, idx): ? ?#關鍵,可通過索引的形式獲取每一個圖片的數據及標簽
image = Image.open(self.imgs[idx]) ?#讀取到圖片數據,還不是tensor,BGR
if self.transform: ? ? ? ? ? ? ? ? ?#將PIL圖像數據轉換為tensor
image = self.transform(image) ? #圖像處理為256*256,轉換為tensor

? ? ? ? label = self.labels[idx] ? ?#label還不是tensor
label = torch.from_numpy(np.array(label,dtype=np.int64)) ? ?#label也轉換為tensor
return image,label
#training_data包含了本次需要訓練的全部數據集
training_data = food_dataset(file_path='train.txt', transform=data_transforms['train'])
test_data = food_dataset(file_path='test.txt', transform=data_transforms['valid'])

#training_data需要具備索引的功能,還要確保數據是tensor
train_dataloader = DataLoader(training_data,batch_size=16,shuffle=True)
test_dataloader = DataLoader(test_data,batch_size=16,shuffle=True)


'''判斷當前設備是否支持GPU,其中mps是蘋果m系列芯片的GPU'''
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device") ? #字符串的格式化,CUDA驅動軟件的功能:pytorch能夠去執行cuda的命令
# 神經網絡的模型也需要傳入到GPU,1個batch_size的數據集也需要傳入到GPU,才可以進行訓練


''' 定義神經網絡 ?類的繼承這種方式'''
class CNN(nn.Module): #通過調用類的形式來使用神經網絡,神經網絡的模型,nn.mdoule
def __init__(self): #輸入大小:(3,256,256)
super(CNN,self).__init__() ?#初始化父類
self.conv1 = nn.Sequential( #將多個層組合成一起,創建了一個容器,將多個網絡組合在一起
nn.Conv2d( ? ? ? ? ? ? ?# 2d一般用于圖像,3d用于視頻數據(多一個時間維度),1d一般用于結構化的序列數據
in_channels=3, ? ? ?# 圖像通道個數,1表示灰度圖(確定了卷積核 組中的個數)
out_channels=16, ? ? # 要得到多少個特征圖,卷積核的個數
kernel_size=5, ? ? ?# 卷積核大小 3×3
stride=1, ? ? ? ? ? # 步長
padding=2, ? ? ? ? ?# 一般希望卷積核處理后的結果大小與處理前的數據大小相同,效果會比較好
), ? ? ? ? ? ? ? ? ? ? ?# 輸出的特征圖為(16,256,256)
nn.ReLU(), ?# Relu層,不會改變特征圖的大小
nn.MaxPool2d(kernel_size=2), ? ?# 進行池化操作(2×2操作),輸出結果為(16,128,128)
)
self.conv2 = nn.Sequential(
nn.Conv2d(16,32,5,1,2), ?#輸出(32,128,128)
nn.ReLU(), ?#Relu層 ?(32,128,128)
nn.MaxPool2d(kernel_size=2), ? ?#池化層,輸出結果為(32,64,64)
)
self.conv3 = nn.Sequential(
nn.Conv2d(32, 64, 5, 1, 2), ?# 輸出(64,64,64)
nn.ReLU(), ?# Relu層 ?(64,64,64)
nn.MaxPool2d(kernel_size=2), ?# 池化層,輸出結果為(64,32,32)
)
self.out = nn.Linear(64*32*32,20) ?# 全連接層得到的結果


def forward(self,x): ? #前向傳播,你得告訴它 數據的流向 是神經網絡層連接起來,函數名稱不能改
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
x = x.view(x.size(0),-1) ? ?# flatten操作,結果為:(batch_size,32 * 64 * 64)
output = self.out(x)
return output
model = CNN().to(device) #把剛剛創建的模型傳入到GPU
print(model)


def train(dataloader,model,loss_fn,optimizer):
model.train() #告訴模型,我要開始訓練,模型中w進行隨機化操作,已經更新w,在訓練過程中,w會被修改的
# pytorch提供2種方式來切換訓練和測試的模式,分別是:model.train() 和 mdoel.eval()
# 一般用法是:在訓練開始之前寫上model.train(),在測試時寫上model.eval()
batch_size_num = 1
for X,y in dataloader: ? ? ? ? ? ? ?#其中batch為每一個數據的編號
X,y = X.to(device),y.to(device) #把訓練數據集和標簽傳入cpu或GPU
pred = model.forward(X) ? ? ? ? # .forward可以被省略,父類種已經對此功能進行了設置
loss = loss_fn(pred,y) ? ? ? ? ?# 通過交叉熵損失函數計算損失值loss
# Backpropagation 進來一個batch的數據,計算一次梯度,更新一次網絡
optimizer.zero_grad() ? ? ? ? ? # 梯度值清零
loss.backward() ? ? ? ? ? ? ? ? # 反向傳播計算得到每個參數的梯度值w
optimizer.step() ? ? ? ? ? ? ? ?# 根據梯度更新網絡w參數

? ? ? ? loss_value = loss.item() ? ? ? ?# 從tensor數據種提取數據出來,tensor獲取損失值
if batch_size_num %1 ==0:
print(f"loss: {loss_value:>7f} [number:{batch_size_num}]")
batch_size_num += 1

def Test(dataloader,model,loss_fn):
size = len(dataloader.dataset)
num_batches = len(dataloader) ?# 打包的數量
model.eval() ? ? ? ?#測試,w就不能再更新
test_loss,correct =0,0
with torch.no_grad(): ? ? ? #一個上下文管理器,關閉梯度計算。當你確認不會調用Tensor.backward()的時候
for X,y in dataloader:
X,y = X.to(device),y.to(device)
pred = model.forward(X)
test_loss += loss_fn(pred,y).item() #test_loss是會自動累加每一個批次的損失值
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
a = (pred.argmax(1) == y) #dim=1表示每一行中的最大值對應的索引號,dim=0表示每一列中的最大值對應的索引號
b = (pred.argmax(1) == y).type(torch.float)
test_loss /= num_batches #能來衡量模型測試的好壞
correct /= size ?#平均的正確率
print(f"Test result: \n Accuracy:{(100*correct)}%, Avg loss:{test_loss}")

loss_fn = nn.CrossEntropyLoss() ?#創建交叉熵損失函數對象,因為手寫字識別一共有十種數字,輸出會有10個結果
#
optimizer = torch.optim.Adam(model.parameters(),lr=0.001) #創建一個優化器,SGD為隨機梯度下降算法
# # params:要訓練的參數,一般我們傳入的都是model.parameters()
# # lr:learning_rate學習率,也就是步長
#
# # loss表示模型訓練后的輸出結果與樣本標簽的差距。如果差距越小,就表示模型訓練越好,越逼近真實的模型
train(train_dataloader,model,loss_fn,optimizer) #訓練1次完整的數據。多輪訓練
Test(test_dataloader,model,loss_fn)

epochs = 10
for t in range(epochs):
print(f"epoch {t+1}\n---------------")
train(train_dataloader,model,loss_fn,optimizer)
print("Done!")
Test(test_dataloader,model,loss_fn)

十、總結
本文詳細介紹了使用PyTorch實現食物分類的全流程。通過合理的網絡設計、數據增強和訓練策略,我們能夠構建一個有效的分類系統。讀者可以根據實際需求調整網絡結構、超參數和數據增強策略,以獲得更好的性能。

完整代碼已在上文展示,建議在實際應用中根據具體數據集調整相關參數。希望本文能幫助讀者掌握PyTorch圖像分類的基本流程和方法。

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

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

相關文章

【開題答辯全過程】以 基于微信小程序的教學輔助系統 為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人,語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

【代碼解讀】Deepseek_vl2中具體代碼調用

【代碼解讀】Deepseek_vl2中具體代碼調用 文章目錄【代碼解讀】Deepseek_vl2中具體代碼調用DeepseekVLV2Processor解讀DeepseekVLV2ForCausalLM - 多模態模型DeepSeek-VL2 Processor的輸入格式單樣本格式多樣本格式DeepSeek-VL2模型的輸出形式總結主要輸出類型:Deep…

Git 9 ,.git/index.lock 文件沖突問題( .git/index.lock‘: File exists. )

目錄 前言 一、問題背景 1.1 問題出現場景 1.2 典型報錯信息 1.3 問題影響 二、問題原因分 2.1 Git 的 index 與鎖機制 2.2 主要作用 2.3 根本原因 三、解決方案 3.1 確認進程 3.2 手動刪除 3.3 再次執行 四、注意事項 4.1 確保運行 4.2 問題排查 4.3 自動化解…

Proteus8 仿真教學全指南:從入門到實戰的電子開發利器

在電子設計、單片機課程設計或創客實踐中,你是否常因實物采購貴、新手怕燒板、調試排錯難而頭疼?Proteus8 作為一款 “全能型” EDA 仿真工具,完美解決這些痛點 —— 它集「原理圖繪制 PCB 設計 虛擬仿真」于一體,支持 51、STM3…

系統科學:結構、功能與層級探析

摘要本文旨在系統性地梳理和辨析系統科學中的核心概念——結構、功能與層級。文章首先追溯系統思想的理論源流,確立其作為一種超越還原論的整體性研究范式。在此基礎上,深度剖析系統結構的內在構成(組分、框架、動態性)、系統層級…

面試官問:你如何看待薪資待遇?

在面試過程中,“你如何看待薪資待遇?”這個問題,是很多面試官都會提出的經典問題之一。雖然表面上看起來是一個簡單的提問,但它實則關乎候選人的職業價值觀、工作態度以及對自己能力的認知。薪資是工作的重要動力之一,…

HarmonyOS 應用開發新范式:深入剖析 Stage 模型與 ArkUI 最佳實踐

好的,請看這篇基于 HarmonyOS (鴻蒙) 最新技術棧的深度技術文章。 HarmonyOS 應用開發新范式:深入剖析 Stage 模型與 ArkUI 最佳實踐 引言 隨著 HarmonyOS 4、5 的持續演進和未來 6 的規劃,其應用開發框架經歷了革命性的重構。對于技術開發者…

【Python數據可視化:Matplotlib高級技巧】

Python數據可視化:Matplotlib高級技巧引言在數據科學和分析領域,數據可視化是理解和傳達信息的關鍵工具。Python中最流行的可視化庫之一就是Matplotlib。雖然初學者可以快速上手Matplotlib的基礎功能,但掌握其高級技巧才能真正發揮這個強大庫…

LazyLLM教程 | 第7講:檢索升級實踐:親手打造“更聰明”的文檔理解系統!

本節,我們將首先介紹如何評價 RAG 的檢索組件,幫助您理解如何衡量 RAG 系統的檢索能力。隨后,我們會深入探討幾種提升 RAG 系統檢索組件效果的策略實現以及對應的效果對比:1.基于 LazyLLM 實現查詢重寫策略。2.介紹 LazyLLM 中的節…

rust語言 (1.88) egui (0.32.1) 學習筆記(逐行注釋)(二十四)窗口顏色、透明度、居中顯示

一、窗口顏色和透明度 &#xff08;一&#xff09;效果預覽&#xff08;二&#xff09;透明窗體主要代碼 use eframe::egui; use egui::Color32;fn main() -> eframe::Result<()> {let options eframe::NativeOptions {viewport: egui::ViewportBuilder::default() …

基于無人機的風電葉片全自動智能巡檢:高精度停角估計與細節優先曝光調控技術

【導讀】 本文致力于解決一個非常實際的工業問題&#xff1a;如何利用無人機&#xff08;UAV&#xff09;全自動、高效、可靠地檢查風力渦輪機葉片。葉片是風力發電機組中最昂貴且易損的部件之一&#xff0c;定期檢查至關重要。然而&#xff0c;當前的技術在自動化過程中面臨幾…

騰訊云上有性能比較強的英偉達GPU

騰訊云上有性能比較強的英偉達GPU A100&#xff0c;雖然落后3~4代&#xff0c;但是估計是最強的英偉達GPU了。

AI任務相關解決方案13-AI智能體架構方案(意圖識別+多任務規劃+MCP+RAG)與關鍵技術深度解析研究報告,以及實現代碼

文章目錄 1. 總體技術方案 2. 生成式大模型(LLM):Data Agent的大腦 3. 意圖識別:準確理解用戶意圖 3.1 基于BERT的微調方法 3.2 基于大語言模型(LLM)的零樣本/少樣本方法 4. 多任務規劃:提升架構的靈活性 4.1 任務分解與規劃 4.2 多智能體協作規劃 4.3 基于強化學習的規劃方…

每日五個pyecharts可視化圖表日歷圖和箱線圖:從入門到精通

&#x1f4ca; 本文特色&#xff1a;從零開始掌握日歷圖和箱線圖可視化技巧&#xff0c;包含多個完整實例、核心配置項解析和實用場景指南&#xff0c;助您快速構建專業數據可視化圖表。pyecharts源碼 目錄什么是日歷圖和箱線圖&#xff1f;&#x1f4c5; 日歷圖&#xff08;Ca…

在本地獲取下載chrome,然后離線搬運到 ECS

場景&#xff1a; 阿里云 ECS 無Y網&#xff0c;無法直接拉取 storage.googleapis.com。因此需先在本地里拿到直鏈并下載&#xff0c;再上傳到 ECS。 注&#xff1a; 這個鏈接是顯示近期的幾個版本 https://googlechromelabs.github.io/chrome-for-testing/ 這個鏈接是所有版…

小土堆目標檢測筆記

文章目錄1 什么是目標檢測2 目標檢測常見的數據集2.1 目標檢測數據集2.2 目標檢測數據集的標注2.3 目標檢測工具介紹3 數據集的標注3.1 VOC數據集標注3.2 加載數據集1 什么是目標檢測 希望計算機在視頻或圖像中定位并識別我們感興趣的目標 定位&#xff1a;找到目標在圖像中的…

Linux內核內存管理系列博客教程學習規劃

&#x1f4da; 系列總體目標 幫助讀者系統理解Linux內核內存管理機制&#xff0c;從基礎概念到核心實現&#xff0c;最終能參與內核內存相關開發。&#x1f4c5; 系列大綱&#xff08;共20篇博文&#xff09; 第一部分&#xff1a;基礎概念篇&#xff08;4篇&#xff09;Linux內…

2025應屆生求職指南:掌握這些新興技能提升競爭力

2025應屆生求職指南&#xff1a;掌握這些新興技能提升競爭力2025-09-01 21:29:35在當前就業市場競爭日益激烈的背景下&#xff0c;2025屆應屆生既面臨挑戰&#xff0c;也迎來新的發展機遇。科技不斷進步與行業變革推動了人才需求結構的變化&#xff0c;掌握一些新興技能已成為提…

DevOps篇之Jenkins實現k8s集群版本發布以及版本管理

設計思路 通過Jenkins 實現 Kubernetes 集群的版本發布和版本管理。并且利用Jenkins實現多集群 K8s 發布。首先需要了解Helm 的應用場景&#xff0c;以及 GitLab 中配置多集群 KUBECONFIG 等問題。現在工具采用 Jenkins&#xff0c;所以需要重點放在 Jenkins 與 K8s 的集成上&a…

AI 智能體架構中的協議設計三部曲:MCP → A2A → AG-UI

AI 智能體應用在企業實際落地越來越多&#xff0c;一個完整的 AI 智能體應用系統通常包含三個主要角色&#xff1a;用戶、AI 智能體和外部工具。AI 智能體架構設計的核心任務之一&#xff0c;就是解決這三個角色之間的溝通問題。 這三個角色的溝通&#xff0c;涉及到&#xff1…