深度學習-多分類

在這里插入圖片描述
?開頭摘要??:
本文將深入探討如何使用PyTorch實現基于Softmax回歸的MNIST手寫數字識別系統。從多分類問題的核心概念出發,詳細解析??One-Hot編碼??技術如何將類別標簽向量化,剖析??交叉熵損失函數??的數學原理及其在訓練中的優化機制。通過完整代碼實戰,展示數據加載、網絡構建、模型訓練與評估的全流程,并重點介紹??TensorBoard可視化??工具的應用技巧。本教程涵蓋模型保存加載、預測結果可視化等實用功能,為初學者提供從理論到實踐的全面指導,幫助快速掌握分類任務的核心技術棧。

文章目錄

    • 多分類
    • one_hot編碼
      • 編碼原理
    • 交叉熵損失函數
      • 示例
    • 實戰案例基于mnnist的手寫識別
      • TensorBoard的使用
      • 部分代碼解釋
    • 總體實現
    • 核心收獲
      • 代碼

多分類

  • 輸出是每個類別的概率,要求有多少個分類最終的輸出層就有多少個神經元
  • 各分類輸出概率的總和是1(使用softmax歸一化)
    在這里插入圖片描述

one_hot編碼

One-Hot 編碼是機器學習中處理??分類數據??的核心技術,它將離散類別轉換為向量表示,使其能被神經網絡處理。

一句話:在一個樣本中:n個分類,結果是第k個,則yone-hot=[0,?,1?第k位,?,0]y_{\text{one-hot}} = [0, \cdots, \underbrace{1}_{\text{第k位}}, \cdots, 0]yone-hot?=[0,?,k1??,?,0]

編碼原理

對于一個包含 C 個類別的特征:

  • 創建長度為 C 的零向量
  • 對第 k 類數據,將其向量中第 k 個位置設為 1
  • 其余位置保持為 0

yone-hot=[0,?,1?第k位,?,0]y_{\text{one-hot}} = [0, \cdots, \underbrace{1}_{\text{第k位}}, \cdots, 0]yone-hot?=[0,?,k1??,?,0]

假設動物分類的類別為:[“狗”, “貓”, “鳥”]
類別 One-Hot 編碼
狗 [1, 0, 0]
貓 [0, 1, 0]
鳥 [0, 0, 1]

交叉熵損失函數

一句話:在H(y,pi)=?∑xylog?piH(y,p_i)=-\sum_{x}y\log p_iH(y,pi?)=?x?ylogpi?中,只有一條1*log(pi)為最終交叉熵損失函數值,其它都是0*log(pi)=0

交叉熵損失函數與邏輯回歸中的損失函數效果相同,都是為如何調整參數指明方向,即通過求取梯度,調整參數使損失函數的值逼近0,只是交叉熵損失函數用在多分類中
L(y^,y)=?ylog?(y^)?(1?y)log?(1?y^)L(\hat{y}, y) = - y \log(\hat{y}) - (1 - y) \log(1 - \hat{y}) L(y^?,y)=?ylog(y^?)?(1?y)log(1?y^?)

交叉熵損失函數
H(y,pi)=?∑xylog?piH(y,p_i)=-\sum_{x}y\log p_iH(y,pi?)=?x?ylogpi?

