從零實現 LLM(上):原理講透 + 最小可運行 GPT

引言

為什么要學習 LLM

當你和 ChatGPT 對話時,它不僅能回答你的問題,還能續寫故事、記住上下文,甚至調整風格。你可能會想:它是怎么做到的?

答案就是:大語言模型(Large Language Model, LLM。近幾年,從 ChatGPTClaude,從文心一言到通義千問,從 DeepSeekQWen,幾乎所有新一代 AI 產品都離不開它。

但很多學習者會有疑問:

  • LLM 太大了,我是不是玩不起?

    其實不用。我們不會上來就研究 1000 億參數的模型,而是用一個幾十萬參數的 mini-GPT —— 它保留了核心機制(TokenizerAttentionContext Window、采樣策略),只需幾百行代碼,就能在 Google Colab 跑起來。

  • 代碼會不會復雜得看不懂?

    不會。我會逐步拆開,一邊講概念,一邊寫代碼。

  • 跑通這個 demo 有什么意義?

    因為它能讓你真正理解:

    • 為什么 LLM 能續寫文本?
    • 為什么它能“記住”上下文?
    • 為什么會出現“復讀機”?
    • 調整 Temperature / Top-k / Top-p 時,為什么風格完全不同?
flowchart TDA[文本輸入] --> B[分詞器]B --> C[Token 序列(數字ID)]C --> D[Embedding 層]D --> E[Transformer 塊 ×N]E --> F[層歸一化 LayerNorm]F --> G[線性輸出層 Head]G --> H[Softmax 概率分布]H --> I[預測下一個 Token]I --> J[拼接到已有序列]J --> K[生成文本輸出]K -->|直到停止條件| I
本文目標

這篇文章會帶你完成以下目標:

  1. 從零基礎入門:用最直觀的方式解釋 LLM 關鍵概念。
  2. 代碼逐步實現:一步步構建 tokenizerTransformer、訓練循環、生成函數。
  3. 跑通一個 demo LLM:在 Google Colab 上實際訓練并生成文本。
  4. 理解常見問題:為什么 val_loss 很高?為什么結果會復讀?
  5. 學會擴展:如何從 demo 走向更大、更實用的模型。
適合人群
  • 零基礎讀者:你只需要一點點 Python 基礎,就能看懂并跑起來。
  • 有經驗的開發者:你能深入理解代碼實現的細節,明白 LLM 的內部機制。
  • 研究者/愛好者:你能得到一個可擴展的 mini-GPT 框架,作為更大實驗的起點。

一、LLM 基礎概念

在寫代碼之前,我們先把一些“關鍵詞”解釋清楚。你會發現,LLM 的核心思想其實并不復雜。

1.1 Token 與分詞(Tokenization

LLM 并不直接理解“漢字”或“英語單詞”,它看到的只是 一串數字。 這些數字的最小單位就叫 Token,它可能是一個字母、一個漢字、一個子詞,甚至一個完整的單詞。

分詞(Tokenization)就是把文字切分成 token,再轉成數字。打個比方:如果一句話是文章,那么 token 就是“樂高積木”,模型就是學會如何把這些積木拼起來。

  • 字符級分詞H e l l o → [6, 15, 22, 22, 25]
  • BPE 分詞Hello → [23](一個子詞搞定)

兩種常見分詞方式:

  1. 字符級(char-level:直接把每個字符當成一個 token

    優點:實現簡單,語言無關。

    缺點:序列很長,訓練難度大。

  2. BPE(子詞級):從最小的字符開始,逐步合并常見的子串,形成子詞。

    優點:序列更短,訓練更快,效果更好。

    缺點:需要訓練一個分詞模型(我們用 sentencepiece 實現)。

在我們的代碼里,可以選擇 tokenizer_mode = 'char''bpe'BPE 更推薦,能更快收斂,也能生成更自然的句子。

1.2 上下文窗口(Context Window

LLM 一次不能看全篇文章,它有一個“短期記憶”,叫 上下文窗口 (block_size)。比如 block_size=64,就表示模型最多能記住最近 64 個 token,再往前的就忘了。

  • 窗口越大 → 能處理更長的上下文,但訓練更慢、更占顯存。

  • 小實驗時建議 32~64。

  • 在代碼里,block_size 就是這個“記憶力”的大小。

1.3 預測下一個詞(Next Token Prediction

LLM 的訓練目標非常簡單:給定前面的 token,預測下一個 token 的概率分布。

例子:輸入 "The quick brown",模型大概率會預測 "fox"
這就是 Next Token Prediction —— 不斷重復這個游戲,模型就學會了語言規律。

topk_topp_demo

1.4 Transformer 架構

mini-GPT 就是一個簡化的 Transformer 解碼器,由三部分組成:

  1. Embedding:把 token id 變成向量,并加上位置信息。
  2. 自注意力(Self-Attention
    • 每個 token 可以“關注”前面的 token
    • 因果遮罩(Causal Mask,確保只看過去,不看未來。
  3. 前饋網絡 + 殘差連接 + LayerNorm:增加表達能力,保證訓練穩定。

最后輸出層 head 給出下一個 token 的概率分布。

1.5 生成策略(Sampling

訓練完模型后,要讓它“說話”。此時它會輸出下一個詞的概率分布,我們可以用不同方式來“抽簽”:

  • Temperature(溫度):控制隨機性。
    • 小于 1 → 更保守、確定性強。
    • 大于 1 → 更有創造性。
  • Top-k:只在概率最高的 k 個詞中挑。
  • Top-p(核采樣):動態選擇累計概率 ≤ p 的候選,更自然。
  • 頻率懲罰(frequency penalty:詞出現越多,下次越難選,防止復讀。
  • 出現懲罰(presence penalty:只要出現過,就扣分,鼓勵換話題。
  • 停止條件 / 最大長度:避免模型“一直說下去”。

在我們的 generate() 函數里,可以通過設置這些參數,直接看到生成風格的變化。


二、代碼框架搭建

理解了 LLM 的基本概念之后,我們要從代碼開始動手。這里我們用 Google Colab,因為它自帶 PythonGPU,不需要安裝復雜環境,還能免費用 GPU,非常適合學習和實驗。

GIF 2-9-2025 上午 10-23-48

2.1 準備環境(安裝依賴)

Colab 新建一個 Notebook,輸入:

!pip install torch sentencepiece

解釋:

  • torchPyTorch,是我們要用的深度學習框架。
  • sentencepieceGoogle 開源的分詞工具,用來做 BPE 分詞。

👉 如果你在本地跑,需要 Python 3.9+,并建議有一張支持 CUDA 的顯卡,否則速度會比較慢。

2.2 準備語料文件(input.txt

LLM 的“教材”就是語料。教材越多、越多樣,模型學得越好。我們先用一份小語料 input.txt 試試:

Once upon a time, there was a small language model.
It tried to read books, tell stories, and learn from text.
Sometimes it was good, sometimes it was silly.
But every day, it became a little bit better.The quick brown fox jumps over the lazy dog.
Hello world! This is a simple test of tokenization, context windows, and generation.詩言志,歌詠言。語言是人類的工具,也是思想的載體。
模型學習文字,就像小孩學說話。

👉 在 Colab 里,可以直接寫入文件:

text_data = """Once upon a time, there was a small language model.
It tried to read books, tell stories, and learn from text.
Sometimes it was good, sometimes it was silly.
But every day, it became a little bit better.The quick brown fox jumps over the lazy dog.
Hello world! This is a simple test of tokenization, context windows, and generation.詩言志,歌詠言。語言是人類的工具,也是思想的載體。
模型學習文字,就像小孩學說話。
"""with open("input.txt", "w", encoding="utf-8") as f:f.write(text_data)

?? 提醒:

  • 如果語料太短,模型只會“背書”,輸出幾乎和原文一樣。
  • 如果你換成幾萬字小說片段,輸出會更靈活、更有創造性。
2.3 讀取語料并檢查
from pathlib import Pathtext = Path('input.txt').read_text(encoding='utf-8')
print("語料長度(字符數)=", len(text))
print("開頭 200 個字符:\n", text[:200])

運行后會打印語料長度和前 200 個字符,方便確認文件讀取成功。

read_text

我在 Colab 中使用的 input.txt 的數據是 Alice’s Adventures in Wonderland,所以打印內容和截圖是不一樣的,不要糾結這個點。

2.4 實現分詞器(Tokenizer
2.4.1 為什么要分詞?

計算機不能直接理解文字,所以要把文字轉換成數字。分詞器(Tokenizer)就是把文本拆分成 token → 數字 id,同時還能把數字 id 轉回文本。

2.4.2 字符級分詞(最簡單)

每個字符就是一個 token

# 建立字表
chars = sorted(list(set(text)))
stoi = {ch: i for i, ch in enumerate(chars)}  # 字符 -> 數字
itos = {i: ch for i, ch in enumerate(chars)}  # 數字 -> 字符# 編碼 / 解碼函數
def encode(s: str):return [stoi[c] for c in s]def decode(ids: list):return "".join([itos[i] for i in ids])print("字符表大小 =", len(chars))
print("encode('Hello') =", encode("Hello"))
print("decode =", decode(encode("Hello")))

示例輸出:

字符表大小 = 68
encode('Hello') = [12, 45, 50, 50, 60]
decode = Hello

👉 好處:實現簡單。缺點:序列很長,訓練會更難。

2.4.3 BPE 分詞(更高效)

如果語料較大,用 BPEByte Pair Encoding)能更好地壓縮序列:

import sentencepiece as spm# 訓練一個 BPE 模型(詞表大小設為 200,適合小語料)
spm.SentencePieceTrainer.train(input="input.txt",model_prefix="spm_bpe",vocab_size=200,model_type="bpe",character_coverage=1.0,bos_id=-1, eos_id=-1, unk_id=0, pad_id=-1,hard_vocab_limit=False
)# 加載模型
sp = spm.SentencePieceProcessor(model_file="spm_bpe.model")# 定義編碼/解碼函數
def encode_bpe(s: str):return sp.encode(s, out_type=int)def decode_bpe(ids: list):return sp.decode(ids)print("BPE 詞表大小 =", sp.get_piece_size())
print("encode_bpe('Hello world') =", encode_bpe("Hello world"))
print("decode_bpe =", decode_bpe(encode_bpe("Hello world")))

示例輸出:

BPE 詞表大小 = 200
encode_bpe('Hello world') = [35, 78, 42]
decode_bpe = Hello world

👉 好處:序列更短,訓練更快,效果更好。

對比

  • 字符級 "Hello world" → 11 個 token
  • BPE "Hello world" → 2 個 token

注意
BPE 的分詞結果并不是固定的,比如 "Hello world" 可能會被切成 2 個,也可能是 5 個 token。這不是 bug,而是因為 BPE 只會合并訓練語料里出現過的高頻子串。如果某個詞在語料中出現得不夠頻繁,就會被拆成更小的子詞片段。

顯然,BPE 序列更短,更適合長文本訓練。

tokenizer_char_vs_bpe

?? 注意:

如果語料太短而 vocab_size 太大,會報錯。解決方法:減小詞表大小(比如 200)。

2.5 劃分訓練集與驗證集

機器學習必須要區分 訓練數據驗證數據

  • 訓練數據:模型學習用。
  • 驗證數據:檢查模型是否過擬合。
import torchdata = encode(text)  # 如果用 BPE,就改成 encode_bpe
data = torch.tensor(data, dtype=torch.long)n = int(0.9 * len(data))  # 90% 訓練,10% 驗證
train_data = data[:n]
val_data = data[n:]print("訓練集大小 =", len(train_data))
print("驗證集大小 =", len(val_data))

示例輸出:

訓練集大小 = 270
驗證集大小 = 30

三、實現 Transformer 解碼器

到目前為止,我們已經準備好了數據和分詞器。接下來要搭建的,就是 LLM 的“大腦”—— Transformer 解碼器。它的任務很明確:根據前面的 token,預測下一個 token 的概率分布

我們會逐層拆開看:Embedding → 自注意力 → 前饋網絡(MLP) → 堆疊多層 → 輸出層

3.1 Embedding:把數字變成向量

分詞器輸出的只是 token id(純數字),但神經網絡更擅長處理向量。 所以第一步:把每個 token id 映射到一個向量。

import torch
import torch.nn as nnvocab_size = 200     # 詞表大小(根據分詞器而定)
n_embd = 128         # 向量維度(embedding 維度)
block_size = 64      # 上下文窗口大小class TokenEmbedding(nn.Module):def __init__(self, vocab_size, n_embd, block_size):super().__init__()self.tok_emb = nn.Embedding(vocab_size, n_embd)   # token embeddingself.pos_emb = nn.Embedding(block_size, n_embd)   # 位置 embeddingdef forward(self, idx):B, T = idx.shapetok = self.tok_emb(idx)                           # (B, T, n_embd)pos = self.pos_emb(torch.arange(T, device=idx.device))  # (T, n_embd)return tok + pos  # token 向量 + 位置信息
  • token embedding:每個詞的“語義表示”。
  • position embedding:告訴模型詞的順序,否則模型只知道“有哪些詞”,卻不知道“順序如何”。
3.2 自注意力機制(Self-Attention

這是 Transformer 的核心。它的作用是:每個詞可以決定要多關注前面哪些詞,從中獲取信息

3.2.1 基本思路
  • 每個輸入向量會生成 查詢向量 (Q)、鍵向量 (K)、值向量 (V)
  • 通過 QK 的點積,得到注意力分數(相關性)。
  • Softmax 把分數轉成權重,再加權求和值向量 V
3.2.2 代碼實現
class CausalSelfAttention(nn.Module):def __init__(self, n_embd, n_head, block_size):super().__init__()self.n_head = n_headself.head_dim = n_embd // n_headself.qkv = nn.Linear(n_embd, 3 * n_embd, bias=False)self.proj = nn.Linear(n_embd, n_embd)# 因果遮罩:保證不能看未來self.register_buffer("mask", torch.tril(torch.ones(block_size, block_size)).view(1, 1, block_size, block_size))def forward(self, x):B, T, C = x.shapeqkv = self.qkv(x).view(B, T, 3, self.n_head, self.head_dim)q, k, v = qkv.unbind(dim=2)  # 拆成 Q, K, Vq, k, v = [t.transpose(1, 2) for t in (q, k, v)]  # (B, nh, T, hd)# 注意力分數 (B, nh, T, T)att = (q @ k.transpose(-2, -1)) / (self.head_dim ** 0.5)att = att.masked_fill(self.mask[:, :, :T, :T] == 0, float("-inf"))att = torch.softmax(att, dim=-1)# 加權求和y = att @ v  # (B, nh, T, hd)y = y.transpose(1, 2).contiguous().view(B, T, C)  # 拼回 (B, T, C)return self.proj(y)

這里的 因果遮罩 (Causal Mask) 非常關鍵:它確保每個位置只能看到“自己和前面的詞”,不能偷看未來。這就是“自回歸”的本質。

3.3 前饋網絡(Feed Forward, MLP

注意力層捕捉了依賴關系,但還需要增加“非線性變換能力”。這就是 MLP(前饋網絡) 的作用。

class FeedForward(nn.Module):def __init__(self, n_embd):super().__init__()self.net = nn.Sequential(nn.Linear(n_embd, 4 * n_embd),  # 放大nn.ReLU(),nn.Linear(4 * n_embd, n_embd),  # 再縮回去)def forward(self, x):return self.net(x)

3.4 Transformer Block

注意力層前饋層 組合起來,并加上 殘差連接層歸一化。一層能學到“短距離依賴”,比如“New → York”;多層堆疊,就能學到更長距離、更復雜的關系。

class TransformerBlock(nn.Module):def __init__(self, n_embd, n_head, block_size):super().__init__()self.ln1 = nn.LayerNorm(n_embd)self.ln2 = nn.LayerNorm(n_embd)self.attn = CausalSelfAttention(n_embd, n_head, block_size)self.ffwd = FeedForward(n_embd)def forward(self, x):x = x + self.attn(self.ln1(x))  # 殘差連接x = x + self.ffwd(self.ln2(x))  # 殘差連接return x

殘差連接:保留原始信息,避免梯度消失。

層歸一化:讓訓練更穩定。

3.5 GPT 模型主體

現在把所有部分拼起來,形成一個完整的 GPT 模型。

class GPT(nn.Module):def __init__(self, vocab_size, n_embd=128, n_head=4, n_layer=4, block_size=64):super().__init__()self.block_size = block_sizeself.embed = TokenEmbedding(vocab_size, n_embd, block_size)self.blocks = nn.Sequential(*[TransformerBlock(n_embd, n_head, block_size) for _ in range(n_layer)])self.ln_f = nn.LayerNorm(n_embd)self.head = nn.Linear(n_embd, vocab_size, bias=False)def forward(self, idx, targets=None):x = self.embed(idx)x = self.blocks(x)x = self.ln_f(x)logits = self.head(x)  # (B, T, vocab_size)loss = Noneif targets is not None:# 交叉熵:預測下一個 tokenloss = nn.functional.cross_entropy(logits.view(-1, logits.size(-1)), targets.view(-1))return logits, loss
  • logits:每個位置對整個詞表的預測分數(還沒轉成概率)。
  • loss:用交叉熵衡量“預測和真實答案的差距”。
3.6 小實驗:前向傳播

我們來做一個簡單的測試,看看模型能否正常運行:

model = GPT(vocab_size=vocab_size, n_embd=128, n_head=4, n_layer=2, block_size=64)
x = torch.randint(0, vocab_size, (1, 10))  # 隨機 10 個 token
logits, loss = model(x, x)
print("logits shape =", logits.shape)
print("loss =", loss.item())

示例輸出:

logits shape = torch.Size([1, 10, 200])
loss = 5.3

解釋:

  • [1, 10, 200] → 批大小=1,序列長度=10,每個位置預測 200 個詞的分布。
  • loss=5.3 → 說明預測和答案差距還比較大,這是正常的,因為模型還沒訓練。

attention_heatmap


四、訓練循環

前面我們已經實現了模型結構,但它現在就像一個剛出生的孩子:大腦有了,但里面是空的,還不會說話。訓練循環的作用就是不斷地 喂飯 → 考試 → 判分 → 調整,直到它逐漸學會語言規律。

4.1 為什么需要訓練循環?

訓練的本質是:

  1. 喂飯:給模型輸入文本(前文)。
  2. 考試:讓它預測下一個詞。
  3. 判分:計算預測和真實答案的差距(loss)。
  4. 調整:根據差距更新模型的參數。

就像小孩學說話:聽別人說 → 自己模仿 → 被糾正 → 慢慢改進。

4.2 批次采樣(get_batch

訓練時不能一次把所有數據丟進去(太慢、顯存會爆),所以我們把數據切成一個個 小批次(batch

import torchdef get_batch(split, block_size, batch_size, device):data = train_data if split == "train" else val_data# 確保不會越界:片段長度 = block_sizemax_start = len(data) - block_size - 1ix = torch.randint(0, max_start, (batch_size,))x = torch.stack([data[i : i + block_size] for i in ix])y = torch.stack([data[i + 1 : i + block_size + 1] for i in ix])return x.to(device), y.to(device)
  • x:輸入序列(前文)。
  • y:目標序列(就是 x 右移一位 → 下一個 token)。

例子:

  • 輸入:The quick brown
  • 目標:he quick brown fox

這樣模型學的就是“前文 → 下一個詞”。

4.3 損失函數(Loss

我們用 交叉熵(CrossEntropy 來衡量預測和真實答案的差距。

  • 如果模型預測“fox”的概率高,就獎勵它(loss 小)。
  • 如果它預測“dog”的概率高,就懲罰它(loss 大)。

可以理解為“預測分布” vs “正確答案(one-hot 向量)”的差距。

GPT 類里我們已經寫過:

loss = nn.functional.cross_entropy(logits.view(-1, vocab_size), targets.view(-1))
4.4 優化器(Optimizer

優化器的作用就是 更新參數,讓模型一步步變聰明。我們用 AdamW,這是 Transformer 的常見選擇。

import mathoptimizer = torch.optim.AdamW(model.parameters(), lr=3e-4, betas=(0.9, 0.95), weight_decay=0.01)

參數解釋:

  • lr=3e-4:學習率,決定“每次調整的幅度”。
  • betas:動量參數,幫助收斂更穩定。
  • weight_decay:權重衰減,防止過擬合。
4.5 學習率調度(Warmup + Cosine Decay

如果一上來就用大學習率,模型可能“嚇壞了”,訓練會不穩定。所以我們采用:

  • Warmup:前期小步慢跑(逐漸加大學習率)。
  • Cosine Decay:后期慢慢收尾(逐漸減小學習率)。
def cosine_lr(step, max_steps, base_lr, warmup):if step < warmup:return base_lr * (step + 1) / max(1, warmup)t = (step - warmup) / max(1, max_steps - warmup)return 0.5 * (1 + math.cos(math.pi * t)) * base_lr
4.6 梯度裁剪(Gradient Clipping

有時候梯度會突然爆炸,導致訓練崩掉。解決辦法是:把梯度裁剪在一定范圍內。

torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
4.7 訓練主循環

現在把所有東西拼起來:

device = "cuda" if torch.cuda.is_available() else "cpu"
model = GPT(vocab_size=vocab_size, n_embd=128, n_head=4, n_layer=2, block_size=64).to(device)max_steps = 1000
batch_size = 32
warmup = 100
base_lr = 3e-4optimizer = torch.optim.AdamW(model.parameters(), lr=base_lr, betas=(0.9, 0.95), weight_decay=0.01)for step in range(1, max_steps + 1):# 獲取一批訓練數據x, y = get_batch("train", block_size=64, batch_size=batch_size, device=device)# 前向傳播logits, loss = model(x, y)# 反向傳播optimizer.zero_grad(set_to_none=True)loss.backward()torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)# 動態調整學習率lr = cosine_lr(step, max_steps, base_lr, warmup)for pg in optimizer.param_groups:pg["lr"] = lroptimizer.step()# 每 100 步做一次驗證if step % 100 == 0:with torch.no_grad():vx, vy = get_batch("val", block_size=64, batch_size=batch_size, device=device)_, vloss = model(vx, vy)print(f"step {step}: train_loss={loss.item():.3f} | val_loss={vloss.item():.3f}")
4.8 輸出示例

運行后,你會看到類似這樣的日志:

step 100: train_loss=2.019 | val_loss=6.231
step 200: train_loss=1.444 | val_loss=5.789
step 300: train_loss=0.824 | val_loss=5.159
step 400: train_loss=0.486 | val_loss=4.909
...

解釋:

  • train_loss:模型在訓練集上的表現,應該隨訓練下降。
  • val_loss:模型在驗證集上的表現。如果 val_loss 先降后升,說明過擬合。

loss_curve

4.9 如何判斷訓練效果?
  1. 正常情況train_lossval_loss 都下降 → 模型在學規律。
  2. 過擬合train_loss 一直下降,但 val_loss 上升 → 模型只會背書。
  3. 欠擬合train_loss 長期很高 → 模型太小 / 學習率太低 / 數據太少。

在小語料實驗里,不要糾結 loss 數值,重要的是學會訓練流程。真正要訓練能用的模型,需要更大的語料和更長的訓練時間。


到這里,我們已經完整地實現了一個 mini-GPT,從最基礎的 Token / 分詞器,到 Transformer 架構;從 訓練循環,到能跑通的 第一個語言模型。請繼續閱讀:下篇:《從零實現 LLM(下):推理生成、常見問題與進階優化》


🎁 彩蛋:一鍵運行 Notebook

如果你不想從零復制粘貼代碼,或者想直接體驗完整的 mini-GPT 實現,我已經準備了一份 Google Colab Notebook

👉 點擊這里直接運行 mini-GPT(Colab)

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

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

相關文章

浪潮科技Java開發面試題及參考答案(120道題-下)

如何給 MySQL 表添加索引?添加索引的語法是什么?添加索引時需要考慮哪些因素(如字段類型、查詢頻率、索引選擇性)? 給 MySQL 表添加索引需根據業務需求選擇合適的索引類型,不同類型的索引語法不同,同時需綜合評估字段特性、查詢模式等因素,避免無效或過度索引。 一、…

大數據畢業設計選題推薦-基于大數據的宮頸癌風險因素分析與可視化系統-Spark-Hadoop-Bigdata

?作者主頁&#xff1a;IT研究室? 個人簡介&#xff1a;曾從事計算機專業培訓教學&#xff0c;擅長Java、Python、微信小程序、Golang、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦??? Java項目 Python…

【PyTorch實戰:Tensor變形】5、 PyTorch Tensor指南:從基礎操作到Autograd與GPU加速實戰

一、Tensor核心概念解析 1.1 什么是Tensor? Tensor是PyTorch中最基本的數據結構,也是深度學習框架的核心計算單元。我們可以將Tensor理解為多維數組的統一表示,它在PyTorch中的地位相當于NumPy中的ndarray,但具有兩個關鍵增強特性:GPU加速支持和自動求導能力。 1.2 為…

2025年我國具身智能產業鏈全景分析

一、具身智能產業概述與定義 1.1 具身智能的基本概念與內涵 具身智能&#xff08;Embodied Intelligence&#xff09;是指通過物理實體與環境進行交互的智能系統&#xff0c;其核心在于將感知、決策和執行緊密結合&#xff0c;使智能體能夠在動態環境中自主感知、學習和執行任務…

VMWare上搭建大數據集群

文章目錄1. 采用軟件較新版本2. 準備三臺虛擬機3. 搭建Hadoop集群3.1 在主節點上配置Hadoop3.1.1 編輯映射文件3.1.2 配置免密登錄3.1.3 配置JDK3.1.4 配置Hadoop3.2 從主節點分發到從節點3.3 格式化名稱節點3.4 啟動Hadoop集群3.5 使用Hadoop WebUI3.6 運行MR應用&#xff1a;…

小迪自用web筆記29

PHP刷新是點擊刷新之后原來的圖片替換掉&#xff0c;換成新的圖片。把inhoneJPG給替換掉如果這個圖片是由用戶可自定義輸入的話&#xff0c;可xss漏洞應用。因為這段代碼本質邏輯是點擊刷新之后。就執行update方法中的代碼&#xff0c;而這個方法中存儲的是。截取IMG&#xff0…

WPS--專業pj版

下載 下載鏈接 解壓后 安裝 默認安裝 激活 輸入解壓后文件中的激活碼

Android Framework智能座艙面試題

目錄 1.談一談你對binder機制的理解?它為什么是Android中最重要的IPC通信方式?與其他IPC(Socket、共享內存)通信方式相比有哪些優勢? 2.如果你需要新提供的車載硬件(比如:一個座椅震動馬達)提供系統級別支持應該怎么做? 3.你了解Android與QNX共存方案的實現方式嗎?他們…

[CISCN2019 華北賽區 Day1 Web1]Dropbox

TRY 首先上傳和刪除文件抓包&#xff0c;可以發現upload.php和delete.php&#xff0c;只允許上傳gif png jpg后綴的文件。但是上傳的文件并沒有辦法訪問&#xff0c;不過可以下載&#xff0c;抓包發現下載的時候請求體是文件名&#xff0c;嘗試能不能通過路徑穿越獲取源碼&…

網站管理后臺

這里套用的模板為 楓雨在線 在寶塔面板左側選擇菜單欄文件 在根目錄下找到www文件夾&#xff0c;點擊進入wwwroot文件夾&#xff0c;隨后能看到域名文件夾&#xff0c;里面有一下初始內容&#xff0c;可以全部刪掉&#xff0c;留下 .user.ini 文件 點擊上傳&#xff0c;將…

一款免費易用且打造的全功能媒體播放器

zyfun[zyplayer]是一款免費易用且打造的全功能媒體播放器, 致力于提供流暢、高效的跨平臺娛樂體驗。 注意&#xff1a;播放源請自行查詢&#xff0c;或者聯系博主。 下載&#xff1a;軟件下載 在線體驗可暫時使用:https://tv.snowytime.cn 密碼為123456 &#x1f389; 功能亮點…

【AI產品思路】AI 原型設計工具橫評:產品經理視角下的 v0、Bolt 與 Lovable

本文原創作者&#xff1a;姚瑞南 AI-agent 大模型運營專家/音樂人/野生穿搭model&#xff0c;先后任職于美團、獵聘等中大廠AI訓練專家和智能運營專家崗&#xff1b;多年人工智能行業智能產品運營及大模型落地經驗&#xff0c;擁有AI外呼方向國家專利與PMP項目管理證書。&#…

計算機視覺(九):圖像輪廓

在計算機視覺&#xff08;Computer Vision, CV&#xff09;中&#xff0c;圖像輪廓&#xff08;Image Contour&#xff09;是圖像中物體邊界的重要表現形式。它不僅能描述物體的形狀特征&#xff0c;還能為目標識別、目標檢測、圖像分割、場景理解、三維重建等任務提供重要依據…

ThinkPHP 6框架常見錯誤:htmlentities()函數參數類型問題解決

在ThinkPHP 6框架中&#xff0c;htmlentities() 函數是一個常用的PHP函數&#xff0c;用于將字符轉換為HTML實體。這個函數通常在輸出內容到瀏覽器時使用&#xff0c;以防止跨站腳本&#xff08;XSS&#xff09;攻擊。然而&#xff0c;在使用過程中可能會遇到參數類型問題。錯誤…

網絡通信 IO 模型學習總結基礎強化

網絡通信概念網絡通信因為要處理復雜的物理信號&#xff0c;錯誤處理等&#xff0c;所以采用了分層設計。為什么要采用分層設計&#xff1f;1. 每層可以獨立開發&#xff0c;測試和替換&#xff1b;2. 發生問題也可以快速定位到具體層次&#xff1b;3. 協議標準化&#xff0c;不…

【ComfyUI】深度 ControlNet 深度信息引導生成

今天給大家演示一個結合 ControlNet 深度信息的 ComfyUI 建筑可視化工作流。整個流程通過引入建筑專用的權重模型和深度控制網絡&#xff0c;使得生成的建筑圖像不僅具備高質量和超寫實的細節&#xff0c;還能精確遵循輸入圖片的結構特征。在這個案例中&#xff0c;模型加載、文…

Python數據可視化科技圖表繪制系列教程(六)

目錄 散點圖1 散點圖2 添加線性回歸線的散點圖 自定義點形狀的散點圖 不同樣式的散點圖 抖動散點圖 邊際圖 邊緣為直方圖的邊際圖 邊緣為箱線圖的邊際圖 曼哈頓圖 【聲明】&#xff1a;未經版權人書面許可&#xff0c;任何單位或個人不得以任何形式復制、發行、出租、…

spring AI 的簡單使用

1. 引入 Spring 官?推出的?個穩定版??智能(AI)集成框架. 旨在幫助 Java/Spring 開發者更便捷地在企業級應?中集成 AI 能? (如?語?模型、機器學習、向量數據庫、圖像?成等)。 它主要提供了以下功能&#xff1a; ? ?持主要的AI模型提供商, ?如 Anthropic、OpenAI、M…

圖像去霧:從暗通道先驗到可學習融合——一份可跑的 PyTorch 教程

一、為什么“去霧”依然是好課題&#xff1f; 真實需求大&#xff1a;手機拍照、自動駕駛、遙感、監控都要在惡劣天氣下成像。 數據集相對干凈&#xff1a;與通用目標檢測相比&#xff0c;去霧只有“有霧/無霧”一對圖像&#xff0c;標注成本低。 傳統與深度并存&#xff1a;…

Ubuntu 22.04.1上安裝MySQL 8.0及設置root密碼

安裝MySQL 8.0 在 Ubuntu 22.04.1 系統需要遵循幾個明確的步驟&#xff0c;并在安裝過程中配置root密碼&#xff0c;以下是詳細的過程和相關的注意事項。步驟 1: 更新系統 使用終端更新系統軟件包列表以確保所有的包是最新的。sudo apt update sudo apt upgrade步驟 2: 安裝MyS…