yi:是真實標簽(真實分布),通常采用one?hot編碼(真實類別為1,其余為0)y_i:是真實標簽(真實分布),通常采用one-hot編碼(真實類別為1,其余為0)yi?:是真實標簽(真實分布),通常采用one?hot編碼(真實類別為1,其余為0
(乘的時候按類,分開乘了,0*log or 1*log ,單個樣本,最終結果取決于那個唯一的1*log的值)

pi:是預測概率(模型輸出的概率分布)p_i:是預測概率(模型輸出的概率分布)pi?:是預測概率(模型輸出的概率分布)

log?(pi):是預測概率的對數值\log(p_i):是預測概率的對數值log(pi?):是預測概率的對數值

整體計算:是真實標簽yi與預測概率對數log?(pi)的乘積再求和取負整體計算:是真實標簽y_i與預測概率對數\log(p_i)的乘積再求和取負整體計算:是真實標簽yi?與預測概率對數log(pi?)的乘積再求和取負

示例

在這里插入圖片描述

  • L=0.357 表示當前預測不夠準確(理想值應接近0)
  • Log的底數無所謂,經過訓練,任何底數的結果都是相同的

log(x)
在這里插入圖片描述

實戰案例基于mnnist的手寫識別

TensorBoard的使用

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter(comment='test_tensorboard')  # 用于記錄要可視化的數據
#writer = SummaryWriter(存放的地址)

如果不指定絕對路徑,PyTorch 默認創建runs在當前文件夾下
在這里插入圖片描述

在你安裝TensorBoard的虛擬py環境中運行以下代碼即可

tensorboard --logdir="這個event文件所在目錄的絕對地址"

在這里插入圖片描述
在這里插入圖片描述

部分代碼解釋

import torch
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torchvision.datasets import MNIST
import matplotlib.pyplot as plt
import os
import numpy as np
from datetime import datetime
import os
log_dir = "runs"
os.makedirs(log_dir, exist_ok=True)

創建一個名為runs的文件夾

import matplotlib.pyplot as plt
writer = SummaryWriter(log_dir=log_subdir)

記錄數據便于后續畫圖

3.定義網絡基本框架

class SoftmaxRegression(torch.nn.Module):#括號中的 torch.nn.Module 表示你的 SoftmaxRegression 類 繼承自 PyTorch 的 Module 基類def __init__(self):  #self 指代 當前類的實例對象(即正在創建的具體模型)super().__init__()# 單層網絡結構:784輸入 -> 10輸出self.linear = torch.nn.Linear(28 * 28, 10)#定義了這個網絡的基本結構,有784個輸入特征,10個輸出def forward(self, x):# 應用log_softmax到線性層輸出return torch.nn.functional.log_softmax(self.linear(x), dim=1)

log_softmax(self.linear(x), dim=1)相當于兩步
softmax_output = exp(z_i) / sum(exp(z_j)) # 轉換為概率分布
log_softmax = log(softmax_output) # 取自然對數

torch.nn.functional.log_softmax(self.linear(x), dim=1),dim=1
im=0:跨樣本操作(通常不需要)(每個樣本的第n類概率加起來為1)
dim=1:跨類別操作(分類任務的標準做法)(每個樣本的n個類的各個概率加起來為1)

在這個模型中沒有隱藏層,這是一個單層神經網絡(也稱為 Softmax 回歸或多元邏輯回歸),是直接從784個輸出特征到,輸出層的十個輸出神經元

線性變換-神經元a0
線性變換-神經元a1
1......1
線性變換-神經元a9
輸入的784個特征x
激活函數log_softmax(z)

4.加載訓練數據

def get_data_loader(is_train, batch_size=128):transform = transforms.Compose([transforms.ToTensor(),#張量化圖像transforms.Normalize((0.1307,), (0.3081,))  # MNIST的均值和標準差])dataset = MNIST(root='./data', train=is_train, download=True, transform=transform)return DataLoader(dataset, batch_size=batch_size, shuffle=is_train, pin_memory=True)

dataset = MNIST( # 創建MNIST數據集對象
root=‘./data’, # 指定數據存儲路徑為當前目錄下的data文件夾
train=is_train, # 確定加載訓練集(True)還是測試集(False)
download=True, # 如果本地沒有數據集則自動下載
transform=transform # 應用指定的數據預處理轉換
)
return DataLoader( # 返回數據加載器
dataset, # 使用的數據集對象
batch_size=batch_size, # 指定每次加載的數據批大小
shuffle=is_train, # 決定是否打亂數據順序
pin_memory=True # 內存優化選項(GPU訓練時使用)
)

5.返回正確率

#test_data是測試數據
#net 是一個 ??已經實例化并訓練好的神經網絡對象??"""評估模型準確率"""
def evaluate(test_data, net): net.eval()correct = 0total = 0with torch.no_grad():for images, labels in test_data:images, labels = images.to(device), labels.to(device)outputs = net(images.view(-1, 28 * 28))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()return correct / total

6.保存訓練結果

def save_model(net, filename='softmax_model.pth'):#當前目錄下"""保存模型"""torch.save(net.state_dict(), filename)#提取模型的所有可學習參數print(f"模型已保存至 {filename}")n

#net 是一個 ??已經實例化并訓練好的神經網絡對象??

7.加載之前的訓練結果

def load_model(net, filename='softmax_model.pth'):"""加載模型"""if os.path.exists(filename):net.load_state_dict(torch.load(filename, map_location=device))#map_location=device是為了指定模型加載到哪個設備上(CPU或GPU)print(f"模型已從 {filename} 加載")else:print(f"警告: 未找到模型文件 {filename}")return net

device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)

8.可視化

def visualize_predictions(model, test_loader, num_images=12):"""可視化模型預測結果"""model.eval()images, labels = next(iter(test_loader))images, labels = images.to(device), labels.to(device)with torch.no_grad():outputs = model(images.view(-1, 28 * 28))_, predictions = torch.max(outputs, 1)plt.figure(figsize=(12, 8))for i in range(num_images):plt.subplot(3, 4, i + 1)img = images[i].cpu().numpy().squeeze()plt.imshow(img, cmap='gray')plt.title(f"預測: {predictions[i].item()} (真實: {labels[i].item()})")plt.axis('off')plt.tight_layout()plt.savefig('softmax_predictions.png', dpi=150)plt.show()# 將圖像添加到TensorBoard(使用PIL圖像替代)from PIL import Imagefrom torchvision.utils import save_image# 創建臨時圖像文件temp_img_path = "temp_grid.png"save_image(images[:num_images], temp_img_path, nrow=4)# 讀取并添加到TensorBoardimg = Image.open(temp_img_path)img_array = np.array(img)writer.add_image('predictions', img_array, dataformats='HWC')

總體實現

import torch
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torchvision.datasets import MNIST
import matplotlib.pyplot as plt
import os
import numpy as np
from datetime import datetime# 解決Matplotlib中文顯示問題
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑體顯示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常顯示負號# 檢查CUDA設備是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用設備: {device}")# 確保日志目錄存在
log_dir = "runs"
os.makedirs(log_dir, exist_ok=True)# 創建TensorBoard記錄器
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
log_subdir = os.path.join(log_dir, f"softmax_mnist_{timestamp}")
writer = SummaryWriter(log_dir=log_subdir) #用來畫圖的數據就放在log_dir=log_subdir里class SoftmaxRegression(torch.nn.Module):#括號中的 torch.nn.Module 表示你的 SoftmaxRegression 類 繼承自 PyTorch 的 Module 基類"""簡單的Softmax回歸模型"""def __init__(self):  #self 指代 當前類的實例對象(即正在創建的具體模型)super().__init__()# 單層網絡結構:784輸入 -> 10輸出self.linear = torch.nn.Linear(28 * 28, 10)def forward(self, x):# 應用log_softmax到線性層輸出return torch.nn.functional.log_softmax(self.linear(x), dim=1)def get_data_loader(is_train, batch_size=128):"""獲取數據加載器"""transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))  # MNIST的均值和標準差])dataset = MNIST(root='./data', train=is_train, download=True, transform=transform)return DataLoader(dataset, batch_size=batch_size, shuffle=is_train, pin_memory=True)def evaluate(test_data, net):"""評估模型準確率"""net.eval()correct = 0total = 0with torch.no_grad():for images, labels in test_data:images, labels = images.to(device), labels.to(device)outputs = net(images.view(-1, 28 * 28))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()return correct / totaldef save_model(net, filename='softmax_model.pth'):"""保存模型"""torch.save(net.state_dict(), filename)print(f"模型已保存至 {filename}")def load_model(net, filename='softmax_model.pth'):"""加載模型"""if os.path.exists(filename):net.load_state_dict(torch.load(filename, map_location=device))print(f"模型已從 {filename} 加載")else:print(f"警告: 未找到模型文件 {filename}")return netdef visualize_predictions(model, test_loader, num_images=12):"""可視化模型預測結果"""model.eval()images, labels = next(iter(test_loader))images, labels = images.to(device), labels.to(device)with torch.no_grad():outputs = model(images.view(-1, 28 * 28))_, predictions = torch.max(outputs, 1)plt.figure(figsize=(12, 8))for i in range(num_images):plt.subplot(3, 4, i + 1)img = images[i].cpu().numpy().squeeze()plt.imshow(img, cmap='gray')plt.title(f"預測: {predictions[i].item()} (真實: {labels[i].item()})")plt.axis('off')plt.tight_layout()plt.savefig('softmax_predictions.png', dpi=150)plt.show()# 將圖像添加到TensorBoard(使用PIL圖像替代)from PIL import Imagefrom torchvision.utils import save_image# 創建臨時圖像文件temp_img_path = "temp_grid.png"save_image(images[:num_images], temp_img_path, nrow=4)# 讀取并添加到TensorBoardimg = Image.open(temp_img_path)img_array = np.array(img)writer.add_image('predictions', img_array, dataformats='HWC')def main():# 獲取數據加載器train_loader = get_data_loader(is_train=True, batch_size=128)test_loader = get_data_loader(is_train=False, batch_size=512)# 創建模型model = SoftmaxRegression().to(device)print(f"模型參數量: {sum(p.numel() for p in model.parameters()):,}")# 嘗試加載現有模型model = load_model(model)# 評估初始準確率init_acc = evaluate(test_loader, model)print(f"初始準確率: {init_acc:.4f}")writer.add_scalar('Accuracy/test', init_acc, 0)# 使用Adam優化器optimizer = torch.optim.Adam(model.parameters(), lr=0.01)# 訓練循環total_step = 0for epoch in range(10):model.train()total_loss = 0correct = 0total = 0for i, (images, labels) in enumerate(train_loader):images, labels = images.to(device), labels.to(device)# 前向傳播outputs = model(images.view(-1, 28 * 28))loss = torch.nn.functional.nll_loss(outputs, labels)# 反向傳播和優化optimizer.zero_grad()loss.backward()optimizer.step()# 統計信息total_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()# 每100個batch記錄一次if (i + 1) % 100 == 0:train_acc = correct / totalavg_loss = total_loss / (i + 1)print(f"Epoch [{epoch + 1}/10], Step [{i + 1}/{len(train_loader)}], "f"Loss: {avg_loss:.4f}, Accuracy: {train_acc:.4f}")# 記錄到TensorBoardwriter.add_scalar('Loss/train', avg_loss, total_step)writer.add_scalar('Accuracy/train', train_acc, total_step)total_step += 1# 每個epoch結束后評估測試集test_acc = evaluate(test_loader, model)print(f"Epoch [{epoch + 1}/10], 測試準確率: {test_acc:.4f}")writer.add_scalar('Accuracy/test', test_acc, epoch)# 訓練后保存模型save_model(model)# 最終評估final_acc = evaluate(test_loader, model)print(f"最終測試準確率: {final_acc:.4f}")# 可視化預測結果visualize_predictions(model, test_loader)# 在TensorBoard中添加模型圖dummy_input = torch.randn(1, 784).to(device)writer.add_graph(model, dummy_input)# 關閉TensorBoard寫入器writer.close()print(f"TensorBoard日志保存在: {log_subdir}")print("使用命令查看TensorBoard: tensorboard --logdir=runs")if __name__ == '__main__':main()

核心收獲

1. 多分類問題本質
○ 輸出層神經元數=分類數
○ 使用Softmax確保概率歸一化:σ(z)j=ezj∑k=1Kezk\sigma(z)_j = \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}}σ(z)j?=k=1K?ezk?ezj??
2. 數據編碼技術
○ One-Hot編碼:y貓=[0,1,0]y_{\text{貓}} = [0,1,0]y?=[0,1,0]
○ 數據標準化:Normalize((0.1307,),(0.3081,))Normalize((0.1307,), (0.3081,))Normalize((0.1307,),(0.3081,))
3. 損失函數優化
○ 交叉熵損失:L=?∑yilog?(pi)L = -\sum y_i \log(p_i)L=?yi?log(pi?)
○ Adam優化器自適應調整學習率

代碼

數據加載
網絡構建
訓練循環
評估驗證
結果可視化
模型部署

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

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

相關文章

JVM 類加載過程

一、加載(Loading)目標:把字節碼文件(.class)“讀入 JVM”,生成類的 “半成品”(Class 對象)。Bootstrap ClassLoader(啟動類加載器):負責加載 JV…

通俗范疇論13 雞與蛋的故事番外篇

通俗范疇論13 雞與蛋的故事番外篇 在上一篇中,我們得到了雞與蛋的Set局部小范疇如下: 雞與蛋 SetSetSet 局部小范疇 如上圖所示,每個雞來自于一個蛋,每個蛋來自于一只雞,如此循環,以至于無窮… 是的,假設雞與蛋兩個對象代表的集合,都是無窮集合,這個系統就沒有問題…

記錄跟隨recyclerview滑動的指示器

老早之前做的一個功能&#xff0c;橫向recyclerview滑動時&#xff0c;底部做跟隨滑動指示器。今天代碼不用了&#xff0c;記錄下代碼。<LinearLayoutandroid:layout_width"match_parent"android:layout_height"wrap_content"android:layout_marginTop&…

快速過一遍Python基礎語法

前言 本文章是深度學習的前導課&#xff0c;對有編程基礎的小伙伴更加的友好&#xff08;C、C&#xff09;&#xff0c;如果完全沒有學過任何一門編程語言也沒有關系&#xff0c;本文章不會涉及到晦澀難懂的原理&#xff0c;只是簡單的帶大家過一遍Python的基礎語法。 下面的操…

[爬蟲實戰] 多進程/多線程/協程-異步爬取豆瓣Top250

相關爬蟲知識點&#xff1a;[爬蟲知識] 深入理解多進程/多線程/協程的異步邏輯 相關爬蟲專欄&#xff1a;JS逆向爬蟲實戰 爬蟲知識點合集 爬蟲實戰案例 逆向知識點合集 前言&#xff1a; 在之前文章中&#xff0c;我們深入探討了多進程、多線程和協程這三大異步技術的工作…

Git系列--1.初始Git

一、背景 目錄 一、背景 二、認識 三、如何在Linux上安裝Git 3.1檢測git是否存在和版本 3.2安裝和卸載git 3.2.1Centos 3.2.2Ubuntu 四、基本操作 4.1創建本地倉庫 4.2必須的配置項 4.3宏觀認識基本分區 我們會根據需求不斷更改我們的文件內容&#xff0c;但有時我們會…

QWidget的屬性

QWidget的屬性 windowOpacityAPI說明windowOpacity()獲取不透明數值&#xff0c;返回float&#xff0c;取值為0.0到1.0&#xff0c;其中0.0為全透明&#xff0c;1.0為完全不透明setWindowOpacity()設置控件的不透明數值注意點&#xff1a;窗口不透明度的變化并非精確的&#xf…

【PTA數據結構 | C語言版】后綴表達式求值

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 請編寫程序&#xff0c;求給定的后綴表達式的值。 輸入格式&#xff1a; 輸入在一行中給出一個非空后綴表達式&#xff0c;其中操作數為 int 型整數&#xff0c;操作符包括加、減、乘、除、取模。各…

裝配式建筑4.0:當房子像汽車一樣被“智造”

傳統建筑方式&#xff0c;如同手工打造藝術品一般&#xff0c;大部分工作依賴現場施工&#xff0c;工人在建筑工地進行混凝土澆筑、磚塊堆砌、鋼筋綁扎等繁雜工作。這種方式受天氣、工人技術水平等因素影響極大&#xff0c;不僅施工周期漫長&#xff0c;質量也參差不齊。據統計…

Go語言生態成熟度分析:為何Go還無法像Java那樣實現注解式框架?

近年來&#xff0c;Go語言因其性能高效、部署簡單、并發模型優秀等特性&#xff0c;成為云原生與微服務架構中的熱門語言。然而&#xff0c;在實際的企業級項目開發中&#xff0c;開發者普遍會發現一個現象&#xff1a;Go的開發效率&#xff0c;尤其在快速構建中大型業務系統時…

oc分類和swift擴展有哪些區別

目錄1. 語言環境2. 主要目的3. 核心能力對比4. 關鍵差異詳解4.1. 屬性支持4.2. Swift 擴展4.3. 初始化器4.4. 方法沖突與覆蓋4.5. 關聯類型與泛型5. 設計哲學6. 總結表在 Objective-C 和 Swift 中&#xff0c;分類&#xff08;Category&#xff09;和擴展&#xff08;Extension…

go.work

一般學習一個小東西時&#xff0c;無非兩點&#xff0c;1、怎么用&#xff1f; 2、為啥用&#xff1f;在寫一個小的項目demo時&#xff0c;忽然看到一個奇怪的東西“go.work”&#xff1f;這是啥&#xff1f;好奇&#x1f62f;&#xff0c;想知道。我是這么問AI的&#xff1a;g…

Kimi K2萬億參數開源模型原理介紹

Kimi K2 技術全解&#xff1a;1T MoE 大模型如何煉成開放智能體 文章目錄Kimi K2 技術全解&#xff1a;1T MoE 大模型如何煉成開放智能體1. 模型架構與特點&#xff1a;1 T MoE 的「大」與「省」2. 主要創新點&#xff1a;MuonClip、Agentic RL 與工具調用2.1 MuonClip 優化器&…

【CMake】CMake構建項目入門

一、CMake介紹 CMake 是一個跨平臺的自動化構建工具&#xff0c;用于管理軟件項目的編譯過程。它通過簡單的配置文件&#xff08;CMakeLists.txt&#xff09;生成特定平臺的構建文件&#xff08;如 Makefile、Visual Studio 項目&#xff09;&#xff0c;讓開發者可以專注于代…

貪心算法題解——劃分字母區間【LeetCode】

763. 劃分字母區間 本題目&#xff0c;“同一字母最多出現在一個片段中”&#xff0c;因為這句話&#xff0c;所以本質上 這道題目屬于合并區間 一、算法邏輯&#xff08;逐步思路&#xff09; ? 目標&#xff1a; 將字符串 s 劃分成盡可能多的片段&#xff0c;要求&#xf…

Python----目標檢測(使用YOLOV8網絡訓練人臉)

一、Ultralytics安裝 網址&#xff1a;主頁 -Ultralytics YOLO 文檔 Ultralytics提供了各種安裝方法&#xff0c;包括pip、conda和Docker。通過 ultralytics pip包安裝最新穩定版本的YOLOv8&#xff0c;或克隆Ultralytics GitHub 存儲庫以獲取最新版本。可以使用Docker在隔離的…

Filament引擎(三) ——引擎渲染流程

通過Filament引擎(二) ——引擎的調用及接口層核心對象的介紹我們知道&#xff0c;要在項目中使用filament&#xff0c;首先我們需要構建出filament的Engine的對象&#xff0c;然后通過filament::Engine對象實例&#xff0c;來構建其他對象&#xff0c;組裝渲染場景&#xff0c…

Oracle存儲過程導出數據到Excel:全面實現方案詳解

技術背景與需求分析 數據導出是企業級應用的核心功能,Oracle存儲過程因其高性能執行(減少網絡傳輸)、代碼復用性(封裝業務邏輯)和事務安全性(ACID保障)成為理想載體。Excel作為使用率$ \geq 95% $的辦公工具,其兼容性需求尤為突出。典型場景包括: 財務報表自動生成物…

解決el-table右下角被擋住部分

一部分展示不全&#xff0c;被遮擋&#xff0c;因為 最右邊加了fixed"right"<el-table-column fixed"right" label"操作" width"120">解決&#xff1a;1、去除fixed"right"或2、設置樣式單頁面<style lang"sc…

Waiting for server response 和 Content Download

在瀏覽器網絡調試&#xff08;如 Chrome DevTools 的 Network 面板&#xff09;中&#xff0c;Timing 選項卡下的 Waiting for server response 和 Content Download 是兩個關鍵性能指標&#xff0c;它們分別代表了 HTTP 請求生命周期的不同階段。以下是詳細解釋和優化方案&…