From 4bfee3d495dbcacfc17bbe11eae110a7096a2135 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:00:44 +0000 Subject: [PATCH] Deployed 7da26142 with MkDocs version: 1.6.1 --- Summaries/2025/weekly/2025-W01-12/index.html | 10 +++++----- Summaries/index.html | 2 +- Tags/index.html | 2 +- search/search_index.json | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Summaries/2025/weekly/2025-W01-12/index.html b/Summaries/2025/weekly/2025-W01-12/index.html index 449355cf..f24be6fb 100644 --- a/Summaries/2025/weekly/2025-W01-12/index.html +++ b/Summaries/2025/weekly/2025-W01-12/index.html @@ -8,7 +8,7 @@ -
My friends! / About Me
"},{"location":"Links/","title":"\u53cb\u94fe","text":""},{"location":"Links/#_1","title":"\u53cb\u94fe","text":"Abstract
My friends!
Wnc \u7684\u5496\u5561\u9986 \u6211\u81ea\u5df1\uff01 donotknow DoNotKnow Kinnari \u5f88\u5389\u5bb3\u7684\u5b66\u957f\uff01 MenGrey \u5f88\u5389\u5bb3\u7684\u540c\u5b66\uff01"},{"location":"AI/","title":"AI","text":""},{"location":"AI/#artificial-intelligence","title":"Artificial Intelligence","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
FFB6D \u590d\u73b0\u7ea6 1547 \u4e2a\u5b57 387 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 13 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/Dive_into_Deep_Learning/#1","title":"1 \u5f15\u8a00","text":""},{"location":"AI/Dive_into_Deep_Learning/#2","title":"2 \u9884\u5907\u77e5\u8bc6","text":""},{"location":"AI/Dive_into_Deep_Learning/#21","title":"2.1 \u6570\u636e\u64cd\u4f5c","text":"x = torch.arrange(12)\nx.shape\nx.numel()\nx.reshape(3, 4)\ntorch.zeros((2, 3, 4))\ntorch.ones((2, 3, 4))\ntorch.randn(3, 4)\n
torch.cat((X, Y), dim = 0) # \u7ad6\u7740\u52a0\ntorch.cat((X, Y), dim = 1) # \u6a2a\u7740\u52a0\nx.sum()\n
x.requires_grad_(True) # \u7b49\u4ef7\u4e8ex=torch.arange(4.0,requires_grad=True)\nx.grad # \u9ed8\u8ba4\u503c\u662fNone\ny = 2 * torch.dot(x, x)\ny.backward()\nx.grad\nx.grad == 4 * x\n
"},{"location":"AI/Dive_into_Deep_Learning/#251","title":"2.5.1 \u975e\u6807\u91cf\u53d8\u91cf\u7684\u53cd\u5411\u4f20\u64ad","text":"Python# \u5bf9\u975e\u6807\u91cf\u8c03\u7528backward\u9700\u8981\u4f20\u5165\u4e00\u4e2agradient\u53c2\u6570\uff0c\u8be5\u53c2\u6570\u6307\u5b9a\u5fae\u5206\u51fd\u6570\u5173\u4e8eself\u7684\u68af\u5ea6\u3002\n# \u672c\u4f8b\u53ea\u60f3\u6c42\u504f\u5bfc\u6570\u7684\u548c\uff0c\u6240\u4ee5\u4f20\u9012\u4e00\u4e2a1\u7684\u68af\u5ea6\u662f\u5408\u9002\u7684\nx.grad.zero_()\ny = x * x\n# \u7b49\u4ef7\u4e8ey.backward(torch.ones(len(x)))\ny.sum().backward()\nx.grad\n
"},{"location":"AI/Dive_into_Deep_Learning/#252","title":"2.5.2 \u5206\u79bb\u8ba1\u7b97","text":"Pythonx.grad.zero_()\ny = x * x\nu = y.detach()\nz = u * x\n\nz.sum().backward()\nx.grad == u\n
"},{"location":"AI/Dive_into_Deep_Learning/#26","title":"2.6 \u6982\u7387","text":""},{"location":"AI/Dive_into_Deep_Learning/#261","title":"2.6.1 \u57fa\u672c\u6982\u7387\u8bba","text":"fair_probs = torch.ones([6]) / 6\nmultinomial.Multinomial(10, fair_probs).sample() # \u591a\u4e2a\u6837\u672c\n
"},{"location":"AI/Dive_into_Deep_Learning/#262","title":"2.6.2 \u5904\u7406\u591a\u4e2a\u968f\u673a\u53d8\u91cf","text":"$$ P(A, B \\mid C) = P(A \\mid C)P(B \\mid C) $$
\\[ A \\perp B \\mid C \\]%matplotlib inline\nimport random\nimport torch\nfrom d2l import torch as d2l\ndef synthetic_data(w, b, num_examples): #@save\n \"\"\"\u751f\u6210y=Xw+b+\u566a\u58f0\"\"\"\n X = torch.normal(0, 1, (num_examples, len(w)))\n y = torch.matmul(X, w) + b\n y += torch.normal(0, 0.01, y.shape)\n return X, y.reshape((-1, 1))\n\ntrue_w = torch.tensor([2, -3.4])\ntrue_b = 4.2\nfeatures, labels = synthetic_data(true_w, true_b, 1000)\n\ndef data_iter(batch_size, features, labels):\n num_examples = len(features)\n indices = list(range(num_examples))\n # \u8fd9\u4e9b\u6837\u672c\u662f\u968f\u673a\u8bfb\u53d6\u7684\uff0c\u6ca1\u6709\u7279\u5b9a\u7684\u987a\u5e8f\n random.shuffle(indices)\n for i in range(0, num_examples, batch_size):\n batch_indices = torch.tensor(\n indices[i: min(i + batch_size, num_examples)])\n yield features[batch_indices], labels[batch_indices]\n\nw = torch.normal(0, 0.01, size=(2,1), requires_grad=True)\nb = torch.zeros(1, requires_grad=True)\n\ndef linreg(X, w, b): #@save\n \"\"\"\u7ebf\u6027\u56de\u5f52\u6a21\u578b\"\"\"\n return torch.matmul(X, w) + b\n\ndef squared_loss(y_hat, y): #@save\n \"\"\"\u5747\u65b9\u635f\u5931\"\"\"\n return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2\n\ndef sgd(params, lr, batch_size): #@save\n \"\"\"\u5c0f\u6279\u91cf\u968f\u673a\u68af\u5ea6\u4e0b\u964d\"\"\"\n with torch.no_grad():\n for param in params:\n param -= lr * param.grad / batch_size\n param.grad.zero_()\n\nlr = 0.03\nnum_epochs = 3\nnet = linreg\nloss = squared_loss\n\nfor epoch in range(num_epochs):\n for X, y in data_iter(batch_size, features, labels):\n l = loss(net(X, w, b), y) # X\u548cy\u7684\u5c0f\u6279\u91cf\u635f\u5931\n # \u56e0\u4e3al\u5f62\u72b6\u662f(batch_size,1)\uff0c\u800c\u4e0d\u662f\u4e00\u4e2a\u6807\u91cf\u3002l\u4e2d\u7684\u6240\u6709\u5143\u7d20\u88ab\u52a0\u5230\u4e00\u8d77\uff0c\n # \u5e76\u4ee5\u6b64\u8ba1\u7b97\u5173\u4e8e[w,b]\u7684\u68af\u5ea6\n l.sum().backward()\n sgd([w, b], lr, batch_size) # \u4f7f\u7528\u53c2\u6570\u7684\u68af\u5ea6\u66f4\u65b0\u53c2\u6570\n with torch.no_grad():\n train_l = loss(net(features, w, b), labels)\n print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')\n
"},{"location":"AI/Dive_into_Deep_Learning/#33","title":"3.3 \u7ebf\u6027\u56de\u5f52\u7684\u7b80\u6d01\u5b9e\u73b0","text":"Pythonimport numpy as np\nimport torch\nfrom torch.utils import data\nfrom d2l import torch as d2l\n\ntrue_w = torch.tensor([2, -3.4])\ntrue_b = 4.2\nfeatures, labels = d2l.synthetic_data(true_w, true_b, 1000) # \u751f\u6210\u6570\u636e\u96c6\n\ndef load_array(data_arrays, batch_size, is_train=True): #@save\n \"\"\"\u6784\u9020\u4e00\u4e2aPyTorch\u6570\u636e\u8fed\u4ee3\u5668\"\"\"\n dataset = data.TensorDataset(*data_arrays)\n return data.DataLoader(dataset, batch_size, shuffle=is_train)\n\nbatch_size = 10\ndata_iter = load_array((features, labels), batch_size) # \u8bfb\u53d6\u6570\u636e\u96c6\n\n# nn\u662f\u795e\u7ecf\u7f51\u7edc\u7684\u7f29\u5199\nfrom torch import nn\n\nnet = nn.Sequential(nn.Linear(2, 1)) # \u5b9a\u4e49\u6a21\u578b \uff08\u8f93\u5165\uff0c\u8f93\u51fa\uff09\u7279\u5f81\u5f62\u72b6\nnet[0].weight.data.normal_(0, 0.01)\nnet[0].bias.data.fill_(0) # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\nloss = nn.MSELoss() # \u5b9a\u4e49\u635f\u5931\u51fd\u6570\ntrainer = torch.optim.SGD(net.parameters(), lr=0.03) # \u5b9a\u4e49\u4f18\u5316\u7b97\u6cd5\n\n# \u8bad\u7ec3\nnum_epochs = 3\nfor epoch in range(num_epochs):\n for X, y in data_iter:\n l = loss(net(X) ,y)\n trainer.zero_grad()\n l.backward()\n trainer.step()\n l = loss(net(features), labels)\n print(f'epoch {epoch + 1}, loss {l:f}')\n\nw = net[0].weight.data\nprint('w\u7684\u4f30\u8ba1\u8bef\u5dee\uff1a', true_w - w.reshape(true_w.shape))\nb = net[0].bias.data\nprint('b\u7684\u4f30\u8ba1\u8bef\u5dee\uff1a', true_b - b)\n
"},{"location":"AI/Dive_into_Deep_Learning/#34-softmax","title":"3.4 softmax \u56de\u5f52","text":""},{"location":"AI/Dive_into_Deep_Learning/#341","title":"3.4.1 \u5206\u7c7b\u95ee\u9898","text":"%matplotlib inline\nimport torch\nimport torchvision\nfrom torch.utils import data\nfrom torchvision import transforms\nfrom d2l import torch as d2l\n\nd2l.use_svg_display()\n\n# \u901a\u8fc7ToTensor\u5b9e\u4f8b\u5c06\u56fe\u50cf\u6570\u636e\u4ecePIL\u7c7b\u578b\u53d8\u6362\u621032\u4f4d\u6d6e\u70b9\u6570\u683c\u5f0f\uff0c\n# \u5e76\u9664\u4ee5255\u4f7f\u5f97\u6240\u6709\u50cf\u7d20\u7684\u6570\u503c\u5747\u57280\uff5e1\u4e4b\u95f4\ntrans = transforms.ToTensor()\nmnist_train = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=True, transform=trans, download=True)\nmnist_test = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=False, transform=trans, download=True)\n\ndef get_fashion_mnist_labels(labels): #@save\n \"\"\"\u8fd4\u56deFashion-MNIST\u6570\u636e\u96c6\u7684\u6587\u672c\u6807\u7b7e\"\"\"\n text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',\n 'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']\n return [text_labels[int(i)] for i in labels]\n\ndef show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): #@save\n \"\"\"\u7ed8\u5236\u56fe\u50cf\u5217\u8868\"\"\"\n figsize = (num_cols * scale, num_rows * scale)\n _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)\n axes = axes.flatten()\n for i, (ax, img) in enumerate(zip(axes, imgs)):\n if torch.is_tensor(img):\n # \u56fe\u7247\u5f20\u91cf\n ax.imshow(img.numpy())\n else:\n # PIL\u56fe\u7247\n ax.imshow(img)\n ax.axes.get_xaxis().set_visible(False)\n ax.axes.get_yaxis().set_visible(False)\n if titles:\n ax.set_title(titles[i])\n return axes\n\nbatch_size = 256\n\ndef get_dataloader_workers(): #@save\n \"\"\"\u4f7f\u75284\u4e2a\u8fdb\u7a0b\u6765\u8bfb\u53d6\u6570\u636e\"\"\"\n return 4\n\ntrain_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,\n num_workers=get_dataloader_workers())\n\ndef load_data_fashion_mnist(batch_size, resize=None): #@save\n \"\"\"\u4e0b\u8f7dFashion-MNIST\u6570\u636e\u96c6\uff0c\u7136\u540e\u5c06\u5176\u52a0\u8f7d\u5230\u5185\u5b58\u4e2d\"\"\"\n trans = [transforms.ToTensor()]\n if resize:\n trans.insert(0, transforms.Resize(resize))\n trans = transforms.Compose(trans)\n mnist_train = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=True, transform=trans, download=True)\n mnist_test = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=False, transform=trans, download=True)\n return (data.DataLoader(mnist_train, batch_size, shuffle=True,\n num_workers=get_dataloader_workers()),\n data.DataLoader(mnist_test, batch_size, shuffle=False,\n num_workers=get_dataloader_workers()))\n\ntrain_iter, test_iter = load_data_fashion_mnist(32, resize=64)\nfor X, y in train_iter:\n print(X.shape, X.dtype, y.shape, y.dtype)\n break\n
"},{"location":"AI/Dive_into_Deep_Learning/#36-softmax","title":"3.6 softmax \u56de\u5f52\u7684\u4ece\u96f6\u5f00\u59cb\u5b9e\u73b0","text":"Pythonimport torch\nfrom IPython import display\nfrom d2l import torch as d2l\n\nbatch_size = 256\ntrain_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)\n\nnum_inputs = 784\nnum_outputs = 10\n\nW = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)\nb = torch.zeros(num_outputs, requires_grad=True) # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\n\nX = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\nX.sum(0, keepdim=True), X.sum(1, keepdim=True) \n\ndef softmax(X):\n X_exp = torch.exp(X)\n partition = X_exp.sum(1, keepdim=True)\n return X_exp / partition # \u8fd9\u91cc\u5e94\u7528\u4e86\u5e7f\u64ad\u673a\u5236\n\nX = torch.normal(0, 1, (2, 5))\nX_prob = softmax(X)\nX_prob, X_prob.sum(1) # \u5b9a\u4e49softmax\u64cd\u4f5c\n\ndef net(X):\n return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b) # \u5b9a\u4e49\u6a21\u578b\n\ny = torch.tensor([0, 2])\ny_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])\ny_hat[[0, 1], y] \ndef cross_entropy(y_hat, y):\n return - torch.log(y_hat[range(len(y_hat)), y])\n\ncross_entropy(y_hat, y) # \u5b9a\u4e49\u635f\u5931\u51fd\u6570\n\ndef accuracy(y_hat, y): #@save\n \"\"\"\u8ba1\u7b97\u9884\u6d4b\u6b63\u786e\u7684\u6570\u91cf\"\"\"\n if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:\n y_hat = y_hat.argmax(axis=1)\n cmp = y_hat.type(y.dtype) == y\n return float(cmp.type(y.dtype).sum())\n\ndef evaluate_accuracy(net, data_iter): #@save\n \"\"\"\u8ba1\u7b97\u5728\u6307\u5b9a\u6570\u636e\u96c6\u4e0a\u6a21\u578b\u7684\u7cbe\u5ea6\"\"\"\n if isinstance(net, torch.nn.Module):\n net.eval() # \u5c06\u6a21\u578b\u8bbe\u7f6e\u4e3a\u8bc4\u4f30\u6a21\u5f0f\n metric = Accumulator(2) # \u6b63\u786e\u9884\u6d4b\u6570\u3001\u9884\u6d4b\u603b\u6570\n with torch.no_grad():\n for X, y in data_iter:\n metric.add(accuracy(net(X), y), y.numel())\n return metric[0] / metric[1]\n\nclass Accumulator: #@save\n \"\"\"\u5728n\u4e2a\u53d8\u91cf\u4e0a\u7d2f\u52a0\"\"\"\n def __init__(self, n):\n self.data = [0.0] * n\n\n def add(self, *args):\n self.data = [a + float(b) for a, b in zip(self.data, args)]\n\n def reset(self):\n self.data = [0.0] * len(self.data)\n\n def __getitem__(self, idx):\n return self.data[idx]\n\nevaluate_accuracy(net, test_iter) # \u5206\u7c7b\u7cbe\u5ea6\n\ndef train_epoch_ch3(net, train_iter, loss, updater): #@save\n \"\"\"\u8bad\u7ec3\u6a21\u578b\u4e00\u4e2a\u8fed\u4ee3\u5468\u671f\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n # \u5c06\u6a21\u578b\u8bbe\u7f6e\u4e3a\u8bad\u7ec3\u6a21\u5f0f\n if isinstance(net, torch.nn.Module):\n net.train()\n # \u8bad\u7ec3\u635f\u5931\u603b\u548c\u3001\u8bad\u7ec3\u51c6\u786e\u5ea6\u603b\u548c\u3001\u6837\u672c\u6570\n metric = Accumulator(3)\n for X, y in train_iter:\n # \u8ba1\u7b97\u68af\u5ea6\u5e76\u66f4\u65b0\u53c2\u6570\n y_hat = net(X)\n l = loss(y_hat, y)\n if isinstance(updater, torch.optim.Optimizer):\n # \u4f7f\u7528PyTorch\u5185\u7f6e\u7684\u4f18\u5316\u5668\u548c\u635f\u5931\u51fd\u6570\n updater.zero_grad()\n l.mean().backward()\n updater.step()\n else:\n # \u4f7f\u7528\u5b9a\u5236\u7684\u4f18\u5316\u5668\u548c\u635f\u5931\u51fd\u6570\n l.sum().backward()\n updater(X.shape[0])\n metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())\n # \u8fd4\u56de\u8bad\u7ec3\u635f\u5931\u548c\u8bad\u7ec3\u7cbe\u5ea6\n return metric[0] / metric[2], metric[1] / metric[2]\n\nclass Animator: #@save\n \"\"\"\u5728\u52a8\u753b\u4e2d\u7ed8\u5236\u6570\u636e\"\"\"\n def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,\n ylim=None, xscale='linear', yscale='linear',\n fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,\n figsize=(3.5, 2.5)):\n # \u589e\u91cf\u5730\u7ed8\u5236\u591a\u6761\u7ebf\n if legend is None:\n legend = []\n d2l.use_svg_display()\n self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)\n if nrows * ncols == 1:\n self.axes = [self.axes, ]\n # \u4f7f\u7528lambda\u51fd\u6570\u6355\u83b7\u53c2\u6570\n self.config_axes = lambda: d2l.set_axes(\n self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)\n self.X, self.Y, self.fmts = None, None, fmts\n\n def add(self, x, y):\n # \u5411\u56fe\u8868\u4e2d\u6dfb\u52a0\u591a\u4e2a\u6570\u636e\u70b9\n if not hasattr(y, \"__len__\"):\n y = [y]\n n = len(y)\n if not hasattr(x, \"__len__\"):\n x = [x] * n\n if not self.X:\n self.X = [[] for _ in range(n)]\n if not self.Y:\n self.Y = [[] for _ in range(n)]\n for i, (a, b) in enumerate(zip(x, y)):\n if a is not None and b is not None:\n self.X[i].append(a)\n self.Y[i].append(b)\n self.axes[0].cla()\n for x, y, fmt in zip(self.X, self.Y, self.fmts):\n self.axes[0].plot(x, y, fmt)\n self.config_axes()\n display.display(self.fig)\n display.clear_output(wait=True)\n\ndef train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save\n \"\"\"\u8bad\u7ec3\u6a21\u578b\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],\n legend=['train loss', 'train acc', 'test acc'])\n for epoch in range(num_epochs):\n train_metrics = train_epoch_ch3(net, train_iter, loss, updater)\n test_acc = evaluate_accuracy(net, test_iter)\n animator.add(epoch + 1, train_metrics + (test_acc,))\n train_loss, train_acc = train_metrics\n assert train_loss < 0.5, train_loss\n assert train_acc <= 1 and train_acc > 0.7, train_acc\n assert test_acc <= 1 and test_acc > 0.7, test_acc\n\nlr = 0.1\n\ndef updater(batch_size):\n return d2l.sgd([W, b], lr, batch_size)\n\nnum_epochs = 10\ntrain_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater) # \u8bad\u7ec3\n\ndef predict_ch3(net, test_iter, n=6): #@save\n \"\"\"\u9884\u6d4b\u6807\u7b7e\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n for X, y in test_iter:\n break\n trues = d2l.get_fashion_mnist_labels(y)\n preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))\n titles = [true +'\\n' + pred for true, pred in zip(trues, preds)]\n d2l.show_images(\n X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])\n\npredict_ch3(net, test_iter) # \u9884\u6d4b\n
"},{"location":"AI/Dive_into_Deep_Learning/#37-softmax","title":"3.7 softmax \u56de\u5f52\u7684\u7b80\u6d01\u5b9e\u73b0","text":"Pythonimport torch\nfrom torch import nn\nfrom d2l import torch as d2l\n\nbatch_size = 256\ntrain_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)\n\n# PyTorch\u4e0d\u4f1a\u9690\u5f0f\u5730\u8c03\u6574\u8f93\u5165\u7684\u5f62\u72b6\u3002\u56e0\u6b64\uff0c\n# \u6211\u4eec\u5728\u7ebf\u6027\u5c42\u524d\u5b9a\u4e49\u4e86\u5c55\u5e73\u5c42\uff08flatten\uff09\uff0c\u6765\u8c03\u6574\u7f51\u7edc\u8f93\u5165\u7684\u5f62\u72b6\nnet = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))\n\ndef init_weights(m):\n if type(m) == nn.Linear:\n nn.init.normal_(m.weight, std=0.01)\n\nnet.apply(init_weights); # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\n
\\[ \\begin{split}\\begin{aligned} \\hat y_j & = \\frac{\\exp(o_j - \\max(o_k))\\exp(\\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))\\exp(\\max(o_k))} \\\\ & = \\frac{\\exp(o_j - \\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))}. \\end{aligned}\\end{split} \\] \\[ \\begin{split}\\begin{aligned} \\log{(\\hat y_j)} & = \\log\\left( \\frac{\\exp(o_j - \\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))}\\right) \\\\ & = \\log{(\\exp(o_j - \\max(o_k)))}-\\log{\\left( \\sum_k \\exp(o_k - \\max(o_k)) \\right)} \\\\ & = o_j - \\max(o_k) -\\log{\\left( \\sum_k \\exp(o_k - \\max(o_k)) \\right)}. \\end{aligned}\\end{split} \\] Pythonloss = nn.CrossEntropyLoss(reduction='none') # LogSumExp\u6280\u5de7\n\ntrainer = torch.optim.SGD(net.parameters(), lr=0.1) # \u4f18\u5316\u7b97\u6cd5\n\nnum_epochs = 10\nd2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer) # \u8bad\u7ec3\n
"},{"location":"AI/Dive_into_Deep_Learning/#_1","title":"\u591a\u5c42\u611f\u77e5\u673a","text":""},{"location":"AI/Dive_into_Deep_Learning/#_2","title":"\u8fc7\u62df\u5408\u548c\u6b20\u62df\u5408","text":""},{"location":"AI/Dive_into_Deep_Learning/#dropout","title":"dropout","text":""},{"location":"AI/Dive_into_Deep_Learning/#_3","title":"\u6df1\u5ea6\u5b66\u4e60\u8ba1\u7b97","text":""},{"location":"AI/Dive_into_Deep_Learning/#_4","title":"\u5377\u79ef\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#lenet","title":"LeNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#_5","title":"\u73b0\u4ee3\u5377\u79ef\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#alexnet","title":"AlexNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#vgg","title":"VGG","text":""},{"location":"AI/Dive_into_Deep_Learning/#nin","title":"NiN","text":""},{"location":"AI/Dive_into_Deep_Learning/#googlenet","title":"GoogLeNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#resnet","title":"ResNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#densenet","title":"DenseNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#_6","title":"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#_7","title":"\u73b0\u4ee3\u5faa\u73af\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#gru","title":"GRU","text":""},{"location":"AI/Dive_into_Deep_Learning/#lstm","title":"LSTM","text":""},{"location":"AI/Dive_into_Deep_Learning/#seq2seq","title":"seq2seq","text":""},{"location":"AI/Dive_into_Deep_Learning/#_8","title":"\u6ce8\u610f\u529b\u673a\u5236","text":""},{"location":"AI/Dive_into_Deep_Learning/#nadaraya-watson","title":"Nadaraya-Watson","text":""},{"location":"AI/Dive_into_Deep_Learning/#bahdanau","title":"Bahdanau","text":""},{"location":"AI/Dive_into_Deep_Learning/#multi-headed-attention","title":"Multi-headed attention","text":""},{"location":"AI/Dive_into_Deep_Learning/#transformer","title":"Transformer","text":""},{"location":"AI/Dive_into_Deep_Learning/#_9","title":"\u4f18\u5316\u7b97\u6cd5","text":""},{"location":"AI/Dive_into_Deep_Learning/#adagrad","title":"AdaGrad","text":""},{"location":"AI/Dive_into_Deep_Learning/#rmsprop","title":"RMSProp","text":""},{"location":"AI/Dive_into_Deep_Learning/#adadelta","title":"Adadelta","text":""},{"location":"AI/Dive_into_Deep_Learning/#adam","title":"Adam","text":""},{"location":"AI/Dive_into_Deep_Learning/#_10","title":"\u8ba1\u7b97\u6027\u80fd","text":""},{"location":"AI/Dive_into_Deep_Learning/#_11","title":"\u8ba1\u7b97\u673a\u89c6\u89c9","text":""},{"location":"AI/Dive_into_Deep_Learning/#ssd","title":"SSD","text":""},{"location":"AI/Dive_into_Deep_Learning/#r-cnn","title":"R-CNN","text":""},{"location":"AI/Dive_into_Deep_Learning/#_12","title":"\u81ea\u7136\u8bed\u8a00\u5904\u7406:\u9884\u8bad\u7ec3","text":""},{"location":"AI/Dive_into_Deep_Learning/#word2vec","title":"word2vec","text":""},{"location":"AI/Dive_into_Deep_Learning/#glove","title":"GloVe","text":""},{"location":"AI/Dive_into_Deep_Learning/#bert","title":"BERT","text":""},{"location":"AI/Dive_into_Deep_Learning/#_13","title":"\u81ea\u7136\u8bed\u8a00\u5904\u7406:\u5e94\u7528","text":""},{"location":"AI/SLAM14/","title":"\u89c6\u89c9SLAM\u5341\u56db\u8bb2","text":""},{"location":"AI/SLAM14/#slam","title":"\u89c6\u89c9SLAM\u5341\u56db\u8bb2","text":"\u7ea6 14110 \u4e2a\u5b57 72 \u884c\u4ee3\u7801 20 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 71 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/SLAM14/#1","title":"1 \u9884\u5907\u77e5\u8bc6","text":""},{"location":"AI/SLAM14/#11","title":"1.1 \u672c\u4e66\u8bb2\u4ec0\u4e48","text":"simultaneous localization and mapping
GitHub - gaoxiang12/slambook2: edition 2 of the slambook
"},{"location":"AI/SLAM14/#123","title":"1.2.3 \u9762\u5411\u7684\u8bfb\u8005","text":"apt
\u6765\u5b89\u88c5\u8f6f\u4ef6\u3002\u57fa\u672c\u547d\u4ee4\u4e3a sudo apt install [package-name]
\u3002/usr/
\u76ee\u5f55\u4e0b\uff0c\u4f46\u5177\u4f53\u7684\u6587\u4ef6\u53ef\u80fd\u5206\u5e03\u5728\u591a\u4e2a\u5b50\u76ee\u5f55\u4e2d\u3002apt search
\u547d\u4ee4\u6765\u641c\u7d22\u3002\u4f8b\u5982\uff0csudo apt search eigen
\u53ef\u4ee5\u5e2e\u52a9\u627e\u5230\u6240\u6709\u5305\u542b \"eigen\" \u7684\u8f6f\u4ef6\u5305\u3002cmake_minimum_required( VERSION 2.8)\n\nproject(HelloSLAM)\n\nadd_executable(helloSLAM helloSLAM.cpp)\n
\u5bf9\u4e2d\u95f4\u6587\u4ef6\u7684\u5904\u7406:
Text Onlymkdir build\ncd build\ncmake ..\nmake\n
"},{"location":"AI/SLAM14/#244","title":"2.4.4 \u4f7f\u7528\u5e93","text":"Text Onlyadd_library(hello libHelloSLAM.cpp)\n
add_library(hello_shared SHARED libHelloSLAM.cpp)\n
#ifndef LIBHELLOSLAM_H_\n#define LIBHELLOSLAM_H_\n\nvoid printHello()\n\n#endif\n
#include \"libHelloSLAM.h\"\n\nint main(int argc, char **argv) {\n printHello();\n return 0; \n}\n
add_executable(useHello useHello.cpp)\ntarget_link_libraries(useHello hello_shared)\n
"},{"location":"AI/SLAM14/#245-ide","title":"2.4.5 \u4f7f\u7528 IDE","text":"#include <iostream>\nusing namespace std;\n\n#include <ctime>\n\n#include <eigen3>\nusing namespace Eigen;\n\n#define MATRIX_SIZE 50\n\nint main(int argc, char **argv) {\n Matrix<float, 2, 3> matrix_23;\n// \u5982\u4e0b\u90fd\u662f\u4e09\u7ef4\u5411\u91cf\n Vector3d v_3d;\n Matrix<float, 3, 1> vd_3d;\n// \u5982\u4e0b\u662f3*3\u77e9\u9635\n Matrix3d matrix_33 = Matrix3d::Zero();\n// \u4e24\u4e2a\u52a8\u6001\u5206\u914d\n Matrix<double, Dynamic, Dynamic> matrix_dynamic;\n MatrixXd matrix_x;\n\n matrix_23 << 1, 2, 3, 4, 5, 6;\n cout<< \"matrix 2*3 from 1 to 6: \\n\" << matrix_23 << endl;\n\n cout << \"print matrix 2*3:\" << endl;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 3; j+) cout << matrix_23(i, j) << \"\\t\";\n cout << endl;\n }\n\n v_3d << 3, 2, 1;\n vd_3d << 4, 5, 6;\n\n Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;\n cout << \"[1, 2, 3; 4, 5, 6] * [3, 2, 1] =\" << result.transpose() << endl;\n\n matrix_22 = Matrix3d::Random();\n\n // \u4e00\u4e9b\u77e9\u9635\u7684\u64cd\u4f5c:\n // transpose()\n // sum()\n // trace()\n // inverse()\n // determinant()\n\n SelfAdjointEigenSolver<Matrix3d> eigen_solver(matrix_33.transpose() * matrix_33);\n cout << eigen_solver.eigenvalues() << endl;\n cout << eigen_solver.eigenvectors() << endl;\n\n // solve the equation\n Matrix<double, MATRIX_SIZE, MATRIX_SIZE> matrix_NN = MatrixXd::Random(MATRIX_SIZE, MATRIX_SIZE);\n matrix_NN = matrix_NN * matrix_NN.transpose()\n Matrix<double, MATRIX_SIZE, 1> v_Nd = MatrixXd::random(MATRIX_SIZE, 1);\n\n // \u7b2c\u4e00\u79cd:\u76f4\u63a5\u6c42\u9006\n Matrix<double, MATRIX_SIZE, 1> x = matrix_NN.inverse() * v_Nd;\n\n // \u7b2c\u4e8c\u79cd:\u77e9\u9635\u5206\u89e3\n x = matrix_NN.colPivHouseholderQr().solve(v_Nd);\n\n}\n
thus:
\\[ \\theta=\\arccos\\frac{\\mathrm{tr}(R)-1}{2}. \\] \\[ Rn=n. \\]\u5141\u8bb8\u7f29\u653e\uff0c\u76f8\u4f3c\u53d8\u6362\u7fa4: Sim (3) 2. \u4eff\u5c04\u53d8\u6362:
\\[ T_A=\\begin{bmatrix}A&t\\\\\\mathbf{0}^\\mathrm{T}&1\\end{bmatrix}. \\]\u53ea\u4fdd\u8bc1\u5e73\u884c\u5173\u7cfb 3. \u5c04\u5f71\u53d8\u6362
\\[ T_P=\\begin{bmatrix}A&t\\\\\\\\a^\\mathrm{T}&v\\end{bmatrix}. \\]\u603b\u7ed3\u4e00\u4e0b:
\\[ \\begin{array}{c|c|c|c}\\hline\\text{\u53d8\u6362\u540d\u79f0}&\\text{\u77e9\u9635\u5f62\u5f0f}&\\text{\u81ea\u7531\u5ea6}&\\text{\u4e0d\u53d8\u6027\u8d28}\\\\\\hline\\text{\u6b27\u6c0f\u53d8\u6362}&\\begin{bmatrix}R&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&6&\\text{\u957f\u5ea6\u3001\u5939\u89d2\u3001\u4f53\u79ef}\\\\\\text{\u76f8\u4f3c\u53d8\u6362}&\\begin{bmatrix}sR&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&7&\\text{\u4f53\u79ef\u6bd4}\\\\\\text{\u4eff\u5c04\u53d8\u6362}&\\begin{bmatrix}A&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&12&\\text{\u5e73\u884c\u6027\u3001\u4f53\u79ef\u6bd4}\\\\\\text{\u5c04\u5f71\u53d8\u6362}&\\begin{bmatrix}A&t\\\\a^\\mathrm{T}&v\\end{bmatrix}&15&\\text{\u63a5\u89e6\u5e73\u9762\u7684\u76f8\u4ea4\u548c\u76f8\u5207}\\\\\\hline\\end{array} \\]"},{"location":"AI/SLAM14/#36-eigen","title":"3.6 \u5b9e\u8df5: Eigen \u51e0\u4f55\u6a21\u5757","text":""},{"location":"AI/SLAM14/#361-eigen","title":"3.6.1 Eigen \u51e0\u4f55\u6a21\u5757\u7684\u6570\u636e\u6f14\u793a","text":"\u518d\u8bf4\u5427\u3002
"},{"location":"AI/SLAM14/#362","title":"3.6.2 \u5b9e\u9645\u7684\u5750\u6807\u53d8\u6362\u4f8b\u5b50","text":"TODO
"},{"location":"AI/SLAM14/#37","title":"3.7 \u53ef\u89c6\u5316\u6f14\u793a","text":""},{"location":"AI/SLAM14/#371","title":"3.7.1 \u663e\u793a\u8fd0\u52a8\u8f68\u8ff9","text":"TODO
"},{"location":"AI/SLAM14/#4","title":"4 \u674e\u7fa4\u548c\u674e\u4ee3\u6570","text":"\u4e8e\u662f\u6c42\u5bfc->\u4e00\u4e2a\u7b97\u7b26 \\(\\displaystyle \\phi\\) \uff0c\u88ab\u79f0\u4e3a \\(\\displaystyle \\boldsymbol{SO}(3)\\) \u539f\u70b9\u9644\u8fd1\u7684\u6b63\u5207\u7a7a\u95f4\uff08Tangent Space\uff09 \u8bbe\u5728 \\(\\displaystyle t_{0}\\) \u9644\u8fd1\uff0c\\(\\displaystyle \\phi\\) \u4fdd\u6301\u5e38\u6570 \\(\\displaystyle \\phi(t_{0})=\\phi_{0}\\)\uff0c
\\[ \\dot{\\boldsymbol{R}}(t)=\\boldsymbol{\\phi}(t_0)^\\wedge\\boldsymbol{R}(t)=\\boldsymbol{\\phi}_0^\\wedge\\boldsymbol{R}(t). \\]\u518d\u6709 \\(\\displaystyle \\boldsymbol{R}(0) = \\boldsymbol{I}\\)\uff0c\u89e3\u7684:
\\[ \\boldsymbol{R}(t)=\\exp\\left(\\boldsymbol{\\phi}_{0}^{\\wedge}t\\right). \\]\u674e\u4ee3\u6570\u7531\u4e00\u4e2a\u96c6\u5408 \\(\\displaystyle \\mathbb{V}\\)\u3001\u4e00\u4e2a\u6570\u57df \\(\\displaystyle \\mathbb{F}\\) \u548c\u4e00\u4e2a\u4e8c\u5143\u8fd0\u7b97 \\(\\displaystyle [,]\\) \u7ec4\u6210\u3002\u5982\u679c\u6ee1\u8db3\u4ee5\u4e0b\u51e0\u6761\u6027\u8d28\uff0c\u5219\u79f0 ( \\(\\displaystyle \\mathbb{V},\\mathbb{F},[,]\\)) \u4e3a\u4e00\u4e2a\u674e\u4ee3\u6570\uff0c\u8bb0\u4f5c \\(\\displaystyle \\mathfrak{g}\\)\u3002
\\(\\displaystyle \\boldsymbol{\\Phi}=\\boldsymbol{\\phi}^{\\wedge}=\\begin{bmatrix}0&-\\phi_3&\\phi_2\\\\\\\\\\phi_3&0&-\\phi_1\\\\\\\\-\\phi_2&\\phi_1&0\\end{bmatrix}\\in\\mathbb{R}^{3\\times3}.\\) \u6240\u4ee5\u4e24\u4e2a\u5411\u91cf \\(\\displaystyle \\phi_{1},\\phi_{2}\\) \u7684\u674e\u62ec\u53f7\u4e3a:
\\[ [\\phi_1,\\phi_2]=(\\boldsymbol{\\Phi}_1\\boldsymbol{\\Phi}_2-\\boldsymbol{\\Phi}_2\\boldsymbol{\\Phi}_1)^\\vee. \\] \\[ \\mathfrak{so}(3)=\\left\\{\\phi\\in\\mathbb{R}^3,\\boldsymbol{\\Phi}=\\phi^\\wedge\\in\\mathbb{R}^{3\\times3}\\right\\}. \\] \\[ R=\\exp(\\phi^{\\wedge}). \\]"},{"location":"AI/SLAM14/#415-displaystyle-mathfrakse3","title":"4.1.5 \u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{se}(3)\\)","text":"\\[ \\mathfrak{se}(3)=\\left\\{\\boldsymbol{\\xi}=\\begin{bmatrix}\\boldsymbol{\\rho}\\\\\\boldsymbol{\\phi}\\end{bmatrix}\\in\\mathbb{R}^6,\\boldsymbol{\\rho}\\in\\mathbb{R}^3,\\boldsymbol{\\phi}\\in\\mathfrak{so}(3),\\boldsymbol{\\xi}^\\wedge=\\begin{bmatrix}\\boldsymbol{\\phi}^\\wedge&\\boldsymbol{\\rho}\\\\\\boldsymbol{0}^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\]\u524d\u4e09\u7ef4\u4e3a\u5e73\u79fb\uff0c\u540e\u4e09\u7ef4\u4e3a\u65cb\u8f6c\uff08\u5b9e\u8d28\u4e0a\u662f \\(\\displaystyle \\mathfrak{so}(3)\\) \u5143\u7d20\uff09
\\[ \\xi^\\wedge=\\begin{bmatrix}\\phi^\\wedge&\\rho\\\\0^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}. \\]\u540c\u6837\u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{se}(3)\\) \u4e5f\u6709\u7c7b\u4f3c\u4e8e \\(\\displaystyle \\mathfrak{so}(3)\\) \u7684\u674e\u62ec\u53f7:
\\[ [\\xi_1,\\xi_2]=\\left(\\xi_1^\\wedge\\xi_2^\\wedge-\\xi_2^\\wedge\\xi_1^\\wedge\\right)^\\vee. \\]"},{"location":"AI/SLAM14/#42","title":"4.2 \u6307\u6570\u4e0e\u5bf9\u6570\u6620\u5c04","text":""},{"location":"AI/SLAM14/#421-so3","title":"4.2.1 SO(3)\u4e0a\u7684\u6307\u6570\u6620\u5c04","text":"\u548c
\\[ a^{\\wedge}a^{\\wedge}a^{\\wedge}=a^{\\wedge}(aa^{\\mathrm{T}}-I)=-a^{\\wedge}. \\]\u4e8e\u662f\u6211\u4eec\u53ef\u4ee5\u5316\u7b80:
\\[ \\begin{aligned} \\exp\\left(\\phi^\\wedge\\right)& =\\exp\\left(\\theta\\boldsymbol{a}^\\wedge\\right)=\\sum_{n=0}^\\infty\\frac1{n!}\\left(\\theta\\boldsymbol{a}^\\wedge\\right)^n \\\\ &=I+\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{2!}\\theta^{2}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\frac{1}{3!}\\theta^{3}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\frac{1}{4!}\\theta^{4}(\\boldsymbol{a}^{\\wedge})^{4}+\\cdots \\\\ &=\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{2!}\\theta^{2}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}-\\frac{1}{3!}\\theta^{3}\\boldsymbol{a}^{\\wedge}-\\frac{1}{4!}\\theta^{4}(\\boldsymbol{a}^{\\wedge})^{2}+\\cdots \\\\ &=\\boldsymbol{a}\\boldsymbol{a}^{\\mathsf{T}}+\\underbrace{\\left(\\theta-\\frac{1}{3!}\\theta^{3}+\\frac{1}{5!}\\theta^{5}-\\cdots\\right)}_{\\sin\\theta}\\boldsymbol{a}^{\\wedge}-\\underbrace{\\left(1-\\frac{1}{2!}\\theta^{2}+\\frac{1}{4!}\\theta^{4}-\\cdots\\right)}_{\\cos\\theta}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge} \\\\ &=a^\\wedge a^\\wedge+I+\\sin\\theta a^\\wedge-\\cos\\theta a^\\wedge a^\\wedge \\\\ &=(1-\\cos\\theta)\\boldsymbol{a}^\\wedge\\boldsymbol{a}^\\wedge+\\boldsymbol{I}+\\sin\\theta\\boldsymbol{a}^\\wedge \\\\ &=\\cos\\theta\\boldsymbol{I}+(1-\\cos\\theta)\\boldsymbol{aa}^\\mathrm{T}+\\sin\\theta\\boldsymbol{a}^\\mathrm{\\wedge}. \\end{aligned} \\]\u6700\u540e\u5f97\u5230:
\\[ \\exp(\\theta\\boldsymbol{a}^\\wedge)=\\cos\\theta\\boldsymbol{I}+(1-\\cos\\theta)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\sin\\theta\\boldsymbol{a}^\\wedge. \\]\u6240\u4ee5 \\(\\displaystyle \\mathfrak{so}(3)\\) \u5c31\u662f\u65cb\u91cf\u5411\u91cf\u7ec4\u6210\u7684\u7a7a\u95f4\uff0c\u800c\u6307\u6570\u6620\u5c04\u5373\u7f57\u5fb7\u91cc\u683c\u65af\u516c\u5f0f\u3002
\u540c\u6837\u7684\u63a8\u5bfc\u65b9\u5f0f:
\\[ \\begin{aligned} \\exp\\left(\\xi^{\\wedge}\\right)& =\\begin{bmatrix}\\sum_{n=0}^{\\infty}\\frac{1}{n!}(\\phi^{\\wedge})^{n}&\\sum_{n=0}^{\\infty}\\frac{1}{(n+1)!}(\\phi^{\\wedge})^{n}\\rho\\\\\\\\\\mathbf{0}^{\\mathrm{T}}&1\\end{bmatrix} \\\\ &\\stackrel{\\Delta}{=}\\begin{bmatrix}R&J\\rho\\\\\\\\0^\\mathrm{T}&1\\end{bmatrix}=T. \\end{aligned} \\] \\[ \\begin{aligned} \\sum_{n=0}^{\\infty}\\frac{1}{(n+1)!}(\\phi^{\\wedge})^{n}& =\\boldsymbol{I}+\\frac{1}{2!}\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{3!}\\theta^{2}{(\\boldsymbol{a}^{\\wedge})}^{2}+\\frac{1}{4!}\\theta^{3}{(\\boldsymbol{a}^{\\wedge})}^{3}+\\frac{1}{5!}\\theta^{4}{(\\boldsymbol{a}^{\\wedge})}^{4}\\cdots \\\\ &=\\frac{1}{\\theta}\\left(\\frac{1}{2!}\\theta^{2}-\\frac{1}{4!}\\theta^{4}+\\cdots\\right)(\\boldsymbol{a}^{\\wedge})+\\frac{1}{\\theta}\\left(\\frac{1}{3!}\\theta^{3}-\\frac{1}{5}\\theta^{5}+\\cdots\\right)(\\boldsymbol{a}^{\\wedge})^{2}+\\boldsymbol{I} \\\\ &=\\frac1\\theta\\left(1-\\cos\\theta\\right)\\left(\\boldsymbol{a}^{\\wedge}\\right)+\\frac{\\theta-\\sin\\theta}\\theta\\left(\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\boldsymbol{I}\\right)+\\boldsymbol{I} \\\\ &=\\frac{\\sin\\theta}\\theta\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}\\theta\\right)\\boldsymbol{aa}^\\mathrm{T}+\\frac{1-\\cos\\theta}\\theta\\boldsymbol{a}^\\mathrm{\\wedge}\\overset{\\mathrm{def}}{\\operatorname*{=}}\\boldsymbol{J}. \\end{aligned} \\] \\[ \\boldsymbol{J}=\\frac{\\sin\\theta}{\\theta}\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}{\\theta}\\right)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\frac{1-\\cos\\theta}{\\theta}\\boldsymbol{a}^\\mathrm{\\wedge}. \\]4.28 \u6ca1\u770b\u61c2
"},{"location":"AI/SLAM14/#43","title":"4.3 \u674e\u4ee3\u6570\u6c42\u5bfc\u4e0e\u6270\u52a8\u6a21\u578b","text":""},{"location":"AI/SLAM14/#431-bch","title":"4.3.1 BCH \u516c\u5f0f\u4e0e\u8fd1\u4f3c\u5f62\u5f0f","text":"\u63a2\u7a76\u5982\u4e0b\u5f0f\u5b50\u662f\u5426\u6210\u7acb:
\\[ \\ln\\left(\\exp\\left(A\\right)\\exp\\left(B\\right)\\right)=A+B ? \\]\u4f46\u5b83\u5e76\u4e0d\u6210\u7acb\u3002\u4e24\u4e2a\u674e\u4ee3\u6570\u6307\u6570\u6620\u5c04\u4e58\u79ef\u7684\u5b8c\u6574\u5f62\u5f0f\uff0c\u7531 Baker-Campbell-Hausdorff \u7ed9\u51fa:
\\[ \\ln\\left(\\exp\\left(A\\right)\\exp\\left(B\\right)\\right)=A+B+\\frac{1}{2}\\left[A,B\\right]+\\frac{1}{12}\\left[A,\\left[A,B\\right]\\right]-\\frac{1}{12}\\left[B,\\left[A,B\\right]\\right]+\\cdots \\]\u7279\u522b\u7684\uff0c\u5f53 \\(\\displaystyle \\phi_{1}\\) \u6216 \\(\\displaystyle \\phi_{2}\\) \u4e3a\u5c0f\u91cf\u65f6\uff0c\u5c0f\u91cf\u4e8c\u6b21\u4ee5\u4e0a\u7684\u9879\u90fd\u53ef\u4ee5\u88ab\u5ffd\u7565\uff0c\u6b64\u65f6\u7684\u7ebf\u6027\u8fd1\u4f3c\u8868\u8fbe:
\\[ \\ln\\left(\\exp\\left(\\phi_1^\\wedge\\right)\\exp\\left(\\phi_2^\\wedge\\right)\\right)^\\vee\\approx\\begin{cases}J_l(\\phi_2)^{-1}\\phi_1+\\phi_2&\\text{\u5f53}\\phi_1\\text{\u4e3a\u5c0f\u91cf},\\\\J_r(\\phi_1)^{-1}\\phi_2+\\phi_1&\\text{\u5f53}\\phi_2\\text{\u4e3a\u5c0f\u91cf}.\\end{cases} \\] \\[ \\boldsymbol{J}_{l}=\\frac{\\sin\\theta}{\\theta}\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}{\\theta}\\right)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\frac{1-\\cos\\theta}{\\theta}\\boldsymbol{a}^\\mathrm{\\wedge}. \\] \\[ \\boldsymbol{J}_{\\ell}^{-1}=\\frac{\\theta}{2}\\cot\\frac{\\theta}{2}\\boldsymbol{I}+\\left(1-\\frac{\\theta}{2}\\cot\\frac{\\theta}{2}\\right)\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\frac{\\theta}{2}\\boldsymbol{a}^{\\wedge}. \\] \\[ J_{r}(\\phi)=J_{l}(-\\phi). \\]\u4e8e\u662f\u6211\u4eec\u5c31\u53ef\u4ee5\u8c08\u8bba\u674e\u7fa4\u4e58\u6cd5\u4e0e\u674e\u4ee3\u6570\u52a0\u6cd5\u7684\u5173\u7cfb\u4e86\u3002 \\(\\displaystyle \\boldsymbol{R}\\) \u5bf9\u5e94 \\(\\displaystyle \\phi\\)\uff0c\u6211\u4eec\u7ed9\u5b83\u5de6\u4e58\u4e00\u4e2a\u5fae\u5c0f\u65cb\u8f6c\uff0c\u8bb0\u4f5c \\(\\displaystyle \\Delta \\boldsymbol{R}\\)
\\[ \\exp\\left(\\Delta\\phi^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)=\\exp\\left(\\left(\\phi+J_{l}^{-1}\\left(\\phi\\right)\\Delta\\phi\\right)^{\\wedge}\\right). \\] \\[ \\exp\\left(\\left(\\phi+\\Delta\\phi\\right)^{\\wedge}\\right)=\\exp\\left(\\left(J_{l}\\Delta\\phi\\right)^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)=\\exp\\left(\\phi^{\\wedge}\\right)\\exp\\left(\\left(J_{r}\\Delta\\phi\\right)^{\\wedge}\\right). \\]\u5bf9\u4e8e SE (3) \u6211\u4eec\u4e5f\u6709:
\\[ \\exp\\left(\\Delta\\xi^{\\wedge}\\right)\\exp\\left(\\xi^{\\wedge}\\right)\\approx\\exp\\left(\\left(\\mathcal{J}_{l}^{-1}\\Delta\\xi+\\xi\\right)^{\\wedge}\\right) \\] \\[ exp\\left(\\xi^{\\wedge}\\right)\\exp\\left(\\Delta\\xi^{\\wedge}\\right)\\approx\\exp\\left(\\left(\\mathcal{J}_{r}^{-1}\\Delta\\xi+\\xi\\right)^{\\wedge}\\right). \\]\u552f\u4e00\u4e0d\u540c\u7684\u662f\u8fd9\u91cc\u7684 \\(\\displaystyle J_{l}\\) \u6bd4\u8f83\u590d\u6742\u3002
"},{"location":"AI/SLAM14/#432-so-3","title":"4.3.2 SO (3) \u4e0a\u7684\u674e\u4ee3\u6570\u6c42\u5bfc","text":"\\[ z=T\\boldsymbol{p}+\\boldsymbol{w}. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{w}\\) \u662f\u968f\u673a\u566a\u58f0\u3002
\\[ e=z-Tp. \\]\u5047\u8bbe\u4e00\u5171\u6709 N \u4e2a\u8fd9\u6837\u7684\u8def\u6807\u70b9\u548c\u89c2\u6d4b:
\\[ \\min_{\\boldsymbol{T}}J(\\boldsymbol{T})=\\sum_{i=1}^N\\left\\|\\boldsymbol{z}_i-\\boldsymbol{T}\\boldsymbol{p}_i\\right\\|_2^2. \\]most importantly\uff0c\u6211\u4eec\u4f1a\u6784\u5efa\u4e0e\u4f4d\u59ff\u6709\u5173\u7684\u51fd\u6570\uff0c\u5e76\u8ba8\u8bba\u8be5\u51fd\u6570\u5173\u4e8e\u4f4d\u59ff\u7684\u5bfc\u6570\uff0c\u4ee5\u8c03\u6574\u5f53\u524d\u7684\u4f30\u8ba1\u503c\u3002 \u4f7f\u7528\u674e\u4ee3\u6570\u89e3\u51b3\u6c42\u5bfc\u95ee\u9898\u7684\u601d\u8def\u5206\u4e3a\u4e24\u79cd:
\u8981\u8ba1\u7b97 \\(\\displaystyle \\frac{\\partial\\left(Rp\\right)}{\\partial R}\\), \u7531\u4e8eSO\uff083\uff09\u6ca1\u6709\u52a0\u6cd5\uff0c\u6211\u4eec\u8f6c\u800c\u8ba1\u7b97: \\(\\displaystyle \\frac{\\partial\\left(\\exp\\left(\\phi^{\\wedge}\\right)\\boldsymbol{p}\\right)}{\\partial\\boldsymbol{\\phi}}.\\)
\\[ \\begin{aligned} \\frac{\\partial\\left(\\exp\\left(\\phi^{\\wedge}\\right)\\boldsymbol{p}\\right)}{\\partial\\phi}& =\\lim_{\\delta\\boldsymbol{\\phi}\\to0}\\frac{\\exp\\left(\\left(\\boldsymbol{\\phi}+\\delta\\boldsymbol{\\phi}\\right)^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\phi}} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\exp\\left(\\left(\\boldsymbol{J}_i\\delta\\boldsymbol{\\phi}\\right)^\\wedge\\right)\\exp\\left(\\boldsymbol{\\phi}^\\wedge\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^\\wedge\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\phi}} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\left(\\boldsymbol{I}+\\left(\\boldsymbol{J}_{l}\\delta\\boldsymbol{\\phi}\\right)^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\phi} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\left(\\boldsymbol{J}_{l}\\delta\\phi\\right)^{\\wedge}\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\phi} \\\\ &=\\lim_{\\delta\\boldsymbol{\\phi}\\to0}\\frac{-(\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p})^{\\wedge}\\boldsymbol{J}_{l}\\delta\\boldsymbol{\\phi}}{\\delta\\boldsymbol{\\phi}}=-(\\boldsymbol{R}\\boldsymbol{p})^{\\wedge}\\boldsymbol{J}_{l}. \\end{aligned} \\]BCH \u7ebf\u6027\u8fd1\u4f3c+\u6cf0\u52d2\u5c55\u5f00\u53d6\u7ebf\u6027\u9879:
\\[ \\frac{\\partial\\left(\\boldsymbol{Rp}\\right)}{\\partial\\boldsymbol{\\phi}}=\\left(-\\boldsymbol{Rp}\\right)^{\\wedge}\\boldsymbol{J}_{l}. \\]\u4f46\u662f\u8fd9\u91cc\u4ecd\u7136\u6709 \\(\\displaystyle \\boldsymbol{J}_{l}\\)
"},{"location":"AI/SLAM14/#441","title":"4.4.1 \u6270\u52a8\u6a21\u578b\uff08\u5de6\u4e58\uff09","text":"\\(\\displaystyle \\varphi\\) \u5bf9\u5e94\u5de6\u6270\u52a8 \\(\\displaystyle \\Delta \\boldsymbol{R}\\)
\\[ \\begin{aligned} \\frac{\\partial\\left(Rp\\right)}{\\partial\\varphi}& =\\lim_{\\varphi\\to0}\\frac{\\exp\\left(\\varphi^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)p-\\exp\\left(\\phi^{\\wedge}\\right)p}{\\varphi} \\\\ &=\\lim_{\\varphi\\to0}\\frac{(\\boldsymbol{I}+\\boldsymbol{\\varphi}^{\\wedge})\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\varphi} \\\\ &=\\lim_{\\varphi\\to0}\\frac{\\varphi^\\wedge Rp}\\varphi=\\lim_{\\varphi\\to0}\\frac{-\\left(Rp\\right)^\\wedge\\varphi}\\varphi=-\\left(Rp\\right)^\\wedge. \\end{aligned} \\]"},{"location":"AI/SLAM14/#442-se-3","title":"4.4.2 SE (3) \u4e0a\u7684\u674e\u4ee3\u6570\u6c42\u5bfc","text":"\\[ \\begin{aligned} \\frac{\\partial\\left(\\boldsymbol{T}\\boldsymbol{p}\\right)}{\\partial\\delta\\boldsymbol{\\xi}}&=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\boldsymbol{0}}\\frac{\\exp\\left(\\delta\\boldsymbol{\\xi}^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\xi} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\mathbf{0}}\\frac{\\left(\\boldsymbol{I}+\\delta\\boldsymbol{\\xi}^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to0}\\frac{\\delta\\boldsymbol{\\xi}^{\\wedge}\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\mathbf{0}}\\frac{\\begin{bmatrix}\\delta\\boldsymbol{\\phi}^\\wedge&\\delta\\boldsymbol{\\rho}\\\\\\\\\\mathbf{0}^\\mathrm{T}&0\\end{bmatrix}\\begin{bmatrix}\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}\\\\\\\\1\\end{bmatrix}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\boldsymbol{0}}\\frac{\\begin{bmatrix}\\delta\\boldsymbol{\\phi}^{\\wedge}\\left(\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}\\right)+\\delta\\boldsymbol{\\rho}\\\\\\boldsymbol{0}^{\\mathrm{T}}\\end{bmatrix}}{[\\delta\\boldsymbol{\\rho},\\delta\\boldsymbol{\\phi}]^{\\mathrm{T}}}=\\begin{bmatrix}\\boldsymbol{I}&-(\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t})^{\\wedge}\\\\\\boldsymbol{0}^{\\mathrm{T}}&\\boldsymbol{0}^{\\mathrm{T}}\\end{bmatrix}\\stackrel{\\mathrm{def}}{=}(\\boldsymbol{T}\\boldsymbol{p})^{\\odot}. \\end{aligned} \\] \\[ \\frac{\\mathrm{d}\\begin{bmatrix}a\\\\b\\end{bmatrix}}{\\mathrm{d}\\begin{bmatrix}x\\\\y\\end{bmatrix}}=\\left(\\frac{\\mathrm{d}[a,b]^\\mathrm{T}}{\\mathrm{d}\\begin{bmatrix}x\\\\y\\end{bmatrix}}\\right)^\\mathrm{T}=\\begin{bmatrix}\\frac{\\mathrm{d}a}{\\mathrm{d}x}&\\frac{\\mathrm{d}b}{\\mathrm{d}x}\\\\\\frac{\\mathrm{d}a}{\\mathrm{d}y}&\\frac{\\mathrm{d}b}{\\mathrm{d}y}\\end{bmatrix}^\\mathrm{T}=\\begin{bmatrix}\\frac{\\mathrm{d}a}{\\mathrm{d}x}&\\frac{\\mathrm{d}a}{\\mathrm{d}y}\\\\\\frac{\\mathrm{d}b}{\\mathrm{d}x}&\\frac{\\mathrm{d}b}{\\mathrm{d}y}\\end{bmatrix} \\]"},{"location":"AI/SLAM14/#45-sophus","title":"4.5 \u5b9e\u8df5:Sophus","text":""},{"location":"AI/SLAM14/#451-sophus","title":"4.5.1 Sophus \u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5","text":""},{"location":"AI/SLAM14/#452","title":"4.5.2 \u4f8b\u5b50: \u8bc4\u4f30\u8f68\u8ff9\u7684\u8bef\u5dee","text":"\u5373\u5747\u65b9\u6839\u8bef\u5dee\uff08Root-Mean-Squared Error, RMSE\uff09
\u4ee3\u7801\u8ba1\u7b97:
Text OnlyTODO\n
"},{"location":"AI/SLAM14/#46","title":"4.6 \u76f8\u4f3c\u53d8\u6362\u4e0e\u674e\u4ee3\u6570","text":"\u5728\u8fd9\u91cc\u6211\u4eec\u8ba8\u8bba Sim (3) \u548c\u5bf9\u5e94\u7684\u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{sim}(3)\\)\u3002 \u5bf9\u4e8e\u4f4d\u4e8e\u7a7a\u95f4\u7684\u70b9 \\(\\displaystyle \\boldsymbol{p}\\)\uff0c\u5728\u76f8\u673a\u5750\u6807\u7cfb\u4e0b\u8981\u7ecf\u8fc7\u4e00\u4e2a\u76f8\u4f3c\u53d8\u6362\uff0c\u800c\u975e\u6b27\u6c0f\u53d8\u6362:
\\[ \\boldsymbol{p}'=\\begin{bmatrix}s\\boldsymbol{R}&\\boldsymbol{t}\\\\\\boldsymbol{0}^\\mathrm{T}&1\\end{bmatrix}\\boldsymbol{p}=s\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}. \\] \\[ \\mathrm{Sim}(3)=\\left\\{S=\\begin{bmatrix}sR&t\\\\\\\\\\mathbf{0}^\\mathrm{T}&1\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\] \\[ \\sin(3)=\\left\\{\\zeta|\\zeta=\\begin{bmatrix}\\rho\\\\\\\\\\phi\\\\\\\\\\sigma\\end{bmatrix}\\in\\mathbb{R}^7,\\zeta^\\wedge=\\begin{bmatrix}\\sigma\\boldsymbol{I}+\\phi^\\wedge&\\rho\\\\\\\\\\mathbf{0}^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\] \\[ \\exp\\left(\\zeta^{\\wedge}\\right)=\\begin{bmatrix}\\mathrm{e}^{\\sigma}\\exp\\left(\\phi^{\\wedge}\\right)&J_{s}\\rho\\\\0^{\\mathrm{T}}&1\\end{bmatrix}. \\]\u5176\u4e2d\uff0c\\(\\displaystyle \\boldsymbol{J}_{S}\\) \u7684\u5f62\u5f0f\u662f:
\\[ \\begin{aligned} \\text{J}& =\\frac{\\mathrm{e}^{\\sigma}-1}{\\sigma}I+\\frac{\\sigma\\mathrm{e}^{\\sigma}\\sin\\theta+\\left(1-\\mathrm{e}^{\\sigma}\\cos\\theta\\right)\\theta}{\\sigma^{2}+\\theta^{2}}\\boldsymbol{a}^{\\wedge} \\\\ &+\\left(\\frac{\\mathrm{e}^\\sigma-1}{\\sigma}-\\frac{\\left(\\mathrm{e}^\\sigma\\cos\\theta-1\\right)\\sigma+\\left(\\mathrm{e}^\\sigma\\sin\\theta\\right)\\theta}{\\sigma^2+\\theta^2}\\right)\\boldsymbol{a}^\\wedge\\boldsymbol{a}^\\wedge. \\end{aligned} \\]\u4e8e\u662f\uff0c\u674e\u4ee3\u6570\u4e0e\u674e\u7fa4\u7684\u5173\u7cfb:
\\[ s=\\mathrm{e}^\\sigma, R=\\exp(\\phi^\\wedge), t=J_s\\rho. \\] \\[ \\frac{\\partial\\boldsymbol{Sp}}{\\partial\\boldsymbol{\\zeta}}=\\begin{bmatrix}\\boldsymbol{I}&-\\boldsymbol{q}^\\wedge&\\boldsymbol{q}\\\\\\boldsymbol{0}^\\mathrm{T}&\\boldsymbol{0}^\\mathrm{T}&0\\end{bmatrix}. \\]"},{"location":"AI/SLAM14/#47","title":"4.7 \u4e60\u9898","text":"TODO
"},{"location":"AI/SLAM14/#5","title":"5 \u76f8\u673a\u4e0e\u56fe\u50cf","text":"\u53bb\u6389\u8d1f\u53f7:
\\[ \\frac Zf=\\frac X{X^{\\prime}}=\\frac Y{Y^{\\prime}}. \\] \\[ \\begin{aligned}X'&=f\\frac{X}{Z}\\\\Y'&=f\\frac{Y}{Z}\\end{aligned}. \\]\u8fd8\u6709\u4e00\u4e2a\u50cf\u7d20\u5750\u6807\u7cfb\uff0cu \u8f74\u4e0e x \u8f74\u5e73\u884c\uff0cv \u8f74\u4e0e y \u8f74\u5e73\u884c:
\\[ \\begin{cases}u=\\alpha X'+c_x\\\\[2ex]v=\\beta Y'+c_y\\end{cases}. \\] \\[ \\begin{cases}u=f_x\\frac{X}{Z}+c_x\\\\\\\\v=f_y\\frac{Y}{Z}+c_y\\end{cases}. \\] \\[ Z\\begin{pmatrix}u\\\\\\\\v\\\\\\\\1\\end{pmatrix}=\\begin{pmatrix}f_x&0&c_x\\\\0&f_y&c_y\\\\\\\\0&0&1\\end{pmatrix}\\begin{pmatrix}X\\\\\\\\Y\\\\\\\\Z\\end{pmatrix}\\overset{\\text{def}}{=}\\boldsymbol{KP}. \\]\u6700\u4e2d\u95f4\u7684\u77e9\u9635\u79f0\u4e3a\u76f8\u673a\u7684\u5185\u53c2\u6570\uff08Camera Inrinsics\uff09\u77e9\u9635 \\(\\displaystyle \\boldsymbol{K}\\)\u3002 \u6807\u5b9a: \u786e\u5b9a\u76f8\u673a\u7684\u5185\u53c2
\\[ Z\\boldsymbol{P}_{uv}=Z\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}=\\boldsymbol{K}\\left(\\boldsymbol{R}\\boldsymbol{P}_\\mathrm{w}+\\boldsymbol{t}\\right)=\\boldsymbol{K}\\boldsymbol{T}\\boldsymbol{P}_\\mathrm{w}. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{R},\\boldsymbol{t}\\) \u53c8\u79f0\u4e3a\u76f8\u673a\u7684\u5916\u53c2\u6570\uff08Camera Extrinsics\uff09
\\[ (\\boldsymbol{RP_\\mathrm{w}}+\\boldsymbol{t})=\\underbrace{[X,Y,Z]^\\mathrm{T}}_{\\text{\u76f8\u673a\u5750\u6807}}\\to\\underbrace{[X/Z,Y/Z,1]^\\mathrm{T}}_{\\text{\u5f52\u4e00\u5316\u5750\u6807}} . \\]\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u627e\u5230\u4e00\u4e2a\u70b9\u5728\u50cf\u7d20\u5e73\u9762\u4e0a\u7684\u6b63\u786e\u4f4d\u7f6e:
\u8fd8\u6709\u5f88\u591a\u7684\u76f8\u673a\u6a21\u578b\u6bd4\u5982: \u4eff\u5c04\u6a21\u578b\uff0c\u900f\u89c6\u6a21\u578b\u3002
\u603b\u7ed3\u4e00\u4e0b\u5355\u76ee\u76f8\u673a\u7684\u6210\u50cf\u8fc7\u7a0b:
\u4e24\u8005\u4e4b\u95f4\u7684\u8ddd\u79bb\u79f0\u4e3a\u53cc\u76ee\u76f8\u673a\u7684\u57fa\u7ebf
\\[ z=\\frac{fb}{d},\\quad d\\stackrel{\\mathrm{def}}{=}u_{\\mathrm{L}}-u_{\\mathrm{R}}. \\]TODO
"},{"location":"AI/SLAM14/#532","title":"5.3.2 \u56fe\u50cf\u53bb\u7578\u53d8","text":"TODO
"},{"location":"AI/SLAM14/#54-3-d","title":"5.4 \u5b9e\u8df5: 3 D \u89c6\u89c9","text":""},{"location":"AI/SLAM14/#541","title":"5.4.1 \u53cc\u76ee\u89c6\u89c9","text":"TODO
"},{"location":"AI/SLAM14/#542-rgb-d","title":"5.4.2 RGB-D \u89c6\u89c9","text":""},{"location":"AI/SLAM14/#55","title":"5.5 \u4e60\u9898","text":""},{"location":"AI/SLAM14/#6","title":"6 \u975e\u7ebf\u6027\u4f18\u5316","text":"\u524d\u9762\u6211\u4eec\u5df2\u7ecf\u641e\u6e05\u695a\u4e86\u8fd0\u52a8\u65b9\u7a0b\u548c\u89c2\u6d4b\u65b9\u7a0b\u7684\u6765\u6e90\uff0c\u73b0\u5728\u6211\u4eec\u5f00\u59cb\u8ba8\u8bba\u566a\u58f0\u3002
"},{"location":"AI/SLAM14/#61","title":"6.1 \u72b6\u6001\u4f30\u8ba1\u95ee\u9898","text":""},{"location":"AI/SLAM14/#611","title":"6.1.1 \u6279\u91cf\u72b6\u6001\u4f30\u8ba1\u4e0e\u6700\u5927\u540e\u9a8c\u4f30\u8ba1","text":"\\[ \\begin{cases}\\boldsymbol{x}_k=f\\left(\\boldsymbol{x}_{k-1},\\boldsymbol{u}_k\\right)+\\boldsymbol{w}_k\\\\\\boldsymbol{z}_{k,j}=h\\left(\\boldsymbol{y}_j,\\boldsymbol{x}_k\\right)+\\boldsymbol{v}_{k,j}\\end{cases}. \\] \\[ s\\boldsymbol{z}_{k,j}=\\boldsymbol{K}(R_k\\boldsymbol{y}_j+\\boldsymbol{t}_k). \\]\u5176\u4e2d \\(\\displaystyle s\\) \u4e3a\u50cf\u7d20\u70b9\u7684\u8ddd\u79bb\u3002 \u6211\u4eec\u901a\u5e38\u5047\u8bbe\u566a\u58f0\u9879\u6ee1\u8db3\u96f6\u5747\u503c\u7684\u9ad8\u65af\u5206\u5e03:
\\[ \\boldsymbol{w}_k\\sim\\mathcal{N}\\left(\\boldsymbol{0},\\boldsymbol{R}_k\\right),\\boldsymbol{v}_k\\sim\\mathcal{N}\\left(\\boldsymbol{0},\\boldsymbol{Q}_{k,j}\\right). \\]\u6709\u4e24\u79cd\u65b9\u6cd5\u6765\u89e3\u51b3\u72b6\u6001\u4f30\u8ba1\u95ee\u9898:
\u53ef\u4ee5\u5148\u6c42\u4e00\u4e2a\u72b6\u6001\u6700\u4f18\u4f30\u8ba1:
\\[ (\\boldsymbol{x},\\boldsymbol{y})^*_{\\mathrm{MAP}}=\\arg\\max P(\\boldsymbol{x},\\boldsymbol{y}|\\boldsymbol{z},\\boldsymbol{u})=\\arg\\max P(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y})P(\\boldsymbol{x},\\boldsymbol{y}). \\]\u6c42\u89e3\u6700\u5927\u540e\u9a8c\u6982\u7387\u7b49\u4ef7\u4e8e\u6700\u5927\u5316\u4f3c\u7136\u548c\u5148\u9a8c\u7684\u4e58\u79ef\u3002 \u4f46\u5982\u679c\u6ca1\u6709\u7684\u5148\u9a8c\uff0c\u90a3\u4e48\u53ef\u4ee5\u6c42\u89e3\u6700\u5927\u4f3c\u7136\u4f30\u8ba1 (Maximize Likelihood Estimation\uff0c MLE):
\\[ (\\boldsymbol{x},\\boldsymbol{y})^*{}_{\\mathrm{MLE}}=\\arg\\max P(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y}). \\]\u6700\u5927\u4f3c\u7136\u4f30\u8ba1: \u5728\u4ec0\u4e48\u6837\u7684\u72b6\u6001\u4e0b\uff0c\u6700\u53ef\u80fd\u4ea7\u751f\u73b0\u5728\u89c2\u6d4b\u5230\u7684\u6570\u636e\u3002
"},{"location":"AI/SLAM14/#612","title":"6.1.2 \u6700\u5c0f\u4e8c\u4e58\u7684\u5f15\u51fa","text":"\u5bf9\u4e8e\u67d0\u4e00\u6b21\u89c2\u6d4b:
\\[ z_{k,j}=h\\left(y_{j},x_{k}\\right)+v_{k,j}, \\] \\[ P(\\boldsymbol{z}_{j,k}|\\boldsymbol{x}_k,\\boldsymbol{y}_j)=N\\left(h(\\boldsymbol{y}_j,\\boldsymbol{x}_k),\\boldsymbol{Q}_{k,j}\\right). \\]\u53ef\u4ee5\u4f7f\u7528\u6700\u5c0f\u5316\u8d1f\u5bf9\u6570\u6765\u6c42\u4e00\u4e2a\u9ad8\u65af\u5206\u5e03\u7684\u6700\u5927\u4f3c\u7136\u3002
\\[ P\\left(\\boldsymbol{x}\\right)=\\frac{1}{\\sqrt{\\left(2\\pi\\right)^{N}\\det\\left(\\boldsymbol{\\Sigma}\\right)}}\\exp\\left(-\\frac{1}{2}(\\boldsymbol{x}-\\boldsymbol{\\mu})^{\\mathrm{T}}\\boldsymbol{\\Sigma}^{-1}\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right)\\right). \\] \\[ -\\ln\\left(P\\left(\\boldsymbol{x}\\right)\\right)=\\frac12\\ln\\left(\\left(2\\pi\\right)^N\\det\\left(\\boldsymbol{\\Sigma}\\right)\\right)+\\frac12\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right)^\\mathrm{T}\\boldsymbol{\\Sigma}^{-1}\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right). \\] \\[ \\begin{aligned} (x_{k},y_{j})^{*}& =\\arg\\max\\mathcal{N}(h(\\boldsymbol{y}_{j},\\boldsymbol{x}_{k}),\\boldsymbol{Q}_{k,j}) \\\\ &=\\arg\\min\\left(\\left(\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right)\\right)^\\mathrm{T}\\boldsymbol{Q}_{k,j}^{-1}\\left(\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right)\\right)\\right). \\end{aligned} \\]\u8be5\u5f0f\u7b49\u4ef7\u4e8e\u6700\u5c0f\u5316\u566a\u58f0\u9879\u7684\u4e00\u4e2a\u4e8c\u6b21\u578b\uff0c\u9a6c\u54c8\u62c9\u8bfa\u6bd4\u65af\u8ddd\u79bb (Mahalanobis distance)\u3002\u5176\u4e2d \\(\\displaystyle \\boldsymbol{Q}_{k,j}^{-1}\\) \u53eb\u4fe1\u606f\u77e9\u9635\uff0c\u5373\u9ad8\u65af\u5206\u5e03\u534f\u65b9\u5dee\u77e9\u9635\u4e4b\u9006\u3002 \u5047\u8bbe\u5404\u4e2a\u65f6\u523b\u7684\u8f93\u5165\u548c\u89c2\u6d4b\u90fd\u662f\u72ec\u7acb\u7684\uff0c\u90a3\u4e48:
\\[ P\\left(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y}\\right)=\\prod_kP\\left(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k\\right)\\prod_{k,j}P\\left(\\boldsymbol{z}_{k,j}|\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right), \\] \\[ \\begin{align} e_{u,k} &=\\boldsymbol{x}_k-f\\left(\\boldsymbol{x}_{k-1},\\boldsymbol{u}_k\\right) \\\\ e_{z,j,k} &=\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right), \\end{align} \\] \\[ \\min J(\\boldsymbol{x},\\boldsymbol{y})=\\sum_{k}\\boldsymbol{e}_{\\boldsymbol{u},k}^{\\mathrm{T}}\\boldsymbol{R}_{k}^{-1}\\boldsymbol{e}_{\\boldsymbol{u},k}+\\sum_{k}\\sum_{j}\\boldsymbol{e}_{\\boldsymbol{z},k,j}^{\\mathrm{T}}\\boldsymbol{Q}_{k,j}^{-1}\\boldsymbol{e}_{\\boldsymbol{z},k,j}. \\]\u8fd9\u6837\u5c31\u5f97\u5230\u4e86\u4e00\u4e2a\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898 (Least Square Problem)
\u8003\u8651\u4e00\u4e2a\u975e\u5e38\u7b80\u5355\u7684\u79bb\u6563\u65f6\u95f4\u7cfb\u7edf:
\\[ \\begin{aligned}&x_{k}=x_{k-1}+u_{k}+w_{k},&&\\boldsymbol{w}_{k}\\sim\\mathcal{N}\\left(0,\\boldsymbol{Q}_{k}\\right)\\\\&\\boldsymbol{z}_{k}=\\boldsymbol{x}_{k}+\\boldsymbol{n}_{k},&&\\boldsymbol{n}_{k}\\sim\\mathcal{N}\\left(0,\\boldsymbol{R}_{k}\\right)\\end{aligned} \\] \\[ \\begin{gathered} x_{map}^{*} =\\arg\\max P(\\boldsymbol{x}|\\boldsymbol{u},\\boldsymbol{z})=\\arg\\max P(\\boldsymbol{u},\\boldsymbol{z}|\\boldsymbol{x}) \\\\ =\\prod_{k=1}^3P(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k)\\prod_{k=1}^3P(\\boldsymbol{z}_k|\\boldsymbol{x}_k), \\end{gathered} \\]\u800c\u5bf9\u4e8e\u5177\u4f53\u7684\u6bcf\u4e00\u9879\uff0c\u6211\u4eec\u6709:
\\[ P(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k)=\\mathcal{N}(\\boldsymbol{x}_k-\\boldsymbol{x}_{k-1},\\boldsymbol{Q}_k), \\] \\[ P\\left(\\boldsymbol{z}_{k}|\\boldsymbol{x}_{k}\\right)=\\mathcal{N}\\left(\\boldsymbol{x}_{k},\\boldsymbol{R}_{k}\\right). \\]\u4e8e\u662f\uff0c\u6211\u4eec\u53ef\u4ee5\u6784\u5efa\u8bef\u5dee\u53d8\u91cf:
\\[ e_{\\boldsymbol{u},k}=\\boldsymbol{x}_k-\\boldsymbol{x}_{k-1}-\\boldsymbol{u}_k,\\quad\\boldsymbol{e}_{z,k}=\\boldsymbol{z}_k-\\boldsymbol{x}_k, \\]\u4e8e\u662f\u6700\u5c0f\u4e8c\u4e58\u7684\u76ee\u6807\u51fd\u6570\u4e3a:
\\[ \\min\\sum_{k=1}^{3}e_{u,k}^{\\mathrm{T}}Q_{k}^{-1}e_{u,k}+\\sum_{k=1}^{3}e_{z,k}^{\\mathrm{T}}R_{k}^{-1}e_{z,k}. \\]\u5b9a\u4e49\u5411\u91cf \\(\\displaystyle \\boldsymbol{y} = [\\boldsymbol{u},\\boldsymbol{z}]^\\mathrm{T}\\)
\\[ y-Hx=e\\sim\\mathcal{N}(\\mathbf{0},\\boldsymbol{\\Sigma}). \\] \\[ H=\\begin{bmatrix}1&-1&0&0\\\\0&1&-1&0\\\\0&0&1&-1\\\\\\hline0&1&0&0\\\\0&0&1&0\\\\0&0&0&1\\end{bmatrix}, \\]\u4e14 \\(\\displaystyle \\Sigma = diag(\\boldsymbol{Q_{1}},\\boldsymbol{Q_{2}},\\boldsymbol{Q_{3}},\\boldsymbol{R_{1}},\\boldsymbol{R_{2}},\\boldsymbol{R_{3}})\\)\u3002 \u95ee\u9898\u5c31\u8f6c\u5316\u6210:
\\[ x_{\\mathrm{map}}^*=\\arg\\min e^{\\mathrm{T}}\\Sigma^{-1}e, \\]\u5b83\u7684\u552f\u4e00\u89e3\u662f:
\\[ x_{\\mathrm{map}}^{*}=(H^{\\mathrm{T}}\\Sigma^{-1}H)^{-1}H^{\\mathrm{T}}\\Sigma^{-1}y. \\]"},{"location":"AI/SLAM14/#62","title":"6.2 \u975e\u7ebf\u6027\u6700\u5c0f\u4e8c\u4e58","text":"\u5148\u8003\u8651\u4e00\u4e2a\u7b80\u5355\u7684\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898:
\\[ \\min_{x}F(x)=\\frac12\\|f\\left(x\\right)\\|_{2}^{2}.` \\]\u5bf9\u4e8e\u4e0d\u65b9\u4fbf\u76f4\u63a5\u6c42\u89e3\u7684\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fed\u4ee3\u7684\u65b9\u5f0f\uff0c\u4ece\u4e00\u4e2a\u521d\u59cb\u503c\u51fa\u53d1\uff0c\u4e0d\u65ad\u5730\u66f4\u65b0\u5f53\u524d\u7684\u4f18\u5316\u53d8\u91cf\uff0c\u4f7f\u76ee\u6807\u51fd\u6570\u4e0b\u964d:
\u4e0b\u9762\u662f\u4e00\u4e9b\u5e7f\u6cdb\u4f7f\u7528\u7684\u7ed3\u679c\u3002
"},{"location":"AI/SLAM14/#621","title":"6.2.1 \u4e00\u9636\u548c\u4e8c\u9636\u68af\u5ea6\u6cd5","text":"\u4f7f\u7528\u6cf0\u52d2\u5c55\u5f00:
\\[ F(\\boldsymbol{x}_k+\\Delta\\boldsymbol{x}_k)\\approx F(\\boldsymbol{x}_k)+\\boldsymbol{J}\\left(\\boldsymbol{x}_k\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}_k+\\frac{1}{2}\\Delta\\boldsymbol{x}_k^\\mathrm{T}\\boldsymbol{H}(\\boldsymbol{x}_k)\\Delta\\boldsymbol{x}_k. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{J}(x_{k})\\) \u662f \\(\\displaystyle F(x)\\) \u5173\u4e8e \\(\\displaystyle x\\) \u7684\u4e00\u9636\u5bfc\u6570\uff08\u68af\u5ea6\u3001\u96c5\u53ef\u6bd4\u77e9\u9635\uff09\uff0c\\(\\displaystyle \\boldsymbol{H}\\) \u662f\u4e8c\u9636\u5bfc\u6570\uff08\u6d77\u585e\u77e9\u9635\uff09\u3002
\\[ \\Delta\\boldsymbol{x}^*=-\\boldsymbol{J}(\\boldsymbol{x}_k). \\] \\[ \\Delta\\boldsymbol{x}^*=\\arg\\min\\left(F\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}+\\frac{1}{2}\\Delta\\boldsymbol{x}^\\mathrm{T}\\boldsymbol{H}\\Delta\\boldsymbol{x}\\right). \\]\u5bf9 \\(\\displaystyle \\Delta x\\) \u6c42\u5bfc\uff0c\u5e76\u4ee4\u5b83\u7b49\u4e8e\u96f6\uff0c\u5f97\u5230:
\\[ J+H\\Delta x=\\mathbf{0}\\Rightarrow H\\Delta x=-J. \\]\u8fd9\u4e2a\u65b9\u6cd5\u53c8\u53eb\u725b\u987f\u6cd5\u3002
"},{"location":"AI/SLAM14/#622","title":"6.2.2 \u9ad8\u65af\u725b\u987f\u6cd5","text":"\u6362\u4e00\u4e2a\u51fd\u6570\u5c55\u5f00:
\\[ f\\left(x+\\Delta x\\right)\\approx f\\left(x\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}. \\] \\[ \\Delta x^{*}=\\arg\\min_{\\Delta x}\\frac{1}{2}\\Big\\|f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}\\Big\\|^{2}. \\] \\[ \\begin{aligned} \\frac12\\left\\|f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\right\\|^2& =\\frac12\\Big(f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\Big)^\\mathrm{T}\\Big(f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\Big) \\\\ &=\\frac12\\left(\\|f(\\boldsymbol{x})\\|_2^2+2f\\left(\\boldsymbol{x}\\right)\\boldsymbol{J}(\\boldsymbol{x})^\\intercal\\Delta\\boldsymbol{x}+\\Delta\\boldsymbol{x}^\\intercal\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}(\\boldsymbol{x})^\\intercal\\Delta\\boldsymbol{x}\\right). \\end{aligned} \\] \\[ \\boldsymbol{J}(\\boldsymbol{x})f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}^\\mathrm{T}\\left(\\boldsymbol{x}\\right)\\Delta\\boldsymbol{x}=\\boldsymbol{0}. \\] \\[ \\underbrace{\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}^{\\intercal}}_{\\boldsymbol{H}(\\boldsymbol{x})}\\left(\\boldsymbol{x}\\right)\\Delta\\boldsymbol{x}=\\underbrace{-\\boldsymbol{J}(\\boldsymbol{x})f\\left(\\boldsymbol{x}\\right)}_{\\boldsymbol{g}(\\boldsymbol{x})}. \\]\u589e\u91cf\u65b9\u7a0b or Gauss-Newton equation or Normal equation
\\[ H\\Delta x=g. \\]\u6c42\u89e3\u589e\u91cf\u65b9\u7a0b\u662f\u6574\u4e2a\u4f18\u5316\u95ee\u9898\u7684\u6838\u5fc3\u6240\u5728 \u603b\u7ed3\u4e00\u4e0b:
Damped Newton Method Trust Region Trust Region Method
\\[ \\rho=\\frac{f\\left(\\boldsymbol{x}+\\Delta\\boldsymbol{x}\\right)-f\\left(\\boldsymbol{x}\\right)}{\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\intercal}\\Delta\\boldsymbol{x}}. \\]\u6846\u67b6:
\u8fd9\u662f\u5e26\u4e0d\u7b49\u5f0f\u7ea6\u675f\u7684\u4f18\u5316\u95ee\u9898:
\\[ \\mathcal{L}(\\Delta\\boldsymbol{x}_{k},\\lambda)=\\frac{1}{2}\\left\\|f\\left(\\boldsymbol{x}_{k}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}_{k}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}_{k}\\right\\|^{2}+\\frac{\\lambda}{2}\\left(\\left\\|\\boldsymbol{D}\\Delta\\boldsymbol{x}_{k}\\right\\|^{2}-\\mu\\right). \\] \\[ (H+\\lambda D^\\mathrm{T}D) \\Delta x_k=g. \\]"},{"location":"AI/SLAM14/#63","title":"6.3 \u5b9e\u8df5: \u66f2\u7ebf\u62df\u5408\u95ee\u9898","text":""},{"location":"AI/SLAM14/#631","title":"6.3.1 \u624b\u5199\u9ad8\u65af\u725b\u987f\u6cd5","text":"TODO
"},{"location":"AI/SLAM14/#632-ceres","title":"6.3.2 \u4f7f\u7528 Ceres \u8fdb\u884c\u66f2\u7ebf\u62df\u5408","text":"TODO
"},{"location":"AI/SLAM14/#633-g2o","title":"6.3.3 \u4f7f\u7528 g2o\u8fdb\u884c\u66f2\u7ebf\u62df\u5408","text":"TODO
"},{"location":"AI/SLAM14/#7-1","title":"7 \u89c6\u89c9\u91cc\u7a0b\u8ba1 1","text":""},{"location":"AI/SLAM14/#71","title":"7.1 \u7279\u5f81\u70b9\u6cd5","text":"data association Brute-Force Matcher
TODO
"},{"location":"AI/SLAM14/#722-orb","title":"7.2.2 \u624b\u5199 ORB \u7279\u5f81","text":""},{"location":"AI/SLAM14/#723","title":"7.2.3 \u8ba1\u7b97\u76f8\u673a\u8fd0\u52a8","text":"\u6210\u6295\u5f71\u5173\u7cfb:\u5c3a\u5ea6\u610f\u4e49\u4e0b\u76f8\u7b49 (equal up to scale)
\\[ sp\\simeq p. \\] \\[ p_1\\simeq KP,\\quad p_2\\simeq K\\left(RP+t\\right). \\] \\[ x_1=K^{-1}p_1,\\quad x_2=K^{-1}p_2. \\] \\[ x_2\\simeq Rx_1+t. \\] \\[ t^{\\wedge}x_{2}\\simeq t^{\\wedge}Rx_{1}. \\] \\[ x_2^\\mathrm{T}t^\\wedge x_2\\simeq x_2^\\mathrm{T}t^\\wedge Rx_1. \\] \\[ x_2^\\mathrm{T}t^\\wedge Rx_1=0. \\] \\[ p_2^\\mathrm{T}K^{-\\mathrm{T}}t^\\wedge RK^{-1}p_1=0. \\]\u5bf9\u6781\u7ea6\u675f
\\[ E=t^{\\wedge}R,\\quad F=K^{-\\mathrm{T}}EK^{-1},\\quad x_{2}^{\\mathrm{T}}Ex_{1}=p_{2}^{\\mathrm{T}}Fp_{1}=0. \\]\u672c\u8d28\u77e9\u9635: \\(\\displaystyle E=t^{\\wedge}R\\)
\u6211\u4eec\u628a\u6240\u6709\u70b9\u90fd\u653e\u5230\u4e00\u4e2a\u65b9\u7a0b\u4e2d\uff0c\u53d8\u6210\u7ebf\u6027\u65b9\u7a0b\u7ec4:
\\[ \\begin{pmatrix}u_2^1u_1^1&u_2^1v_1^1&u_2^1&v_2^1u_1^1&v_2^1v_1^1&v_2^1&u_1^1&v_1^1&1\\\\u_2^2u_1^2&u_2^2v_1^2&u_2^2&v_2^2u_1^2&v_2^2v_1^2&v_2^2&u_1^2&v_1^2&1\\\\\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots\\\\u_2^8u_1^8&u_2^8v_1^8&u_2^8&v_2^8u_1^8&v_2^8u_1^8&u_1^8&v_1^8&1\\end{pmatrix}\\begin{pmatrix}e_1\\\\e_2\\\\e_3\\\\e_4\\\\e_5\\\\e_6\\\\e_7\\\\e_8\\\\e_9\\end{pmatrix}=0. \\] \\[ E=U\\Sigma V^{\\mathrm{T}}, \\] \\[ \\begin{aligned}&t_{1}^{\\wedge}=UR_{Z}(\\frac{\\pi}{2})\\Sigma U^{\\mathrm{T}},\\quad R_{1}=UR_{Z}^{\\mathrm{T}}(\\frac{\\pi}{2})V^{\\mathrm{T}}\\\\&t_{2}^{\\wedge}=UR_{Z}(-\\frac{\\pi}{2})\\Sigma U^{\\mathrm{T}},\\quad R_{2}=UR_{Z}^{\\mathrm{T}}(-\\frac{\\pi}{2})V^{\\mathrm{T}}.\\end{aligned} \\] \\[ \\boldsymbol{E}=\\boldsymbol{U}\\mathrm{diag}(\\frac{\\sigma_1+\\sigma_2}2,\\frac{\\sigma_1+\\sigma_2}2,0)\\boldsymbol{V}^\\mathrm{T}. \\]"},{"location":"AI/SLAM14/#733","title":"7.3.3 \u5355\u5e94\u77e9\u9635","text":"Homography
"},{"location":"AI/SLAM14/#8-2","title":"8 \u89c6\u89c9\u91cc\u7a0b\u8ba1 2","text":""},{"location":"AI/SLAM14/#81","title":"8.1 \u76f4\u63a5\u6cd5\u7684\u5f15\u51fa","text":"vector<Point2f> pt1, pt2;\nfor (auto &kp: kp1) pt1.push_back(kp.pt);\nvector<uchar> status;\nvector<float> error;\ncv::calcOpticalFlowPyrLK(img1, img2, pt1, pt2, status, error);\n
"},{"location":"AI/SLAM14/#832","title":"8.3.2 \u7528\u9ad8\u65af\u725b\u987f\u6cd5\u5b9e\u73b0\u5149\u6d41","text":"\u5355\u5c42\u5149\u6d41 TODO
\\[ \\min_{\\Delta x,\\Delta y}\\left\\|\\boldsymbol{I}_1\\left(x,y\\right)-\\boldsymbol{I}_2\\left(x+\\Delta x,y+\\Delta y\\right)\\right\\|_2^2. \\]\u591a\u5c42\u5149\u6d41 - \u7531\u7c97\u81f3\u7cbe\uff08Coarse-to-fine\uff09
"},{"location":"AI/SLAM14/#833","title":"8.3.3 \u5149\u6d41\u5b9e\u8df5\u5c0f\u7ed3","text":""},{"location":"AI/SLAM14/#84","title":"8.4 \u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#841","title":"8.4.1 \u76f4\u63a5\u6cd5\u7684\u63a8\u5bfc","text":"\\[ \\boldsymbol{p}_1=\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}_1=\\frac{1}{Z_1}\\boldsymbol{K}\\boldsymbol{P}, \\] \\[ \\boldsymbol{p}_{2}=\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}_{2}=\\frac{1}{Z_{2}}\\boldsymbol{K}\\left(\\boldsymbol{R}\\boldsymbol{P}+\\boldsymbol{t}\\right)=\\frac{1}{Z_{2}}\\boldsymbol{K}\\left(\\boldsymbol{T}\\boldsymbol{P}\\right)_{1:3}. \\] \\[ e=\\boldsymbol{I}_1\\left(\\boldsymbol{p}_1\\right)-\\boldsymbol{I}_2\\left(\\boldsymbol{p}_2\\right). \\] \\[ \\min_{T}J\\left(T\\right)=\\left\\|e\\right\\|^{2}. \\] \\[ \\min_{\\boldsymbol{T}}J\\left(\\boldsymbol{T}\\right)=\\sum_{i=1}^{N}e_{i}^{\\mathrm{T}}e_{i},\\quad e_{i}=\\boldsymbol{I}_{1}\\left(\\boldsymbol{p}_{1,i}\\right)-\\boldsymbol{I}_{2}\\left(\\boldsymbol{p}_{2,i}\\right). \\] \\[ \\begin{aligned}&q=TP,\\\\&\\boldsymbol{u}=\\frac{1}{Z_{2}}Kq.\\end{aligned} \\] \\[ e(T)=I_1(p_1)-I_2(u), \\] \\[ \\frac{\\partial e}{\\partial\\boldsymbol{T}}=\\frac{\\partial\\boldsymbol{I}_{2}}{\\partial\\boldsymbol{u}}\\frac{\\partial\\boldsymbol{u}}{\\partial\\boldsymbol{q}}\\frac{\\partial\\boldsymbol{q}}{\\partial\\delta\\boldsymbol{\\xi}}\\delta\\boldsymbol{\\xi}, \\] \\[ \\frac{\\partial\\boldsymbol{u}}{\\partial\\boldsymbol{q}}=\\begin{bmatrix}\\frac{\\partial u}{\\partial X}&\\frac{\\partial u}{\\partial Y}&\\frac{\\partial u}{\\partial Z}\\\\\\frac{\\partial v}{\\partial X}&\\frac{\\partial v}{\\partial Y}&\\frac{\\partial v}{\\partial Z}\\end{bmatrix}=\\begin{bmatrix}\\frac{f_x}{Z}&0&-\\frac{f_xX}{Z^2}\\\\0&\\frac{f_y}{Z}&-\\frac{f_yY}{Z^2}\\end{bmatrix}. \\] \\[ \\frac{\\partial\\boldsymbol{q}}{\\partial\\delta\\boldsymbol{\\xi}}=\\left[I,-\\boldsymbol{q}^{\\wedge}\\right]. \\] \\[ \\frac{\\partial\\boldsymbol{u}}{\\partial\\delta\\boldsymbol{\\xi}}=\\begin{bmatrix}\\frac{f_x}{Z}&0&-\\frac{f_xX}{Z^2}&-\\frac{f_xXY}{Z^2}&f_x+\\frac{f_xX^2}{Z^2}&-\\frac{f_xY}{Z}\\\\0&\\frac{f_y}{Z}&-\\frac{f_yY}{Z^2}&-f_y-\\frac{f_yY^2}{Z^2}&\\frac{f_yXY}{Z^2}&\\frac{f_yX}{Z}\\end{bmatrix}. \\] \\[ J=-\\frac{\\partial I_2}{\\partial u}\\frac{\\partial u}{\\partial\\delta\\xi}. \\]"},{"location":"AI/SLAM14/#842","title":"8.4.2 \u76f4\u63a5\u6cd5\u7684\u8ba8\u8bba","text":""},{"location":"AI/SLAM14/#85","title":"8.5 \u5b9e\u8df5: \u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#851","title":"8.5.1 \u5355\u5c42\u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#852","title":"8.5.2 \u591a\u5c42\u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#853","title":"8.5.3 \u7ed3\u679c\u8ba8\u8bba","text":"\u7ea6 3356 \u4e2a\u5b57 43 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 17 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/%E7%BB%9F%E8%AE%A1%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/#1","title":"1 \u7edf\u8ba1\u5b66\u4e60\u65b9\u6cd5\u6982\u8bba","text":""},{"location":"AI/%E7%BB%9F%E8%AE%A1%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/#11","title":"1.1 \u7edf\u8ba1\u5b66\u4e60","text":"\u7ea6 8852 \u4e2a\u5b57 167 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 44 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
This note is based on GitHub - DaizeDong/Stanford-CS231n-2021-and-2022: Notes and slides for Stanford CS231n 2021 & 2022 in English. I merged the contents together to get a better version. Assignments are not included. \u65af\u5766\u798fcs231n\u7684\u8bfe\u7a0b\u7b14\u8bb0(\u82f1\u6587\u7248\u672c\uff0c\u4e0d\u542b\u5b9e\u9a8c\u4ee3\u7801)\uff0c\u5c062021\u4e0e2022\u4e24\u5e74\u7684\u8bfe\u7a0b\u8fdb\u884c\u4e86\u5408\u5e76\uff0c\u5206\u4eab\u4ee5\u4f9b\u4ea4\u6d41\u3002 And I will add some blogs, articles and other understanding.
Topic Chapter Deep Learning Basics 2 - 4 Perceiving and Understanding the Visual World 5 - 12 Reconstructing and Interacting with the Visual World 13 - 16 Human-Centered Applications and Implications 17 - 18"},{"location":"AI/CS231n/CS231n_notes/#1-introduction","title":"1 - Introduction","text":"A brief history of computer vision & deep learning...
"},{"location":"AI/CS231n/CS231n_notes/#2-image-classification","title":"2 - Image Classification","text":"Image Classification: A core task in Computer Vision. The main drive to the progress of CV.
Challenges: Viewpoint variation, background clutter, illumination, occlusion, deformation, intra-class variation...
"},{"location":"AI/CS231n/CS231n_notes/#k-nearest-neighbor","title":"K Nearest Neighbor","text":"Hyperparameters: Distance metric (\\(p\\) norm), \\(k\\) number.
Choose hyperparameters using validation set.
Never use k-Nearest Neighbor with pixel distance.
"},{"location":"AI/CS231n/CS231n_notes/#linear-classifier","title":"Linear Classifier","text":"Pass...
"},{"location":"AI/CS231n/CS231n_notes/#3-loss-functions-and-optimization","title":"3 - Loss Functions and Optimization","text":""},{"location":"AI/CS231n/CS231n_notes/#loss-functions","title":"Loss Functions","text":"Dataset \\(\\big\\{(x_i,y_i)\\big\\}_{i=1}^N\\\\\\) Loss Function \\(L=\\frac{1}{N}\\sum_{i=1}^NL_i\\big(f(x_i,W),y_i\\big)\\\\\\) Loss Function with Regularization \\(L=\\frac{1}{N}\\sum_{i=1}^NL_i\\big(f(x_i,W),y_i\\big)+\\lambda R(W)\\\\\\)Motivation: Want to interpret raw classifier scores as probabilities.
Softmax Classifier \\(p_i=Softmax(y_i)=\\frac{\\exp(y_i)}{\\sum_{j=1}^N\\exp(y_j)}\\\\\\) Cross Entropy Loss \\(L_i=-y_i\\log p_i\\\\\\) Cross Entropy Loss with Regularization \\(L=-\\frac{1}{N}\\sum_{i=1}^Ny_i\\log p_i+\\lambda R(W)\\\\\\) "},{"location":"AI/CS231n/CS231n_notes/#optimization","title":"Optimization","text":""},{"location":"AI/CS231n/CS231n_notes/#sgd-with-momentum","title":"SGD with Momentum","text":"Problems that SGD can't handle:
Momentum: Build up \u201cvelocity\u201d \\(v_t\\) as a running mean of gradients.
SGD SGD + Momentum \\(x_{t+1}=x_t-\\alpha\\nabla f(x_t)\\) \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) Naive gradient descent. \\(\\rho\\) gives \"friction\", typically \\(\\rho=0.9,0.99,0.999,...\\)Nesterov Momentum: Use the derivative on point \\(x_t+\\rho v_t\\) as gradient instead point \\(x_t\\).
Momentum Nesterov Momentum \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t+\\rho v_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) Use gradient at current point. Look ahead for the gradient in velocity direction. "},{"location":"AI/CS231n/CS231n_notes/#adagrad-and-rmsprop","title":"AdaGrad and RMSProp","text":"AdaGrad: Accumulate squared gradient, and gradually decrease the step size.
RMSProp: Accumulate squared gradient while decaying former ones, and gradually decrease the step size. (\"Leaky AdaGrad\")
AdaGrad RMSProp \\(\\begin{align}\\text{Initialize:}&\\\\&r:=0\\\\\\text{Update:}&\\\\&r:=r+\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{\\nabla f(x_t)}{\\sqrt{r}}\\end{align}\\) \\(\\begin{align}\\text{Initialize:}&\\\\&r:=0\\\\\\text{Update:}&\\\\&r:=\\rho r+(1-\\rho)\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{\\nabla f(x_t)}{\\sqrt{r}}\\end{align}\\) Continually accumulate squared gradients. \\(\\rho\\) gives \"decay rate\", typically \\(\\rho=0.9,0.99,0.999,...\\)"},{"location":"AI/CS231n/CS231n_notes/#adam","title":"Adam","text":"Sort of like \"RMSProp + Momentum\".
Adam (simple version) Adam (full version) \\(\\begin{align}\\text{Initialize:}&\\\\&r_1:=0\\\\&r_2:=0\\\\\\text{Update:}&\\\\&r_1:=\\beta_1r_1+(1-\\beta_1)\\nabla f(x_t)\\\\&r_2:=\\beta_2r_2+(1-\\beta_2)\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{r_1}{\\sqrt{r_2}}\\end{align}\\) \\(\\begin{align}\\text{Initialize:}\\\\&r_1:=0\\\\&r_2:=0\\\\\\text{For }i\\text{:}\\\\&r_1:=\\beta_1r_1+(1-\\beta_1)\\nabla f(x_t)\\\\&r_2:=\\beta_2r_2+(1-\\beta_2)\\Big[\\nabla f(x_t)\\Big]^2\\\\&r_1'=\\frac{r_1}{1-\\beta_1^i}\\\\&r_2'=\\frac{r_2}{1-\\beta_2^i}\\\\&x_{t+1}=x_t-\\alpha\\frac{r_1'}{\\sqrt{r_2'}}\\end{align}\\) Build up \u201cvelocity\u201d for both gradient and squared gradient. Correct the \"bias\" that \\(r_1=r_2=0\\) for the first few iterations."},{"location":"AI/CS231n/CS231n_notes/#overview","title":"Overview","text":""},{"location":"AI/CS231n/CS231n_notes/#learning-rate-decay","title":"Learning Rate Decay","text":"Reduce learning rate at a few fixed points to get a better convergence over time.
\\(\\alpha_0\\) : Initial learning rate.
\\(\\alpha_t\\) : Learning rate in epoch \\(t\\).
\\(T\\) : Total number of epochs.
Method Equation Picture Step Reduce \\(\\alpha_t\\) constantly in a fixed step. Cosine \\(\\begin{align}\\alpha_t=\\frac{1}{2}\\alpha_0\\Bigg[1+\\cos(\\frac{t\\pi}{T})\\Bigg]\\end{align}\\) Linear \\(\\begin{align}\\alpha_t=\\alpha_0\\Big(1-\\frac{t}{T}\\Big)\\end{align}\\) Inverse Sqrt \\(\\begin{align}\\alpha_t=\\frac{\\alpha_0}{\\sqrt{t}}\\end{align}\\)High initial learning rates can make loss explode, linearly increasing learning rate in the first few iterations can prevent this.
Learning rate warm up:
Empirical rule of thumb: If you increase the batch size by \\(N\\), also scale the initial learning rate by \\(N\\) .
"},{"location":"AI/CS231n/CS231n_notes/#second-order-optimization","title":"Second-Order Optimization","text":"Picture Time Complexity Space Complexity First Order \\(O(n)\\) \\(O(n)\\) Second Order \\(O(n^2)\\) with BGFS optimization \\(O(n)\\) with L-BGFS optimizationL-BGFS : Limited memory BGFS.
Motivation: Inducted bias can appear to be high when using human-designed features.
Activation: Sigmoid, tanh, ReLU, LeakyReLU...
Architecture: Input layer, hidden layer, output layer.
Do not use the size of a neural network as the regularizer. Use regularization instead!
Gradient Calculation: Computational Graph + Backpropagation.
"},{"location":"AI/CS231n/CS231n_notes/#backpropagation","title":"Backpropagation","text":"Using Jacobian matrix to calculate the gradient of each node in a computation graph.
Suppose that we have a computation flow like this:
Input X Input W Output Y \\(X=\\begin{bmatrix}x_1\\\\x_2\\\\\\vdots\\\\x_n\\end{bmatrix}\\) \\(W=\\begin{bmatrix}w_{11}&w_{12}&\\cdots&w_{1n}\\\\w_{21}&w_{22}&\\cdots&w_{2n}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\w_{m1}&w_{m2}&\\cdots&w_{mn}\\end{bmatrix}\\) \\(Y=\\begin{bmatrix}y_1\\\\y_2\\\\\\vdots\\\\y_m\\end{bmatrix}\\) \\(n\\times 1\\) \\(m\\times n\\) \\(m\\times 1\\)After applying feed forward, we can calculate gradients like this:
Derivative Matrix of X Jacobian Matrix of X Derivative Matrix of Y \\(D_X=\\begin{bmatrix}\\frac{\\partial L}{\\partial x_1}\\\\\\frac{\\partial L}{\\partial x_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial x_n}\\end{bmatrix}\\) \\(J_X=\\begin{bmatrix}\\frac{\\partial y_1}{\\partial x_1}&\\frac{\\partial y_1}{\\partial x_2}&\\cdots&\\frac{\\partial y_1}{\\partial x_n}\\\\\\frac{\\partial y_2}{\\partial x_1}&\\frac{\\partial y_2}{\\partial x_2}&\\cdots&\\frac{\\partial y_2}{\\partial x_n}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial y_m}{\\partial x_1}&\\frac{\\partial y_m}{\\partial x_2}&\\cdots&\\frac{\\partial y_m}{\\partial x_n}\\end{bmatrix}\\) \\(D_Y=\\begin{bmatrix}\\frac{\\partial L}{\\partial y_1}\\\\\\frac{\\partial L}{\\partial y_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial y_m}\\end{bmatrix}\\) \\(n\\times 1\\) \\(m\\times n\\) \\(m\\times 1\\) Derivative Matrix of W Jacobian Matrix of W Derivative Matrix of Y \\(W=\\begin{bmatrix}\\frac{\\partial L}{\\partial w_{11}}&\\frac{\\partial L}{\\partial w_{12}}&\\cdots&\\frac{\\partial L}{\\partial w_{1n}}\\\\\\frac{\\partial L}{\\partial w_{21}}&\\frac{\\partial L}{\\partial w_{22}}&\\cdots&\\frac{\\partial L}{\\partial w_{2n}}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial L}{\\partial w_{m1}}&\\frac{\\partial L}{\\partial w_{m2}}&\\cdots&\\frac{\\partial L}{\\partial w_{mn}}\\end{bmatrix}\\) \\(J_W^{(k)}=\\begin{bmatrix}\\frac{\\partial y_k}{\\partial w_{11}}&\\frac{\\partial y_k}{\\partial w_{12}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{1n}}\\\\\\frac{\\partial y_k}{\\partial w_{21}}&\\frac{\\partial y_k}{\\partial w_{22}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{2n}}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial y_k}{\\partial w_{m1}}&\\frac{\\partial y_k}{\\partial w_{m2}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{mn}}\\end{bmatrix}\\)\\(J_W=\\begin{bmatrix}J_W^{(1)}&J_W^{(2)}&\\cdots&J_W^{(m)}\\end{bmatrix}\\) \\(D_Y=\\begin{bmatrix}\\frac{\\partial L}{\\partial y_1}\\\\\\frac{\\partial L}{\\partial y_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial y_m}\\end{bmatrix}\\) \\(m\\times n\\) \\(m\\times m\\times n\\) $ m\\times 1$For each element in \\(D_X\\) , we have:
\\(D_{Xi}=\\frac{\\partial L}{\\partial x_i}=\\sum_{j=1}^m\\frac{\\partial L}{\\partial y_j}\\frac{\\partial y_j}{\\partial x_i}\\\\\\)
"},{"location":"AI/CS231n/CS231n_notes/#5-convolutional-neural-networks","title":"5 - Convolutional Neural Networks","text":""},{"location":"AI/CS231n/CS231n_notes/#convolution-layer","title":"Convolution Layer","text":""},{"location":"AI/CS231n/CS231n_notes/#introduction","title":"Introduction","text":"Convolve a filter with an image: Slide the filter spatially within the image, computing dot products in each region.
Giving a \\(32\\times32\\times3\\) image and a \\(5\\times5\\times3\\) filter, a convolution looks like:
Convolve six \\(5\\times5\\times3\\) filters to a \\(32\\times32\\times3\\) image with step size \\(1\\), we can get a \\(28\\times28\\times6\\) feature:
With an activation function after each convolution layer, we can build the ConvNet with a sequence of convolution layers:
By changing the step size between each move for filters, or adding zero-padding around the image, we can modify the size of the output:
"},{"location":"AI/CS231n/CS231n_notes/#1times1-convolution-layer","title":"\\(1\\times1\\) Convolution Layer","text":"This kind of layer makes perfect sense. It is usually used to change the dimension (channel) of features.
A \\(1\\times1\\) convolution layer can also be treated as a full-connected linear layer.
"},{"location":"AI/CS231n/CS231n_notes/#summary_1","title":"Summary","text":"Input image size \\(W_1\\times H_1\\times C\\) filter size \\(F\\times F\\times C\\) filter number \\(K\\) stride \\(S\\) zero padding \\(P\\) Output output size \\(W_2\\times H_2\\times K\\) output width \\(W_2=\\frac{W_1-F+2P}{S}+1\\\\\\) output height \\(H_2=\\frac{H_1-F+2P}{S}+1\\\\\\) Parameters parameter number (weight) \\(F^2CK\\) parameter number (bias) \\(K\\)"},{"location":"AI/CS231n/CS231n_notes/#pooling-layer","title":"Pooling layer","text":"Make the representations smaller and more manageable.
An example of max pooling:
Input image size \\(W_1\\times H_1\\times C\\) spatial extent \\(F\\times F\\) stride \\(S\\) Output output size \\(W_2\\times H_2\\times C\\) output width \\(W_2=\\frac{W_1-F}{S}+1\\\\\\) output height \\(H_2=\\frac{H_1-F}{S}+1\\\\\\)"},{"location":"AI/CS231n/CS231n_notes/#convolutional-neural-networks-cnn","title":"Convolutional Neural Networks (CNN)","text":"CNN stack CONV, POOL, FC layers.
CNN Trends:
Historically architectures of CNN looked like:
where usually \\(m\\) is large, \\(0\\le n\\le5\\), \\(0\\le k\\le2\\).
Recent advances such as ResNet / GoogLeNet have challenged this paradigm.
"},{"location":"AI/CS231n/CS231n_notes/#6-cnn-architectures","title":"6 - CNN Architectures","text":"Best model in ImageNet competition:
"},{"location":"AI/CS231n/CS231n_notes/#alexnet","title":"AlexNet","text":"8 layers.
First use of ConvNet in image classification problem.
Filter size decreases in deeper layer.
Channel number increases in deeper layer.
"},{"location":"AI/CS231n/CS231n_notes/#vgg","title":"VGG","text":"19 layers. (also provide 16 layers edition)
Static filter size (\\(3\\times3\\)) in all layers:
Most memory is in early convolution layers.
Most parameter is in late FC layers.
"},{"location":"AI/CS231n/CS231n_notes/#googlenet","title":"GoogLeNet","text":"22 layers.
No FC layers, only 5M parameters. ( \\(8.3\\%\\) of AlexNet, \\(3.7\\%\\) of VGG )
Devise efficient \"inception module\".
"},{"location":"AI/CS231n/CS231n_notes/#inception-module","title":"Inception Module","text":"Design a good local network topology (network within a network) and then stack these modules on top of each other.
Naive Inception Module:
Inception Module with Dimension Reduction:
152 layers for ImageNet.
Devise \"residual connections\".
Use BN in place of dropout.
"},{"location":"AI/CS231n/CS231n_notes/#residual-connections","title":"Residual Connections","text":"Hypothesis: Deeper models have more representation power than shallow ones. But they are harder to optimize.
Solution: Use network layers to fit a residual mapping instead of directly trying to fit a desired underlying mapping.
It is necessary to use ReLU as activation function, in order to apply identity mapping when \\(F(x)=0\\) .
"},{"location":"AI/CS231n/CS231n_notes/#architecture_1","title":"Architecture","text":""},{"location":"AI/CS231n/CS231n_notes/#senet","title":"SENet","text":"Using ResNeXt-152 as a base architecture.
Add a \u201cfeature recalibration\u201d module. (adjust weights of each channel)
Using the global avg-pooling layer + FC layers to determine feature map weights.
"},{"location":"AI/CS231n/CS231n_notes/#improvements-of-resnet","title":"Improvements of ResNet","text":"Wide Residual Networks, ResNeXt, DenseNet, MobileNets...
"},{"location":"AI/CS231n/CS231n_notes/#other-interesting-networks","title":"Other Interesting Networks","text":"NASNet: Neural Architecture Search with Reinforcement Learning.
EfficientNet: Smart Compound Scaling.
"},{"location":"AI/CS231n/CS231n_notes/#7-training-neural-networks","title":"7 - Training Neural Networks","text":""},{"location":"AI/CS231n/CS231n_notes/#activation-functions","title":"Activation Functions","text":"Activation Usage Sigmoid, tanh Do not use. ReLU Use as default. Leaky ReLU, Maxout, ELU, SELU Replace ReLU to squeeze out some marginal gains. Swish No clear usage."},{"location":"AI/CS231n/CS231n_notes/#data-processing","title":"Data Processing","text":"Apply centralization and normalization before training.
In practice for pictures, usually we apply channel-wise centralization only.
"},{"location":"AI/CS231n/CS231n_notes/#weight-initialization","title":"Weight Initialization","text":"Assume that we have 6 layers in a network.
\\(D_i\\) : input size of layer \\(i\\)
\\(W_i\\) : weights in layer \\(i\\)
\\(X_i\\) : output after activation of layer \\(i\\), we have \\(X_i=g(Z_i)=g(W_iX_{i-1}+B_i)\\)
We initialize each parameter in \\(W_i\\) randomly in \\([-k_i,k_i]\\) .
Tanh Activation Output Distribution \\(k_i=0.01\\) \\(k_i=0.05\\) Xavier Initialization \\(k_i=\\frac{1}{\\sqrt{D_i}\\\\}\\)When \\(k_i=0.01\\), the variance keeps decreasing as the layer gets deeper. As a result, the output of each neuron in deep layer will all be 0. The partial derivative \\(\\frac{\\partial Z_i}{\\partial W_i}=X_{i-1}=0\\\\\\). (no gradient)
When \\(k_i=0.05\\), most neurons is saturated. The partial derivative \\(\\frac{\\partial X_i}{\\partial Z_i}=g'(Z_i)=0\\\\\\). (no gradient)
To solve this problem, We need to keep the variance same in each layer.
Assuming that \\(Var\\big(X_{i-1}^{(1)}\\big)=Var\\big(X_{i-1}^{(2)}\\big)=\\dots=Var\\big(X_{i-1}^{(D_i)}\\big)\\)
We have \\(Z_i=X_{i-1}^{(1)}W_i^{(:,1)}+X_{i-1}^{(2)}W_i^{(:,2)}+\\dots+X_{i-1}^{(D_i)}W_i^{(:,D_i)}=\\sum_{n=1}^{D_i}X_{i-1}^{(n)}W_i^{(:,n)}\\\\\\)
We want \\(Var\\big(Z_i\\big)=Var\\big(X_{i-1}^{(n)}\\big)\\)
Let's do some conduction:
\\(\\begin{aligned}Var\\big(Z_i\\big)&=Var\\Bigg(\\sum_{n=1}^{D_i}X_{i-1}^{(n)}W_i^{(:,n)}\\Bigg)\\\\&=D_i\\ Var\\Big(X_{i-1}^{(n)}W_i^{(:,n)}\\Big)\\\\&=D_i\\ Var\\Big(X_{i-1}^{(n)}\\Big)\\ Var\\Big(W_i^{(:,n)}\\Big)\\end{aligned}\\)
So \\(Var\\big(Z_i\\big)=Var\\big(X_{i-1}^{(n)}\\big)\\) only when \\(Var\\Big(W_i^{(:,n)}\\Big)=\\frac{1}{D_i}\\\\\\), that is to say \\(k_i=\\frac{1}{\\sqrt{D_i}}\\\\\\)
ReLU Activation Output Distribution Xavier Initialization \\(k_i=\\frac{1}{\\sqrt{D_i}\\\\}\\) Kaiming Initialization \\(k_i=\\sqrt{2D_i}\\)For ReLU activation, when using xavier initialization, there still exist \"variance decreasing\" problem.
We can use kaiming initialization instead to fix this.
"},{"location":"AI/CS231n/CS231n_notes/#batch-normalization","title":"Batch Normalization","text":"Force the inputs to be \"nicely scaled\" at each layer.
\\(N\\) : batch size
\\(D\\) : feature size
\\(x\\) : input with shape \\(N\\times D\\)
\\(\\gamma\\) : learnable scale and shift parameter with shape \\(D\\)
\\(\\beta\\) : learnable scale and shift parameter with shape \\(D\\)
The procedure of batch normalization:
Why scale: The constraint \"zero-mean, unit variance\" may be too hard.
Pros:
Cons:
Behaves differently during training and testing: this is a very common source of bugs!
"},{"location":"AI/CS231n/CS231n_notes/#transfer-learning","title":"Transfer Learning","text":"Train on a pre-trained model with other datasets.
An empirical suggestion:
very similar dataset very different dataset very little data Use Linear Classifier on top layer. You\u2019re in trouble\u2026 Try linear classifier from different stages. quite a lot of data Finetune a few layers. Finetune a larger number of layers."},{"location":"AI/CS231n/CS231n_notes/#regularization","title":"Regularization","text":""},{"location":"AI/CS231n/CS231n_notes/#common-pattern-of-regularization","title":"Common Pattern of Regularization","text":"Training: Add some kind of randomness. \\(y=f(x,z)\\)
Testing: Average out randomness (sometimes approximate). \\(y=f(x)=E_z\\big[f(x,z)\\big]=\\int p(z)f(x,z)dz\\\\\\)
"},{"location":"AI/CS231n/CS231n_notes/#regularization-term","title":"Regularization Term","text":"L2 regularization: \\(R(W)=\\sum_k\\sum_lW_{k,l}^2\\) (weight decay)
L1 regularization: \\(R(W)=\\sum_k\\sum_l|W_{k,l}|\\)
Elastic net : \\(R(W)=\\sum_k\\sum_l\\big(\\beta W_{k,l}^2+|W_{k,l}|\\big)\\) (L1+L2)
"},{"location":"AI/CS231n/CS231n_notes/#dropout","title":"Dropout","text":"Training: Randomly set some neurons to 0 with a probability \\(p\\) .
Testing: Each neuron multiplies by dropout probability \\(p\\) . (scale the output back)
More common: Scale the output with \\(\\frac{1}{p}\\) when training, keep the original output when testing.
Why dropout works:
See above.
"},{"location":"AI/CS231n/CS231n_notes/#data-augmentation","title":"Data Augmentation","text":"There also exists automatic data augmentation method using neural networks.
"},{"location":"AI/CS231n/CS231n_notes/#other-methods-and-summary","title":"Other Methods and Summary","text":"DropConnect: Drop connections between neurons.
Fractional Max Pooling: Use randomized pooling regions.
Stochastic Depth: Skip some layers in the network.
Cutout: Set random image regions to zero.
Mixup: Train on random blends of images.
Regularization Method Usage Dropout For large fully-connected layers. Batch Normalization & Data Augmentation Almost always a good idea. Cutout & Mixup For small classification datasets."},{"location":"AI/CS231n/CS231n_notes/#hyperparameter-tuning","title":"Hyperparameter Tuning","text":"Most Common Hyperparameters Less Sensitive Hyperparameters learning ratelearning rate decay scheduleweight decay setting of momentum...Tips on hyperparameter tuning:
Have a worker that continuously samples random hyperparameters and performs the optimization. During the training, the worker will keep track of the validation performance after every epoch, and writes a model checkpoint to a file.
Have a master that launches or kills workers across a computing cluster, and may additionally inspect the checkpoints written by workers and plot their training statistics.
"},{"location":"AI/CS231n/CS231n_notes/#common-procedures","title":"Common Procedures","text":"Turn off weight decay, sanity check loss at initialization \\(\\log(C)\\) for softmax with \\(C\\) classes.
Try to train to 100% training accuracy on a small sample of training data.
Fiddle with architecture, learning rate, weight initialization.
Use the architecture from the previous step, use all training data, turn on small weight decay, find a learning rate that makes the loss drop significantly within 100 iterations.
Good learning rates to try: \\(0.1,0.01,0.001,0.0001,\\dots\\)
Choose a few values of learning rate and weight decay around what worked from Step 3, train a few models for 1-5 epochs.\\
Good weight decay to try: \\(0.0001,0.00001,0\\)
Pick best models from Step 4, train them for longer (10-20 epochs) without learning rate decay.
CS231n Convolutional Neural Networks for Visual Recognition
Compute analytical gradient manually using \\(f_a'=\\frac{\\partial f(x)}{\\partial x}=\\frac{f(x-h)-f(x+h)}{2h}\\\\\\)
Get relative error between numerical gradient \\(f_n'\\) and analytical gradient \\(f_a'\\) using \\(E=\\frac{|f_n'-f_a'|}{\\max{|f_n'|,|f_a'|}}\\\\\\)
Relative Error Result \\(E>10^{-2}\\) Probably \\(f_n'\\) is wrong. \\(10^{-2}>E>10^{-4}\\) Not good, should check the gradient. \\(10^{-4}>E>10^{-6}\\) Okay for objectives with kinks. (e.g. ReLU)Not good for objectives with no kink. (e.g. softmax, tanh) \\(10^{-7}>E\\) Good.Tips on gradient checks:
For example, we have a layer with shape \\(128\\times13\\times13\\). We pick the 17th channel from all 128 channels. Then we run many pictures through the network. During each run we can find a maximal activation feature among all the \\(13\\times13\\) features in channel 17. We then record the corresponding picture patch for each maximal activation feature. At last, we visualize all picture patches for each feature.
This will help us find the relationship between each maximal activation feature and its corresponding picture patches.
(each row of the following picture represents a feature)
"},{"location":"AI/CS231n/CS231n_notes/#saliency-via-occlusion","title":"Saliency via Occlusion","text":"Mask part of the image before feeding to CNN, check how much predicted probabilities change.
"},{"location":"AI/CS231n/CS231n_notes/#saliency-via-backprop","title":"Saliency via Backprop","text":"Striving for Simplicity: The All Convolutional Net
Just like \"Maximally Activating Patches\", this could find the part of an image that a neuron responds to.
"},{"location":"AI/CS231n/CS231n_notes/#gradient-ascent","title":"Gradient Ascent","text":"Generate a synthetic image that maximally activates a neuron.
Objective: \\(\\max S_c(I)-\\lambda\\lVert I\\lVert^2\\)
Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps
"},{"location":"AI/CS231n/CS231n_notes/#adversarial-examples","title":"Adversarial Examples","text":"Find an fooling image that can make the network misclassify correctly-classified images when it is added to the image.
Given a CNN feature vector \\(\\Phi_0\\) for an image, find a new image \\(x\\) that:
Objective: \\(\\min \\lVert\\Phi(x)-\\Phi_0\\lVert+\\lambda R(x)\\)
Understanding Deep Image Representations by Inverting Them
"},{"location":"AI/CS231n/CS231n_notes/#deepdream-amplify-existing-features","title":"DeepDream: Amplify Existing Features","text":"Given an image, amplify the neuron activations at a layer to generate a new one.
Gram Matrix: \u683c\u62c9\u59c6\u77e9\u9635\uff08Gram matrix\uff09\u8be6\u7ec6\u89e3\u8bfb
Layer \\(i\\) gives feature map of shape \\(C_i\\times H_i\\times W_i\\).
Texture Synthesis Using Convolutional Neural Networks
"},{"location":"AI/CS231n/CS231n_notes/#style-transfer","title":"Style Transfer","text":""},{"location":"AI/CS231n/CS231n_notes/#feature-gram-reconstruction","title":"Feature + Gram Reconstruction","text":"Problem: Style transfer requires many forward / backward passes. Very slow!
"},{"location":"AI/CS231n/CS231n_notes/#fast-style-transfer","title":"Fast Style Transfer","text":""},{"location":"AI/CS231n/CS231n_notes/#9-object-detection-and-image-segmentation","title":"9 - Object Detection and Image Segmentation","text":""},{"location":"AI/CS231n/CS231n_notes/#semantic-segmentation","title":"Semantic Segmentation","text":"Paired Training Data: For each training image, each pixel is labeled with a semantic category.
Fully Convolutional Network: Design a network with only convolutional layers without downsampling operators to make predictions for pixels all at once!
Problem: Convolutions at original image resolution will be very expensive...
Solution: Design fully convolutional network with downsampling and upsampling inside it!
Unpooling:
Nearest Neighbor \"Bed of Nails\" \"Position Memory\"Transposed Convolution: (example size \\(3\\times3\\), stride \\(2\\), pad \\(1\\))
Normal Convolution Transposed Convolution "},{"location":"AI/CS231n/CS231n_notes/#object-detection","title":"Object Detection","text":""},{"location":"AI/CS231n/CS231n_notes/#single-object","title":"Single Object","text":"Classification + Localization. (classification + regression problem)
"},{"location":"AI/CS231n/CS231n_notes/#multiple-object","title":"Multiple Object","text":""},{"location":"AI/CS231n/CS231n_notes/#r-cnn","title":"R-CNN","text":"Using selective search to find \u201cblobby\u201d image regions that are likely to contain objects.
Problem: Very slow. Need to do 2000 independent forward passes for each image!
"},{"location":"AI/CS231n/CS231n_notes/#fast-r-cnn","title":"Fast R-CNN","text":"Pass the image through ConvNet before cropping. Crop the conv feature instead.
Problem: Runtime is dominated by region proposals. (about \\(90\\%\\) time cost)
"},{"location":"AI/CS231n/CS231n_notes/#faster-r-cnn","title":"Faster R-CNN","text":"Insert Region Proposal Network (RPN) to predict proposals from features.
Otherwise same as Fast R-CNN: Crop features for each proposal, classify each one.
Region Proposal Network (RPN) : Slide many fixed windows over ConvNet features.
We have \\(k\\) fixed windows (anchor boxes) of different size/scale centered with each anchor.
For positive boxes, also predict a corrections to the ground-truth box.
Faster R-CNN is a Two-stage object detector:
Backbone network
Region proposal network
Crop features: RoI pool / align
Predict object class
Prediction bbox offset
"},{"location":"AI/CS231n/CS231n_notes/#single-stage-object-detectors-yolo","title":"Single-Stage Object Detectors: YOLO","text":"You Only Look Once: Unified, Real-Time Object Detection
Mask R-CNN: Add a small mask network that operates on each RoI and predicts a \\(28\\times28\\) binary mask.
Mask R-CNN performs very good results!
"},{"location":"AI/CS231n/CS231n_notes/#10-recurrent-neural-networks","title":"10 - Recurrent Neural Networks","text":"Supplement content added according to Deep Learning Book - RNN.
"},{"location":"AI/CS231n/CS231n_notes/#recurrent-neural-network-rnn","title":"Recurrent Neural Network (RNN)","text":""},{"location":"AI/CS231n/CS231n_notes/#motivation-sequence-processing","title":"Motivation: Sequence Processing","text":"One to One One to Many Many to One Many to Many Many to Many Vanilla Neural Networks Image Captioning Action Prediction Video Captioning Video Classification on Frame Level"},{"location":"AI/CS231n/CS231n_notes/#vanilla-rnn","title":"Vanilla RNN","text":"\\(x^{(t)}\\) : Input at time \\(t\\).
\\(h^{(t)}\\) : State at time \\(t\\).
\\(o^{(t)}\\) : Output at time \\(t\\)\u200b\u200b.
\\(y^{(t)}\\) : Expected output at time \\(t\\).
"},{"location":"AI/CS231n/CS231n_notes/#many-to-one","title":"Many to One","text":"Calculation State Transition \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(\\tau)}=\\text{sigmoid}\\ \\big(Vh^{(\\tau)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#many-to-many-type-2","title":"Many to Many (type 2)","text":"Calculation State Transition \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#rnn-with-teacher-forcing","title":"RNN with Teacher Forcing","text":"Update current state according to last-time output instead of last-time state.
Calculation State Transition \\(h^{(t)}=\\tanh(Wo^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#rnn-with-output-forwarding","title":"RNN with \"Output Forwarding\"","text":"We can also combine last-state output with this-state input together.
Calculation State Transition (training) \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+Ry^{(t-1)}+b)\\) State Transition (testing) \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+Ro^{(t-1)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)Usually we use \\(o^{(t-1)}\\) in place of \\(y^{(t-1)}\\) at testing time.
"},{"location":"AI/CS231n/CS231n_notes/#bidirectional-rnn","title":"Bidirectional RNN","text":"When dealing with a whole input sequence, we can process features from two directions.
Calculation State Transition (forward) \\(h^{(t)}=\\tanh(W_1h^{(t-1)}+U_1x^{(t)}+b_1)\\) State Transition (backward) \\(g^{(t)}=\\tanh(W_2g^{(t+1)}+U_2x^{(t)}+b_2)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+Wg^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#encoder-decoder-sequence-to-sequence-rnn","title":"Encoder-Decoder Sequence to Sequence RNN","text":"This is a many-to-many structure (type 1).
First we encode information according to \\(x\\) with no output.
Later we decode information according to \\(y\\) with no input.
\\(C\\) : Context vector, often \\(C=h^{(T)}\\) (last state of encoder).
Calculation State Transition (encode) \\(h^{(t)}=\\tanh(W_1h^{(t-1)}+U_1x^{(t)}+b_1)\\) State Transition (decode, training) \\(s^{(t)}=\\tanh(W_2s^{(t-1)}+U_2y^{(t)}+TC+b_2)\\) State Transition (decode, testing) \\(s^{(t)}=\\tanh(W_2s^{(t-1)}+U_2o^{(t)}+TC+b_2)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vs^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#example-image-captioning","title":"Example: Image Captioning","text":""},{"location":"AI/CS231n/CS231n_notes/#summary_2","title":"Summary","text":"Advantages of RNN:
Disadvantages of RNN:
Add a \"cell block\" to store history weights.
\\(c^{(t)}\\) : Cell at time \\(t\\).
\\(f^{(t)}\\) : Forget gate at time \\(t\\). Deciding whether to erase the cell.
\\(i^{(t)}\\) : Input gate at time \\(t\\). Deciding whether to write to the cell.
\\(g^{(t)}\\) : External input gate at time \\(t\\). Deciding how much to write to the cell.
\\(o^{(t)}\\) : Output gate at time \\(t\\). Deciding how much to reveal the cell.
Calculation (Gate) Forget Gate \\(f^{(t)}=\\text{sigmoid}\\ \\big(W_fh^{(t-1)}+U_fx^{(t)}+b_f\\big)\\) Input Gate \\(i^{(t)}=\\text{sigmoid}\\ \\big(W_ih^{(t-1)}+U_ix^{(t)}+b_i\\big)\\) External Input Gate \\(g^{(t)}=\\tanh(W_gh^{(t-1)}+U_gx^{(t)}+b_g)\\) Output Gate \\(o^{(t)}=\\text{sigmoid}\\ \\big(W_oh^{(t-1)}+U_ox^{(t)}+b_o\\big)\\) Calculation (Main) Cell Transition \\(c^{(t)}=f^{(t)}\\odot c^{(t-1)}+i^{(t)}\\odot g^{(t)}\\) State Transition \\(h^{(t)}=o^{(t)}\\odot\\tanh(c^{(t)})\\) Output Calculation \\(O^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\) "},{"location":"AI/CS231n/CS231n_notes/#other-rnn-variants","title":"Other RNN Variants","text":"GRU...
"},{"location":"AI/CS231n/CS231n_notes/#11-attention-and-transformers","title":"11 - Attention and Transformers","text":""},{"location":"AI/CS231n/CS231n_notes/#rnn-with-attention","title":"RNN with Attention","text":"Encoder-Decoder Sequence to Sequence RNN Problem:
Input sequence bottlenecked through a fixed-sized context vector \\(C\\). (e.g. \\(T=1000\\))
Intuitive Solution:
Generate new context vector \\(C_t\\) at each step \\(t\\) !
\\(e_{t,i}\\) : Alignment score for input \\(i\\) at state \\(t\\). (scalar)
\\(a_{t,i}\\) : Attention weight for input \\(i\\) at state \\(t\\).
\\(C_t\\) : Context vector at state \\(t\\).
Calculation Alignment Score \\(e_i^{(t)}=f(s^{(t-1)},h^{(i)})\\).Where \\(f\\) is an MLP. Attention Weight \\(a_i^{(t)}=\\text{softmax}\\ (e_i^{(t)})\\).Softmax includes all \\(e_i\\) at state \\(t\\). Context Vector \\(C^{(t)}=\\sum_i a_i^{(t)}h^{(i)}\\) Decoder State Transition \\(s^{(t)}=\\tanh(Ws^{(t-1)}+Uy^{(t)}+TC^{(t)}+b)\\)Example on Image Captioning:
"},{"location":"AI/CS231n/CS231n_notes/#general-attention-layer","title":"General Attention Layer","text":"Add linear transformations to the input vector before attention.
Notice:
Each \\(y\\) is a linear weighting of values \\(v\\).
The query vectors \\(q\\) are also generated from the inputs.
In this way, the shape of \\(y\\) is equal to the shape of \\(x\\).
Example with CNN:
"},{"location":"AI/CS231n/CS231n_notes/#positional-encoding","title":"Positional Encoding","text":"Self-attention layer doesn\u2019t care about the orders of the inputs!
To encode ordered sequences like language or spatially ordered image features, we can add positional encoding to the inputs.
We use a function \\(P:R\\rightarrow R^d\\) to process the position \\(i\\) into a d-dimensional vector \\(p_i=P(i)\\).
Constraint Condition of \\(P\\) Uniqueness \\(P(i)\\ne P(j)\\) Equidistance \\(\\lVert P(i+k)-P(i)\\rVert^2=\\lVert P(j+k)-P(j)\\rVert^2\\) Boundness \\(P(i)\\in[a,b]\\) Determinacy \\(P(i)\\) is always a static value. (function is not dynamic)We can either train a encoder model, or design a fixed function.
A Practical Positional Encoding Method: Using \\(\\sin\\) and \\(\\cos\\) with different frequency \\(\\omega\\) at different dimension.
\\(P(t)=\\begin{bmatrix}\\sin(\\omega_1,t)\\\\\\cos(\\omega_1,t)\\\\\\\\\\sin(\\omega_2,t)\\\\\\cos(\\omega_2,t)\\\\\\vdots\\\\\\sin(\\omega_{\\frac{d}{2}},t)\\\\\\cos(\\omega_{\\frac{d}{2}},t)\\end{bmatrix}\\), where frequency \\(\\omega_k=\\frac{1}{10000^{\\frac{2k}{d}}}\\\\\\). (wave length \\(\\lambda=\\frac{1}{\\omega}=10000^{\\frac{2k}{d}}\\\\\\))
\\(P(t)=\\begin{bmatrix}\\sin(1/10000^{\\frac{2}{d}},t)\\\\\\cos(1/10000^{\\frac{2}{d}},t)\\\\\\\\\\sin(1/10000^{\\frac{4}{d}},t)\\\\\\cos(1/10000^{\\frac{4}{d}},t)\\\\\\vdots\\\\\\sin(1/10000^1,t)\\\\\\cos(1/10000^1,t)\\end{bmatrix}\\), after we substitute \\(\\omega_k\\) into the equation.
\\(P(t)\\) is a vector with size \\(d\\), where \\(d\\) is a hyperparameter to choose according to the length of input sequence.
An intuition of this method is the binary encoding of numbers.
[lecture 11d] \u6ce8\u610f\u529b\u548ctransformer (positional encoding \u8865\u5145\uff0c\u4ee3\u7801\u5b9e\u73b0\uff0c\u8ddd\u79bb\u8ba1\u7b97)
It is easy to prove that \\(P(t)\\) satisfies \"Equidistance\": (set \\(d=2\\) for example)
\\(\\begin{aligned}\\lVert P(i+k)-P(i)\\rVert^2&=\\big[\\sin(\\omega_1,i+k)-\\sin(\\omega_1,i)\\big]^2+\\big[\\cos(\\omega_1,i+k)-\\cos(\\omega_1,i)\\big]^2\\\\&=2-2\\sin(\\omega_1,i+k)\\sin(\\omega_1,i)-2\\cos(\\omega_1,i+k)\\cos(\\omega_1,i)\\\\&=2-2\\cos(\\omega_1,k)\\end{aligned}\\)
So the distance is not associated with \\(i\\), we have \\(\\lVert P(i+k)-P(i)\\rVert^2=\\lVert P(j+k)-P(j)\\rVert^2\\).
Visualization of \\(P(t)\\) features: (set \\(d=32\\), \\(x\\) axis represents the position of sequence)
"},{"location":"AI/CS231n/CS231n_notes/#masked-self-attention-layer","title":"Masked Self-attention Layer","text":"To prevent vectors from looking at future vectors, we manually set alignment scores to \\(-\\infty\\).
"},{"location":"AI/CS231n/CS231n_notes/#multi-head-self-attention-layer","title":"Multi-head Self-attention Layer","text":"Multiple self-attention heads in parallel.
"},{"location":"AI/CS231n/CS231n_notes/#transformer","title":"Transformer","text":"Attention Is All You Need
"},{"location":"AI/CS231n/CS231n_notes/#encoder-block","title":"Encoder Block","text":"Inputs: Set of vectors \\(z\\). (in which \\(z_i\\) can be a word in a sentence, or a pixel in a picture...)
Output: Set of context vectors \\(c\\). (encoded features of \\(z\\))
The number of blocks \\(N=6\\) in original paper.
Notice:
Inputs: Set of vectors \\(y\\). (\\(y_i\\) can be a word in a sentence, or a pixel in a picture...)
Inputs: Set of context vectors \\(c\\).
Output: Set of vectors \\(y'\\). (decoded result, \\(y'_i=y_{i+1}\\) for the first \\(n-1\\) number of \\(y'\\))
The number of blocks \\(N=6\\) in original paper.
Notice:
Why we need mask in decoder:
\u4e3e\u4e2a\u4f8b\u5b50\u8bb2\u4e0btransformer\u7684\u8f93\u5165\u8f93\u51fa\u7ec6\u8282\u53ca\u5176\u4ed6
\u5728\u6d4b\u8bd5\u6216\u8005\u9884\u6d4b\u65f6\uff0cTransformer\u91ccdecoder\u4e3a\u4ec0\u4e48\u8fd8\u9700\u8981seq mask\uff1f
"},{"location":"AI/CS231n/CS231n_notes/#example-on-image-captioning-only-with-transformers","title":"Example on Image Captioning (Only with Transformers)","text":""},{"location":"AI/CS231n/CS231n_notes/#comparing-rnns-to-transformer","title":"Comparing RNNs to Transformer","text":"RNNs Transformer Pros LSTMs work reasonably well for long sequences. 1. Good at long sequences. Each attention calculation looks at all inputs.2. Can operate over unordered sets or ordered sequences with positional encodings.3. Parallel computation: All alignment and attention scores for all inputs can be done in parallel. Cons 1. Expects an ordered sequences of inputs.2. Sequential computation: Subsequent hidden states can only be computed after the previous ones are done. Requires a lot of memory: \\(N\\times M\\) alignment and attention scalers need to be calculated and stored for a single self-attention head."},{"location":"AI/CS231n/CS231n_notes/#comparing-convnets-to-transformer","title":"Comparing ConvNets to Transformer","text":"ConvNets strike back!
"},{"location":"AI/CS231n/CS231n_notes/#12-video-understanding","title":"12 - Video Understanding","text":""},{"location":"AI/CS231n/CS231n_notes/#video-classification","title":"Video Classification","text":"Take video classification task for example.
Input size: \\(C\\times T\\times H\\times W\\).
The problem is, videos are quite big. We can't afford to train on raw videos, instead we train on video clips.
Raw Videos Video Clips \\(1920\\times1080,\\ 30\\text{fps}\\) \\(112\\times112,\\ 5\\text{f}/3.2\\text{s}\\) \\(10\\text{GB}/\\text{min}\\) \\(588\\text{KB}/\\text{min}\\) "},{"location":"AI/CS231n/CS231n_notes/#plain-cnn-structure","title":"Plain CNN Structure","text":""},{"location":"AI/CS231n/CS231n_notes/#single-frame-2d-cnn","title":"Single Frame 2D-CNN","text":"Train a normal 2D-CNN model.
Classify each frame independently.
Average the result of each frame as the final result.
"},{"location":"AI/CS231n/CS231n_notes/#late-fusion","title":"Late Fusion","text":"Get high-level appearance of each frame, and combine them.
Run 2D-CNN on each frame, pool features and feed to Linear Layers.
Problem: Hard to compare low-level motion between frames.
"},{"location":"AI/CS231n/CS231n_notes/#early-fusion","title":"Early Fusion","text":"Compare frames with very first Conv Layer, after that normal 2D-CNN.
Problem: One layer of temporal processing may not be enough!
"},{"location":"AI/CS231n/CS231n_notes/#3d-cnn","title":"3D-CNN","text":"Convolve on 3 dimensions: Height, Width, Time.
Input size: \\(C_{in}\\times T\\times H\\times W\\).
Kernel size: \\(C_{in}\\times C_{out}\\times 3\\times 3\\times 3\\).
Output size: \\(C_{out}\\times T\\times H\\times W\\). (with zero paddling)
"},{"location":"AI/CS231n/CS231n_notes/#c3d-vgg-of-3d-cnns","title":"C3D (VGG of 3D-CNNs)","text":"The cost is quite expensive...
Network Calculation AlexNet 0.7 GFLOP VGG-16 13.6 GFLOP C3D 39.5 GFLOP"},{"location":"AI/CS231n/CS231n_notes/#two-stream-networks","title":"Two-Stream Networks","text":"Separate motion and appearance.
"},{"location":"AI/CS231n/CS231n_notes/#i3d-inflating-2d-networks-to-3d","title":"I3D (Inflating 2D Networks to 3D)","text":"Take a 2D-CNN architecture.
Replace each 2D conv/pool layer with a 3D version.
"},{"location":"AI/CS231n/CS231n_notes/#modeling-long-term-temporal-structure","title":"Modeling Long-term Temporal Structure","text":""},{"location":"AI/CS231n/CS231n_notes/#recurrent-convolutional-network","title":"Recurrent Convolutional Network","text":"Similar to multi-layer RNN, we replace the dot-product operation with convolution.
Feature size in layer \\(L\\), time \\(t-1\\): \\(W_h\\times H\\times W\\).
Feature size in layer \\(L-1\\), time \\(t\\): \\(W_x\\times H\\times W\\).
Feature size in layer \\(L\\), time \\(t\\): \\((W_h+W_x)\\times H\\times W\\).
Problem: RNNs are slow for long sequences. (can\u2019t be parallelized)
"},{"location":"AI/CS231n/CS231n_notes/#spatio-temporal-self-attention","title":"Spatio-temporal Self-attention","text":"Introduce self-attention into video classification problems.
"},{"location":"AI/CS231n/CS231n_notes/#vision-transformers-for-video","title":"Vision Transformers for Video","text":"Factorized attention: Attend over space / time.
So many papers...
"},{"location":"AI/CS231n/CS231n_notes/#visualizing-video-models","title":"Visualizing Video Models","text":""},{"location":"AI/CS231n/CS231n_notes/#multimodal-video-understanding","title":"Multimodal Video Understanding","text":""},{"location":"AI/CS231n/CS231n_notes/#temporal-action-localization","title":"Temporal Action Localization","text":"Given a long untrimmed video sequence, identify frames corresponding to different actions.
"},{"location":"AI/CS231n/CS231n_notes/#spatio-temporal-detection","title":"Spatio-Temporal Detection","text":"Given a long untrimmed video, detect all the people in both space and time and classify the activities they are performing.
"},{"location":"AI/CS231n/CS231n_notes/#visually-guided-audio-source-separation","title":"Visually-guided Audio Source Separation","text":"And So on...
"},{"location":"AI/CS231n/CS231n_notes/#13-generative-models","title":"13 - Generative Models","text":""},{"location":"AI/CS231n/CS231n_notes/#pixelrnn-and-pixelcnn","title":"PixelRNN and PixelCNN","text":""},{"location":"AI/CS231n/CS231n_notes/#fully-visible-belief-network-fvbn","title":"Fully Visible Belief Network (FVBN)","text":"\\(p(x)\\) : Likelihood of image \\(x\\).
\\(p(x_1,x_2,\\dots,x_n)\\) : Joint likelihood of all \\(n\\) pixels in image \\(x\\).
\\(p(x_i|x_1,x_2,\\dots,x_{i-1})\\) : Probability of pixel \\(i\\) value given all previous pixels.
For explicit density models, we have \\(p(x)=p(x_1,x_2,\\dots,x_n)=\\prod_{i=1}^np(x_i|x_1,x_2,\\dots,x_{i-1})\\\\\\).
Objective: Maximize the likelihood of training data.
"},{"location":"AI/CS231n/CS231n_notes/#pixelrnn","title":"PixelRNN","text":"Generate image pixels starting from corner.
Dependency on previous pixels modeled using an RNN (LSTM).
Drawback: Sequential generation is slow in both training and inference!
"},{"location":"AI/CS231n/CS231n_notes/#pixelcnn","title":"PixelCNN","text":"Still generate image pixels starting from corner.
Dependency on previous pixels modeled using a CNN over context region (masked convolution).
Drawback: Though its training is faster, its generation is still slow. (pixel by pixel)
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder","title":"Variational Autoencoder","text":"Supplement content added according to Tutorial on Variational Autoencoders. (paper with notes: VAE Tutorial.pdf)
\u53d8\u5206\u81ea\u7f16\u7801\u5668VAE\uff1a\u539f\u6765\u662f\u8fd9\u4e48\u4e00\u56de\u4e8b | \u9644\u5f00\u6e90\u4ee3\u7801
"},{"location":"AI/CS231n/CS231n_notes/#autoencoder","title":"Autoencoder","text":"Learn a lower-dimensional feature representation with unsupervised approaches.
\\(x\\rightarrow z\\) : Dimension reduction for input features.
\\(z\\rightarrow \\hat{x}\\) : Reconstruct input features.
After training, we throw the decoder away and use the encoder for transferring.
For generative models, there is a problem:
We can\u2019t generate new images from an autoencoder because we don\u2019t know the space of \\(z\\).
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder_1","title":"Variational Autoencoder","text":""},{"location":"AI/CS231n/CS231n_notes/#character-description","title":"Character Description","text":"\\(X\\) : Images. (random variable)
\\(Z\\) : Latent representations. (random variable)
\\(P(X)\\) : True distribution of all training images \\(X\\).
\\(P(Z)\\) : True distribution of all latent representations \\(Z\\).
\\(P(X|Z)\\) : True posterior distribution of all images \\(X\\) with condition \\(Z\\).
\\(P(Z|X)\\) : True prior distribution of all latent representations \\(Z\\) with condition \\(X\\).
\\(Q(Z|X)\\) : Approximated prior distribution of all latent representations \\(Z\\) with condition \\(X\\).
\\(x\\) : A specific image.
\\(z\\) : A specific latent representation.
\\(\\theta\\): Learned parameters in decoder network.
\\(\\phi\\): Learned parameters in encoder network.
\\(p_\\theta(x)\\) : Probability that \\(x\\sim P(X)\\).
\\(p_\\theta(z)\\) : Probability that \\(z\\sim P(Z)\\).
\\(p_\\theta(x|z)\\) : Probability that \\(x\\sim P(X|Z)\\).
\\(p_\\theta(z|x)\\) : Probability that \\(z\\sim P(Z|X)\\).
\\(q_\\phi(z|x)\\) : Probability that \\(z\\sim Q(Z|X)\\).
"},{"location":"AI/CS231n/CS231n_notes/#decoder","title":"Decoder","text":"Objective:
Generate new images from \\(\\mathscr{z}\\).
Lemma:
Any distribution in \\(d\\) dimensions can be generated by taking a set of \\(d\\) variables that are normally distributed and mapping them through a sufficiently complicated function. (source: Tutorial on Variational Autoencoders, Page 6)
Solutions:
Objective:
Learn \\(\\mathscr{z}\\) with training images.
Given: (From the decoder, we can deduce the following probabilities.)
Problem:
Both \\(p_\\theta(x)\\) and \\(p_\\theta(z|x)\\) are intractable. (can't be optimized directly as they contain integral operation)
Solution:
Learn \\(Q(Z|X)\\) to approximate the true posterior \\(P(Z|X)\\).
Use \\(q_\\phi(z|x)\\) in place of \\(p_\\theta(z|x)\\).
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder-combination-of-encoder-and-decoder","title":"Variational Autoencoder (Combination of Encoder and Decoder)","text":"Objective:
Maximize \\(p_\\theta(x)\\) for all \\(x^{(i)}\\) in the training set.
$$ \\begin{aligned} \\log p_\\theta\\big(x^{(i)}\\big)&=\\mathbb{E}{z\\sim q\\phi\\big(z|x^{(i)}\\big)}\\Big[\\log p_\\theta\\big(x^{(i)}\\big)\\Big]\\
&=\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(x^{(i)}|z\\big)p_\\theta\\big(z\\big)}{p_\\theta\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Bayes' Rule)}\\
&=\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(x^{(i)}|z\\big)p_\\theta\\big(z\\big)}{p_\\theta\\big(z|x^{(i)}\\big)}\\frac{q_\\phi\\big(z|x^{(i)}\\big)}{q_\\phi\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Multiply by Constant)}\\
&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-\\mathbb{E}z\\Bigg[\\log\\frac{q\\phi\\big(z|x^{(i)}\\big)}{p_\\theta\\big(z\\big)}\\Bigg]+\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(z|x^{(i)}\\big)}{q_\\phi\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Logarithm)}\\
&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]+D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\quad\\text{(KL Divergence)} \\end{aligned} $$
Analyze the Formula by Term:
\\(\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]\\): Decoder network gives \\(p_\\theta\\big(x^{(i)}|z\\big)\\), can compute estimate of this term through sampling.
\\(D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\): This KL term (between Gaussians for encoder and \\(z\\) prior) has nice closed-form solution!
\\(D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\): The part \\(p_\\theta\\big(z|x^{(i)}\\big)\\) is intractable. However, we know KL divergence always \\(\\ge0\\).
Tractable Lower Bound:
We can maximize the lower bound of that formula.
As \\(D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\ge0\\) , we can deduce that:
$$ \\begin{aligned} \\log p_\\theta\\big(x^{(i)}\\big)&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]+D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\
&\\ge\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big] \\end{aligned} $$
So the loss function \\(\\mathcal{L}\\big(x^{(i)},\\theta,\\phi\\big)=-\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]+D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\).
\\(\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]\\): Decoder, reconstruct the input data.
\\(D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\): Encoder, make approximate posterior distribution close to prior.
"},{"location":"AI/CS231n/CS231n_notes/#generative-adversarial-networks-gans","title":"Generative Adversarial Networks (GANs)","text":""},{"location":"AI/CS231n/CS231n_notes/#motivation-modeling","title":"Motivation & Modeling","text":"Objective: Not modeling any explicit density function.
Problem: Want to sample from complex, high-dimensional training distribution. No direct way to do this!
Solution: Sample from a simple distribution, e.g. random noise. Learn the transformation to training distribution.
Problem: We can't learn the mapping relation between sample \\(z\\) and training images.
Solution: Use a discriminator network to tell whether the generate image is within data distribution or not.
Discriminator network: Try to distinguish between real and fake images.
Generator network: Try to fool the discriminator by generating real-looking images.
\\(x\\) : Real data.
\\(y\\) : Fake data, which is generated by the generator network. \\(y=G_{\\theta_g}(z)\\).
\\(D_{\\theta_d}(x)\\) : Discriminator score, which is the likelihood of real image. \\(D_{\\theta_d}(x)\\in[0,1]\\).
Objective of discriminator network:
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
Objective of generator network:
\\(\\min_{\\theta_g}\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
"},{"location":"AI/CS231n/CS231n_notes/#training-strategy","title":"Training Strategy","text":"Two combine this two networks together, we can train them alternately:
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
\\(\\min_{\\theta_g}\\bigg[\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
However, the gradient of generator decreases with the value itself, making it hard to optimize.
So we replace \\(\\log\\big(1-D_{\\theta_d}(y)\\big)\\) with \\(-\\log D_{\\theta_d}(y)\\), and use gradient ascent instead.
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
\\(\\max_{\\theta_g}\\bigg[\\mathbb{E}_{z\\sim p(z)}\\Big(\\log D_{\\theta_d}(y)\\Big)\\bigg]\\)
"},{"location":"AI/CS231n/CS231n_notes/#summary_3","title":"Summary","text":"Pros: Beautiful, state-of-the-art samples!
Cons:
Aim: Solve \u201cpretext\u201d tasks that produce good features for downstream tasks.
Application:
Labels are generated automatically.
"},{"location":"AI/CS231n/CS231n_notes/#rotation","title":"Rotation","text":"Train a classifier on randomly rotated images.
"},{"location":"AI/CS231n/CS231n_notes/#rearrangement","title":"Rearrangement","text":"Train a classifier on randomly shuffled image pieces.
Predict the location of image pieces.
"},{"location":"AI/CS231n/CS231n_notes/#inpainting","title":"Inpainting","text":"Mask part of the image, train a network to predict the masked area.
Method referencing Context Encoders: Feature Learning by Inpainting.
Combine two types of loss together to get better performance:
Transfer between greyscale images and colored images.
Cross-channel predictions for images: Split-Brain Autoencoders.
Video coloring: Establish mappings between reference and target frames in a learned feature space. Tracking Emerges by Colorizing Videos.
"},{"location":"AI/CS231n/CS231n_notes/#summary-for-pretext-tasks","title":"Summary for Pretext Tasks","text":"What we care is the performance of downstream tasks.
"},{"location":"AI/CS231n/CS231n_notes/#problems-of-specific-pretext-tasks","title":"Problems of Specific Pretext Tasks","text":"Intuitive Solution: Contrastive Learning.
"},{"location":"AI/CS231n/CS231n_notes/#contrastive-representation-learning","title":"Contrastive Representation Learning","text":"Local additional references: Contrastive Learning.md.
Objective:
Given a chosen score function \\(s\\), we aim to learn an encoder function \\(f\\) that yields:
Loss Function:
Given \\(1\\) positive sample and \\(N-1\\) negative samples:
InfoNCE Loss Cross Entropy Loss \\(\\begin{aligned}\\mathcal{L}=-\\mathbb{E}_X\\Bigg[\\log\\frac{\\exp{s\\big(f(x),f(x^+)\\big)}}{\\exp{s\\big(f(x),f(x^+)\\big)}+\\sum_{j=1}^{N-1}\\exp{s\\big(f(x),f(x^+)\\big)}}\\Bigg]\\\\\\end{aligned}\\) \\(\\begin{aligned}\\mathcal{L}&=-\\sum_{i=1}^Np(x_i)\\log q(x_i)\\\\&=-\\mathbb{E}_X\\big[\\log q(x)\\big]\\\\&=-\\mathbb{E}_X\\Bigg[\\log\\frac{\\exp(x)}{\\sum_{j=1}^N\\exp(x_j)}\\Bigg]\\end{aligned}\\)The InfoNCE Loss is a lower bound on the mutual information between \\(f(x)\\) and \\(f(x^+)\\):
\\(\\text{MI}\\big[f(x),f(x^+)\\big]\\ge\\log(N)-\\mathcal{L}\\)
The larger the negative sample size \\(N\\), the tighter the bound.
So we use \\(N-1\\) negative samples.
"},{"location":"AI/CS231n/CS231n_notes/#instance-contrastive-learning","title":"Instance Contrastive Learning","text":""},{"location":"AI/CS231n/CS231n_notes/#simclr","title":"SimCLR","text":"Use a projection function \\(g(\\cdot)\\) to project features to a space where contrastive learning is applied.
The extra projection contributes a lot to the final performance.
Score Function: Cos similarity \\(s(u,v)=\\frac{u^Tv}{||u||||v||}\\\\\\).
Positive Pair: Pair of augmented data.
"},{"location":"AI/CS231n/CS231n_notes/#momentum-contrastive-learning-moco","title":"Momentum Contrastive Learning (MoCo)","text":"There are mainly \\(3\\) training strategy in contrastive learning:
(limited by GPU size)
(inconsistency between \\(q\\) and \\(k\\))
(combination of end-to-end & memory bank)
Key differences to SimCLR:
\\(\\theta_k\\leftarrow m\\theta_k+(1-m)\\theta_q\\)
"},{"location":"AI/CS231n/CS231n_notes/#sequence-contrastive-learning","title":"Sequence Contrastive Learning","text":""},{"location":"AI/CS231n/CS231n_notes/#contrastive-predictive-coding-cpc","title":"Contrastive Predictive Coding (CPC)","text":"Contrastive: Contrast between \u201cright\u201d and \u201cwrong\u201d sequences using contrastive learning.
Predictive: The model has to predict future patterns given the current context.
Coding: The model learns useful feature vectors, or \u201ccode\u201d, for downstream tasks, similar to other self-supervised methods.
"},{"location":"AI/CS231n/CS231n_notes/#other-examples-frontier","title":"Other Examples (Frontier)","text":""},{"location":"AI/CS231n/CS231n_notes/#contrastive-language-image-pre-training-clip","title":"Contrastive Language Image Pre-training (CLIP)","text":"Contrastive learning between image and natural language sentences.
"},{"location":"AI/CS231n/CS231n_notes/#15-low-level-vision","title":"15 - Low-Level Vision","text":"Pass...
"},{"location":"AI/CS231n/CS231n_notes/#16-3d-vision","title":"16 - 3D Vision","text":""},{"location":"AI/CS231n/CS231n_notes/#representation","title":"Representation","text":""},{"location":"AI/CS231n/CS231n_notes/#explicit-vs-implicit","title":"Explicit vs Implicit","text":"Explicit: Easy to sample examples, hard to do inside/outside check.
Implicit: Hard to sample examples, easy to do inside/outside check.
Non-parametric Parametric Explicit Points.Meshes. Splines.Subdivision Surfaces. Implicit Level Sets.Voxels. Algebraic Surfaces.Constructive Solid Geometry."},{"location":"AI/CS231n/CS231n_notes/#point-clouds","title":"Point Clouds","text":"The simplest representation.
Collection of \\((x,y,z)\\) coordinates.
Cons:
Collection of vertices \\(v\\) and edges \\(e\\).
Pros:
Use specific functions to approximate the surface. (e.g. B\u00e9zier Curves)
"},{"location":"AI/CS231n/CS231n_notes/#algebraic-surfaces","title":"Algebraic Surfaces","text":"Use specific functions to represent the surface.
"},{"location":"AI/CS231n/CS231n_notes/#constructive-solid-geometry","title":"Constructive Solid Geometry","text":"Combine implicit geometry with Boolean operations.
"},{"location":"AI/CS231n/CS231n_notes/#level-sets","title":"Level Sets","text":"Store a grim of values to approximate the function.
Surface is found where interpolated value equals to \\(0\\).
"},{"location":"AI/CS231n/CS231n_notes/#voxels","title":"Voxels","text":"Binary thresholding the volumetric grid.
"},{"location":"AI/CS231n/CS231n_notes/#ai-3d","title":"AI + 3D","text":"Pass...
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/","title":"Image Classification-Data-driven Approach, k-Nearest Neighbor, train_val_test splits","text":""},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#image-classification-data-driven-approach-k-nearest-neighbor-train_val_test-splits","title":"Image Classification-Data-driven Approach, k-Nearest Neighbor, train_val_test splits","text":"\u7ea6 651 \u4e2a\u5b57 28 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#image-classification","title":"image classification","text":"import numpy as np\n\nclass NearestNeighbor(object): \n def **init**(self): \n pass\n\n def train(self, X, y): \n \"\"\" X is N x D where each row is an example. Y is 1-dimension of size N \"\"\" \n # the nearest neighbor classifier simply remembers all the training data \n self.Xtr = X \n self.ytr = y\n\n def predict(self, X): \n \"\"\" X is N x D where each row is an example we wish to predict label for \"\"\" \n num_test = X.shape[0] \n # lets make sure that the output type matches the input type \n Ypred = np.zeros(num_test, dtype = self.ytr.dtype)\n\n # loop over all test rows\n for i in range(num_test):\n # find the nearest training image to the i'th test image\n # using the L1 distance (sum of absolute value differences)\n distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)\n min_index = np.argmin(distances) # get the index with smallest distance\n Ypred[i] = self.ytr[min_index] # predict the label of the nearest example\n\n return Ypred\n
\\[ d_2 (I_1, I_2) = \\sqrt{\\sum_{p} \\left( I^p_1 - I^p_2 \\right)^2} \\] Pythondistances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))\n
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#k-nearest-neighbor-classifier","title":"k - Nearest Neighbor Classifier","text":""},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#validation-sets-for-hyperparameter-tuning","title":"Validation sets for Hyperparameter tuning","text":"Evaluate on the test only a single time, at the very end
Split your training set into training set and a validation set. Use validation set to tune all hyperparameters. At the end run a single time on the test set and report performance.
As an aside, the computational complexity of the Nearest Neighbor classifier is an active area of research, and several\u00a0Approximate Nearest Neighbor\u00a0(ANN) algorithms and libraries exist that can accelerate the nearest neighbor lookup in a dataset (e.g.\u00a0FLANN). These algorithms allow one to trade off the correctness of the nearest neighbor retrieval with its space/time complexity during retrieval, and usually rely on a pre-processing/indexing stage that involves building a kdtree, or running the k-means algorithm.
In particular, note that images that are nearby each other are much more a function of the general color distribution of the images, or the type of background rather than their semantic identity.
Applying kNN in practicemore about Machine Learing
"},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/","title":"Linear classification-Support Vector Machine, Softmax","text":""},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/#linear-classification-support-vector-machine-softmax","title":"Linear classification-Support Vector Machine, Softmax","text":"\u7ea6 126 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/#linear-classifiaction","title":"Linear Classifiaction","text":"\\[ L_i = \\sum_{j\\neq y_i} \\max(0, s_j - s_{y_i} + \\Delta) \\] \\[ L = \\frac{1}{N} \\sum_i \\sum_{j\\neq y_i} \\left[ \\max(0, f(x_i; W)_j - f(x_i; W)_{y_i} + \\Delta) \\right] + \\lambda \\sum_k\\sum_l W_{k,l}^2 \\] \\[ L_i = -\\log\\left(\\frac{e^{f_{y_i}}}{ \\sum_j e^{f_j} }\\right) \\hspace{0.5in} \\text{or equivalently} \\hspace{0.5in} L_i = -f_{y_i} + \\log\\sum_j e^{f_j} \\] \\[ \\frac{e^{f_{y_i}}}{\\sum_j e^{f_j}} = \\frac{Ce^{f_{y_i}}}{C\\sum_j e^{f_j}} = \\frac{e^{f_{y_i} + \\log C}}{\\sum_j e^{f_j + \\log C}} \\]"},{"location":"AI/CS231n/Numpy/","title":"Numpy","text":""},{"location":"AI/CS231n/Numpy/#python","title":"Python","text":"\u7ea6 49 \u4e2a\u5b57 104 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Numpy/#string","title":"string","text":"Pythons = \"hello\"\nprint(s.capitalize()) # Capitalize a string; prints \"Hello\"\nprint(s.upper()) # Convert a string to uppercase; prints \"HELLO\"\nprint(s.rjust(7)) # Right-justify a string, padding with spaces; prints \" hello\"\nprint(s.center(7)) # Center a string, padding with spaces; prints \" hello \"\nprint(s.replace('l', '(ell)')) # Replace all instances of one substring with another;\n # prints \"he(ell)(ell)o\"\nprint(' world '.strip()) # Strip leading and trailing whitespace; prints \"world\"\n
"},{"location":"AI/CS231n/Numpy/#containers","title":"Containers","text":"Pythonanimals = ['cat', 'dog', 'monkey']\nfor idx, animal in enumerate(animals):\n print('#%d: %s' % (idx + 1, animal))\n# Prints \"#1: cat\", \"#2: dog\", \"#3: monkey\", each on its own line\n
\u5217\u8868\u63a8\u5bfc\u5f0f
Pythonnums = [0, 1, 2, 3, 4]\neven_squares = [x ** 2 for x in nums if x % 2 == 0]\nprint(even_squares) # Prints \"[0, 4, 16]\"\n
\u540c\u6837\u4e5f\u6709\u5b57\u5178\u63a8\u5bfc\u5f0f
Tuples \u53ef\u4ee5\u7528\u4f5c\u5b57\u5178\u4e2d\u7684\u952e\u548c\u96c6\u5408\u7684\u5143\u7d20\uff0c\u4f46\u662f lists \u4e0d\u80fd
"},{"location":"AI/CS231n/Numpy/#numpy","title":"Numpy","text":"Pythonimport numpy as np\n\n# Create a new array from which we will select elements\na = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n\nprint(a) # prints \"array([[ 1, 2, 3],\n # [ 4, 5, 6],\n # [ 7, 8, 9],\n # [10, 11, 12]])\"\n\n# Create an array of indices\nb = np.array([0, 2, 0, 1])\n\n# Select one element from each row of a using the indices in b\nprint(a[np.arange(4), b]) # Prints \"[ 1 6 7 11]\"\n\n# Mutate one element from each row of a using the indices in b\na[np.arange(4), b] += 10\n\nprint(a) # prints \"array([[11, 2, 3],\n # [ 4, 5, 16],\n # [17, 8, 9],\n # [10, 21, 12]])\n
Pythonimport numpy as np\n\na = np.array([[1,2], [3, 4], [5, 6]])\n\nbool_idx = (a > 2) # Find the elements of a that are bigger than 2;\n # this returns a numpy array of Booleans of the same\n # shape as a, where each slot of bool_idx tells\n # whether that element of a is > 2.\n\nprint(bool_idx) # Prints \"[[False False]\n # [ True True]\n # [ True True]]\"\n\n# We use boolean array indexing to construct a rank 1 array\n# consisting of the elements of a corresponding to the True values\n# of bool_idx\nprint(a[bool_idx]) # Prints \"[3 4 5 6]\"\n\n# We can do all of the above in a single concise statement:\nprint(a[a > 2]) # Prints \"[3 4 5 6]\"\n
Pythonx = np.array([1, 2], dtype=np.int64) # Force a particular datatype\nprint(x.dtype) # Prints \"int64\"\n
Pythonimport numpy as np\n\nx = np.array([[1,2],[3,4]], dtype=np.float64)\ny = np.array([[5,6],[7,8]], dtype=np.float64)\n\n# Elementwise sum; both produce the array\n# [[ 6.0 8.0]\n# [10.0 12.0]]\nprint(x + y)\nprint(np.add(x, y))\n\n# Elementwise difference; both produce the array\n# [[-4.0 -4.0]\n# [-4.0 -4.0]]\nprint(x - y)\nprint(np.subtract(x, y))\n\n# Elementwise product; both produce the array\n# [[ 5.0 12.0]\n# [21.0 32.0]]\nprint(x * y)\nprint(np.multiply(x, y))\n\n# Elementwise division; both produce the array\n# [[ 0.2 0.33333333]\n# [ 0.42857143 0.5 ]]\nprint(x / y)\nprint(np.divide(x, y))\n\n# Elementwise square root; produces the array\n# [[ 1. 1.41421356]\n# [ 1.73205081 2. ]]\nprint(np.sqrt(x))\n
\u5e7f\u64ad\u53ef\u4ee5\u907f\u514d\u5faa\u73af
Pythonimport numpy as np\n\n# We will add the vector v to each row of the matrix x,\n# storing the result in the matrix y\nx = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\nv = np.array([1, 0, 1])\ny = x + v # Add v to each row of x using broadcasting\nprint(y) # Prints \"[[ 2 2 4]\n # [ 5 5 7]\n # [ 8 8 10]\n # [11 11 13]]\"\n
"},{"location":"AI/CS231n/Numpy/#scipy","title":"SciPy","text":""},{"location":"AI/CS231n/Numpy/#matplotlib","title":"Matplotlib","text":""},{"location":"AI/EECS%20498-007/KNN/","title":"KNN","text":"\u5bf9\u4e8e\u4e00\u4e2a\u5f85\u5206\u7c7b\u7684\u6837\u672c\uff0c\u627e\u5230\u8bad\u7ec3\u6570\u636e\u96c6\u4e2d\u4e0e\u5176\u6700\u63a5\u8fd1\u7684K\u4e2a\u6837\u672c\uff08\u5373\u6700\u8fd1\u90bb\uff09\uff0c\u7136\u540e\u6839\u636e\u8fd9K\u4e2a\u6837\u672c\u7684\u7c7b\u522b\u6765\u51b3\u5b9a\u5f85\u5206\u7c7b\u6837\u672c\u7684\u7c7b\u522b\u3002
\u7ea6 374 \u4e2a\u5b57 100 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/EECS%20498-007/KNN/#_1","title":"\u6570\u5b66\u63a8\u5bfc","text":"\u5047\u8bbe\u6211\u4eec\u6709\u4e00\u4e2a\u8bad\u7ec3\u6570\u636e\u96c6 \\(T = \\{(x_1, y_1), (x_2, y_2), \\ldots, (x_N, y_N)\\}\\)\uff0c\u5176\u4e2d \\(x_i\\) \u662f\u7279\u5f81\u5411\u91cf\uff0c \\(y_i\\) \u662f\u5bf9\u5e94\u7684\u7c7b\u522b\u6807\u7b7e\u3002\u5bf9\u4e8e\u4e00\u4e2a\u65b0\u7684\u5f85\u5206\u7c7b\u6837\u672c x\uff0cKNN\u7b97\u6cd5\u7684\u76ee\u6807\u662f\u9884\u6d4b\u5176\u7c7b\u522b \\(y\\) \u3002
\u5176\u4e2d\uff0c \\(d\\) \u662f\u7279\u5f81\u7684\u7ef4\u5ea6\u3002
\u5176\u4e2d\uff0c \\(I\\) \u662f\u6307\u793a\u51fd\u6570\uff0c\u5f53 \\(y_i = c_j\\) \u65f6\u53d6\u503c\u4e3a1\uff0c\u5426\u5219\u4e3a0\u3002
"},{"location":"AI/EECS%20498-007/KNN/#_2","title":"\u4f5c\u4e1a\u4e2d\u7684\u5b9e\u73b0","text":"Pythonimport torch\n\ndef compute_distances_two_loops(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n for i in range(num_train):\n for j in range(num_test):\n dists[i,j] = ((x_train[i] - x_test[j]) ** 2).sum() ** (1/2)\n\n return dists\n\ndef compute_distances_one_loop(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n for i in range(num_train):\n dists[i] = ((x_train[i] - x_test) ** 2).sum(dim=(1,2,3)) ** (1/2)\n\n return dists\n\ndef compute_distances_no_loops(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n A = x_train.reshape(num_train, -1)\n B = x_test.reshape(num_test, -1)\n AB2 = A.mm(B.T) * 2\n dists = ((A ** 2).sum(dim=1).reshape(-1, 1) - AB2 + (B ** 2).sum(dim=1).reshape(1, -1)) ** (1/2)\n\n return dists\n\ndef predict_labels(dists, y_train, k=1):\n num_train, num_test = dists.shape\n y_pred = torch.zeros(num_test, dtype=torch.int64)\n\n values, indices = torch.topk(dists, k, dim=0, largest=False)\n for i in range(indices.shape[1]):\n _, idx = torch.max(y_train[indices[:, i]].bincount(), dim=0)\n y_pred[i] = idx\n\n return y_pred\n\nclass KnnClassifier:\n def __init__(self, x_train, y_train):\n self.x_train = x_train\n self.y_train = y_train\n\n def predict(self, x_test, k=1):\n dists = compute_distances_no_loops(self.x_train, x_test)\n y_test_pred = predict_labels(dists, self.y_train, k)\n return y_test_pred\n\n def check_accuracy(self, x_test, y_test, k=1, quiet=False):\n y_test_pred = self.predict(x_test, k=k)\n num_samples = x_test.shape[0]\n num_correct = (y_test == y_test_pred).sum().item()\n accuracy = 100.0 * num_correct / num_samples\n msg = (f'Got {num_correct} / {num_samples} correct; accuracy is {accuracy:.2f}%')\n if not quiet:\n print(msg)\n return accuracy\n\ndef knn_cross_validate(x_train, y_train, num_folds=5, k_choices=None):\n if k_choices is None:\n k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]\n\n x_train_folds = torch.chunk(x_train, num_folds, dim=0)\n y_train_folds = torch.chunk(y_train, num_folds, dim=0)\n\n k_to_accuracies = {}\n\n for k in k_choices:\n list_of_acc = []\n for num_fold in range(num_folds):\n x_train_folds_local = [x for x in x_train_folds]\n y_train_folds_local = [x for x in y_train_folds]\n x_test = x_train_folds_local[num_fold]\n y_test = y_train_folds_local[num_fold]\n del x_train_folds_local[num_fold]\n del y_train_folds_local[num_fold]\n x_train = torch.cat(x_train_folds_local, dim=0)\n y_train = torch.cat(y_train_folds_local, dim=0)\n classifier = KnnClassifier(x_train, y_train)\n list_of_acc.append(classifier.check_accuracy(x_test, y_test, k))\n k_to_accuracies[k] = list_of_acc\n\n return k_to_accuracies\n\ndef knn_get_best_k(k_to_accuracies):\n best_k = 0\n new_dict = {}\n for k, accs in sorted(k_to_accuracies.items()):\n new_dict[k] = sum(accs) / len(accs) \n max_value = max(new_dict.values())\n best_k = [k for k, v in new_dict.items() if v == max_value][0]\n return best_k\n
"},{"location":"AI/EECS%20498-007/Pytorch/","title":"pytorch \u7684\u57fa\u672c\u4f7f\u7528","text":""},{"location":"AI/EECS%20498-007/Pytorch/#pytorch","title":"pytorch \u7684\u57fa\u672c\u4f7f\u7528","text":"\u7ea6 564 \u4e2a\u5b57 45 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
Python# Create a rank 1 tensor from a Python list\na = torch.tensor([[1, 2, 3], [4, 5, 6]])\nprint('Here is a:')\nprint(a)\nprint('type(a): ', type(a))\nprint('rank of a: ', a.dim())\nprint('a.shape: ', a.shape)\n\ntorch.zeros(2, 3)\ntorch.ones(2, 3)\ntorch.eye(3)\ntorch.rand(2, 3)\ntorch.full((M, N), 3.14)\n\ny2 = torch.tensor([1, 2], dtype=torch.int64)\nprint(y2.dtype)\n\nx3 = x0.to(torch.float32)\n\nx0 = torch.eye(3, dtype=torch.float64) \u00a0# Shape (3, 3), dtype torch.float64\nx1 = torch.zeros_like(x0) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Shape (3, 3), dtype torch.float64\nx2 = x0.new_zeros(4, 5) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Shape (4, 5), dtype torch.float64\nx3 = torch.ones(6, 7).to(x0) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# Shape (6, 7), dtype torch.float64\n
Even though PyTorch provides a large number of numeric datatypes, the most commonly used datatypes are:
torch.float32
: Standard floating-point type; used to store learnable parameters, network activations, etc. Nearly all arithmetic is done using this type.torch.int64
: Typically used to store indicestorch.bool
: Stores boolean values: 0 is false and 1 is truetorch.float16
: Used for mixed-precision arithmetic, usually on NVIDIA GPUs with tensor cores. You won't need to worry about this datatype in this course.a[:, 1]
\u548c a[:, 1:2]
\u7684\u533a\u522b\uff0c\u540e\u8005\u4f1a\u4fdd\u7559\u7684\u591a\u4e00\u70b9clone()
\u4ee5\u540e\u7684\u53d8\u91cf\u8ddf\u539f\u53d8\u91cf\u662f\u72ec\u7acb\u7684\uff0c\u4f46\u662f\u7b49\u53f7\u76f4\u63a5\u8d4b\u503c\u7684\u662f\u540c\u4e00\u4e2a\u6307\u9488mask = (a > 3)\nprint('\\nMask tensor:')\nprint(mask)\n# Mask tensor: tensor([[False, False], [False, True], [ True, True]])\n
.view()
shares the same data as the input, so changes to one will affect the other.view
\u8981\u6c42\u539f\u59cb\u5f20\u91cf\u548c\u76ee\u6807\u5f20\u91cf\u5728\u5185\u5b58\u4e2d\u662f\u8fde\u7eed\u7684\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0c view
\u4f1a\u9996\u5148\u8c03\u7528 contiguous
\u65b9\u6cd5\u4f7f\u5176\u8fde\u7eed\uff0c\u7136\u540e\u6539\u53d8\u5f62\u72b6\u3002\u5982\u679c\u5f20\u91cf\u5df2\u7ecf\u662f\u8fde\u7eed\u7684\uff0c view
\u64cd\u4f5c\u4e0d\u4f1a\u590d\u5236\u6570\u636e\u3002reshape
\u4e0d\u8981\u6c42\u539f\u59cb\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0creshape
\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\u5e76\u590d\u5236\u6570\u636e\uff0c\u4ee5\u786e\u4fdd\u65b0\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002view
\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\uff0c\u5b83\u4e0e\u539f\u59cb\u5f20\u91cf\u5171\u4eab\u76f8\u540c\u7684\u6570\u636e\uff0c\u4f46\u662f\u6709\u4e0d\u540c\u7684\u5f62\u72b6\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0cview
\u4f1a\u8fd4\u56de\u4e00\u4e2a\u526f\u672c\u3002reshape
\u4e5f\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\uff0c\u4f46\u603b\u662f\u521b\u5efa\u6570\u636e\u7684\u526f\u672c\uff0c\u5373\u4f7f\u539f\u59cb\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002view
\u3002reshape
\u3002view
\u7684\u53c2\u6570\u662f\u76ee\u6807\u5f62\u72b6\u7684\u7ef4\u5ea6\u3002reshape
\u7684\u53c2\u6570\u4e5f\u662f\u76ee\u6807\u5f62\u72b6\u7684\u7ef4\u5ea6\uff0c\u4f46\u5b83\u53ef\u4ee5\u63a5\u53d7\u4e00\u4e2a\u989d\u5916\u7684\u53c2\u6570inplace
\uff0c\u5982\u679c\u8bbe\u7f6e\u4e3aTrue
\uff0c\u5219\u4f1a\u5728\u539f\u5730\u4fee\u6539\u5f20\u91cf\u7684\u5f62\u72b6\u3002torch.sin(x)
\u548c x.sin()
\u662f\u7b49\u4ef7\u7684x = torch.tensor([[1, 2, 3],\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [4, 5, 6]], dtype=torch.float32)\nprint('Original tensor:')\nprint(x)\n\nprint('\\nSum over entire tensor:')\nprint(torch.sum(x))\nprint(x.sum())\n\n# We can sum over each row:\nprint('\\nSum of each row:')\nprint(torch.sum(x, dim=0))\nprint(x.sum(dim=0))\n\n# Sum over each column:\nprint('\\nSum of each column:')\nprint(torch.sum(x, dim=1))\nprint(x.sum(dim=1))\n
torch.dot
: Computes inner product of vectorstorch.mm
: Computes matrix-matrix productstorch.mv
: Computes matrix-vector productstorch.addmm
/ torch.addmv
: Computes matrix-matrix and matrix-vector multiplications plus a biastorch.bmm
/ torch.baddmm
: Batched versions of torch.mm
and torch.addmm
, respectivelytorch.matmul
: General matrix product that performs different operations depending on the rank of the inputs. Confusingly, this is similar to np.dot
in numpy.\u7ea6 677 \u4e2a\u5b57 216 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u4e24\u79cd\u7ebf\u6027\u5206\u7c7b\u5668\uff1a\u652f\u6301\u5411\u91cf\u673a\uff08SVM\uff09\u548cSoftmax\u5206\u7c7b\u5668\u3002\u8fd9\u4e24\u79cd\u5206\u7c7b\u5668\u90fd\u662f\u76d1\u7763\u5b66\u4e60\u7b97\u6cd5\uff0c\u7528\u4e8e\u5206\u7c7b\u4efb\u52a1\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#svm","title":"\u652f\u6301\u5411\u91cf\u673a\uff08SVM\uff09","text":"SVM\u7684\u76ee\u6807\u662f\u627e\u5230\u4e00\u4e2a\u8d85\u5e73\u9762\uff0c\u5b83\u53ef\u4ee5\u6700\u5927\u5316\u4e0d\u540c\u7c7b\u522b\u4e4b\u95f4\u7684\u8fb9\u754c\u3002\u8fd9\u4e2a\u8d85\u5e73\u9762\u88ab\u79f0\u4e3a\u6700\u4f18\u5206\u5272\u8d85\u5e73\u9762\u3002\u5bf9\u4e8e\u4e8c\u5206\u7c7b\u95ee\u9898\uff0cSVM\u7684\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W, b) = \\frac{1}{N} \\sum_{i=1}^{N} \\max(0, 1 - y_i (W \\cdot x_i + b)) \\]\u5176\u4e2d\uff0c\\(W\\) \u662f\u6743\u91cd\u5411\u91cf\uff0c\\(b\\) \u662f\u504f\u7f6e\u9879\uff0c\\(x_i\\) \u662f\u8f93\u5165\u7279\u5f81\uff0c\\(y_i\\) \u662f\u6807\u7b7e\uff08-1\u62161\uff09\uff0c\\(N\\) \u662f\u6837\u672c\u6570\u91cf\u3002
\u4e3a\u4e86\u5b9e\u73b0\u591a\u5206\u7c7b\uff0c\u6211\u4eec\u4f7f\u7528\u7ed3\u6784\u5316SVM\u635f\u5931\u51fd\u6570\uff0c\u5b83\u8003\u8651\u4e86\u6bcf\u4e2a\u7c7b\u522b\u7684\u5206\u6570\uff0c\u5e76\u5c1d\u8bd5\u6700\u5927\u5316\u6b63\u786e\u7c7b\u522b\u7684\u5206\u6570\u4e0e\u6b21\u9ad8\u7c7b\u522b\u5206\u6570\u4e4b\u95f4\u7684\u5dee\u8ddd\u3002\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = \\frac{1}{N} \\sum_{i=1}^{N} \\sum_{j \\neq y_i} \\max(0, \\text{score}_j - \\text{score}_{y_i} + \\Delta) \\]\u5176\u4e2d\uff0c\\(\\text{score}_j = W_j \\cdot x_i\\)\uff0c\\(\\Delta\\) \u662f\u4e00\u4e2a\u5e38\u6570\uff0c\u901a\u5e38\u8bbe\u7f6e\u4e3a1\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#softmax","title":"Softmax\u5206\u7c7b\u5668","text":"Softmax\u5206\u7c7b\u5668\u4f7f\u7528Softmax\u51fd\u6570\u5c06\u8f93\u5165\u7279\u5f81\u6620\u5c04\u5230\u6982\u7387\u5206\u5e03\u4e0a\u3002\u5bf9\u4e8e\u6bcf\u4e2a\u6837\u672c\uff0cSoftmax\u51fd\u6570\u8f93\u51fa\u6bcf\u4e2a\u7c7b\u522b\u7684\u6982\u7387\u3002Softmax\u51fd\u6570\u5b9a\u4e49\u4e3a\uff1a
\\[ \\text{softmax}(z_i) = \\frac{e^{z_i}}{\\sum_{j=1}^{K} e^{z_j}} \\]\u5176\u4e2d\uff0c\\(z_i\\) \u662f\u7b2c\\(i\\)\u4e2a\u7c7b\u522b\u7684\u5206\u6570\uff0c\\(K\\) \u662f\u7c7b\u522b\u603b\u6570\u3002
Softmax\u5206\u7c7b\u5668\u7684\u635f\u5931\u51fd\u6570\u662f\u4ea4\u53c9\u71b5\u635f\u5931\uff0c\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = -\\frac{1}{N} \\sum_{i=1}^{N} \\sum_{j=1}^{K} y_{ij} \\log(\\text{softmax}(z_j)) \\]\u5176\u4e2d\uff0c\\(y_{ij}\\) \u662f\u4e00\u4e2a\u6307\u793a\u53d8\u91cf\uff0c\u5982\u679c\u6837\u672c\\(i\\)\u5c5e\u4e8e\u7c7b\u522b\\(j\\)\uff0c\u5219\u4e3a1\uff0c\u5426\u5219\u4e3a0\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#_2","title":"\u6b63\u5219\u5316","text":"\u4e3a\u4e86\u9632\u6b62\u8fc7\u62df\u5408\uff0c\u6211\u4eec\u5728\u635f\u5931\u51fd\u6570\u4e2d\u6dfb\u52a0\u4e86\u6b63\u5219\u5316\u9879\u3002L2\u6b63\u5219\u5316\u7684\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = L(W) + \\lambda \\lVert W \\rVert^2 \\]\u5176\u4e2d\uff0c\\(\\lambda\\) \u662f\u6b63\u5219\u5316\u5f3a\u5ea6\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#_3","title":"\u4ee3\u7801\u5b9e\u73b0","text":"\u4ee3\u7801\u4e2d\u5b9e\u73b0\u4e86\u4e24\u79cd\u635f\u5931\u51fd\u6570\u7684\u6734\u7d20\u7248\u672c\uff08svm_loss_naive
\u548c softmax_loss_naive
\uff09\u548c\u5411\u91cf\u5316\u7248\u672c\uff08svm_loss_vectorized
\u548c softmax_loss_vectorized
\uff09\u3002\u5411\u91cf\u5316\u7248\u672c\u901a\u8fc7\u907f\u514d\u663e\u5f0f\u5faa\u73af\u6765\u63d0\u9ad8\u8ba1\u7b97\u6548\u7387\u3002
\u8bad\u7ec3\u8fc7\u7a0b\uff08train_linear_classifier
\uff09\u4f7f\u7528\u968f\u673a\u68af\u5ea6\u4e0b\u964d\uff08SGD\uff09\u6765\u4f18\u5316\u635f\u5931\u51fd\u6570\u3002\u5728\u6bcf\u6b21\u8fed\u4ee3\u4e2d\uff0c\u6211\u4eec\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6279\u6b21\u7684\u6837\u672c\uff0c\u8ba1\u7b97\u635f\u5931\u548c\u68af\u5ea6\uff0c\u7136\u540e\u66f4\u65b0\u6743\u91cd\u3002
\u9884\u6d4b\u8fc7\u7a0b\uff08predict_linear_classifier
\uff09\u4f7f\u7528\u8bad\u7ec3\u597d\u7684\u6743\u91cd\u6765\u9884\u6d4b\u65b0\u6837\u672c\u7684\u7c7b\u522b\u3002
\u4ee3\u7801\u4e2d\u8fd8\u5305\u542b\u4e86\u8d85\u53c2\u6570\u641c\u7d22\u7684\u51fd\u6570\uff08svm_get_search_params
\u548c softmax_get_search_params
\uff09\uff0c\u5b83\u4eec\u8fd4\u56de\u4e0d\u540c\u7684\u5b66\u4e60\u7387\u548c\u6b63\u5219\u5316\u5f3a\u5ea6\u7684\u5019\u9009\u503c\uff0c\u4ee5\u4fbf\u627e\u5230\u6700\u4f73\u7684\u6a21\u578b\u53c2\u6570\u3002
import torch\nimport random\nfrom abc import abstractmethod\n\ndef hello_linear_classifier():\n print('Hello from linear_classifier.py!')\n\nclass LinearClassifier(object):\n def __init__(self):\n random.seed(0)\n torch.manual_seed(0)\n self.W = None\n\n def train(self, X_train, y_train, learning_rate=1e-3, reg=1e-5, num_iters=100,\n batch_size=200, verbose=False):\n train_args = (self.loss, self.W, X_train, y_train, learning_rate, reg,\n num_iters, batch_size, verbose)\n self.W, loss_history = train_linear_classifier(*train_args)\n return loss_history\n\n def predict(self, X):\n return predict_linear_classifier(self.W, X)\n\n @abstractmethod\n def loss(self, W, X_batch, y_batch, reg):\n raise NotImplementedError\n\n def _loss(self, X_batch, y_batch, reg):\n self.loss(self.W, X_batch, y_batch, reg)\n\n def save(self, path):\n torch.save({'W': self.W}, path)\n print(\"Saved in {}\".format(path))\n\n def load(self, path):\n W_dict = torch.load(path, map_location='cpu')\n self.W = W_dict['W']\n print(\"load checkpoint file: {}\".format(path))\n\n\nclass LinearSVM(LinearClassifier):\n def loss(self, W, X_batch, y_batch, reg):\n return svm_loss_vectorized(W, X_batch, y_batch, reg)\n\n\nclass Softmax(LinearClassifier):\n def loss(self, W, X_batch, y_batch, reg):\n return softmax_loss_vectorized(W, X_batch, y_batch, reg)\n\n\ndef svm_loss_naive(W, X, y, reg):\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n loss = 0.0\n for i in range(num_train):\n scores = W.t().mv(X[i])\n correct_class_score = scores[y[i]]\n for j in range(num_classes):\n if j == y[i]:\n continue\n margin = scores[j] - correct_class_score + 1\n if margin > 0:\n loss += margin\n dW[:, j] += X[i]\n dW[:, y[i]] -= X[i]\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef svm_loss_vectorized(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n scores = X.mm(W)\n correct_class_score = scores[range(num_train), y]\n margin = scores - correct_class_score.view(-1, 1) + 1\n margin[range(num_train), y] = 0\n mask = (margin > 0)\n loss = margin[mask].sum()\n mask_correct_y = torch.zeros_like(scores, dtype=torch.bool)\n mask_correct_y[range(num_train), y] = True\n margin[margin > 0] = 1\n margin[margin < 0] = 0\n margin[mask_correct_y] = torch.sum(margin, axis=1) * -1\n dW = margin.T.mm(X).T\n loss /= num_train\n dW /= num_train\n loss += reg * torch.sum(W * W)\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef sample_batch(X, y, num_train, batch_size):\n indices = torch.randint(num_train, (batch_size,))\n y_batch = y[indices]\n X_batch = X[indices]\n return X_batch, y_batch\n\n\ndef train_linear_classifier(loss_func, W, X, y, learning_rate=1e-3,\n reg=1e-5, num_iters=100, batch_size=200,\n verbose=False):\n num_train, dim = X.shape\n if W is None:\n num_classes = torch.max(y) + 1\n W = 0.000001 * torch.randn(dim, num_classes, device=X.device, dtype=X.dtype)\n else:\n num_classes = W.shape[1]\n\n loss_history = []\n for it in range(num_iters):\n X_batch, y_batch = sample_batch(X, y, num_train, batch_size)\n loss, grad = loss_func(W, X_batch, y_batch, reg)\n loss_history.append(loss.item())\n W -= learning_rate * grad\n if verbose and it % 100 == 0:\n print('iteration %d / %d: loss %f' % (it, num_iters, loss))\n\n return W, loss_history\n\n\ndef predict_linear_classifier(W, X):\n y_pred = torch.zeros(X.shape[0], dtype=torch.int64)\n _, y_pred = X.mm(W).max(dim=1)\n return y_pred\n\n\ndef svm_get_search_params():\n learning_rates = [0.000001, 0.0001, 0.001, 0.005, 0.01, 0.05]\n regularization_strengths = [0.001, 0.5, 1, 3]\n return learning_rates, regularization_strengths\n\n\ndef test_one_param_set(cls, data_dict, lr, reg, num_iters=2000):\n train_acc = 0.0\n val_acc = 0.0\n cls.train(data_dict['X_train'], data_dict['y_train'], lr, reg, num_iters,\n batch_size=200, verbose=False)\n y_train_pred = cls.predict(data_dict['X_train'])\n train_acc = 100.0 * (data_dict['y_train'] == y_train_pred).double().mean().item()\n\n y_test_pred = cls.predict(data_dict['X_val'])\n val_acc = 100.0 * (data_dict['y_val'] == y_test_pred).double().mean().item()\n\n return cls, train_acc, val_acc\n\n\ndef softmax_loss_naive(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n\n scores = W.t().mv(X[0])\n correct_class_score = scores[y[0]]\n\n for i in range(num_train):\n scores = W.t().mv(X[i])\n scores = scores - scores.max()\n correct_class_score = scores[y[i]]\n loss += -correct_class_score + torch.log(torch.exp(scores).sum())\n for j in range(num_classes):\n if j == y[i]:\n dW[:, j] += torch.exp(scores[j]) / torch.exp(scores).sum() * X[i, :] - X[i, :]\n else:\n dW[:, j] += torch.exp(scores[j]) / torch.exp(scores).sum() * X[i, :]\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef softmax_loss_vectorized(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n\n\n scores = X.mm(W)\n val, _ = scores.max(dim=1)\n scores = scores - val.view(-1, 1)\n exp_scores = scores.exp()\n exp_scores_sum = exp_scores.sum(dim=1)\n exp_scores_sum_log = exp_scores_sum.log()\n correct_class_scores = scores[range(num_train), y]\n loss = (exp_scores_sum_log - correct_class_scores).sum()\n zeros = torch.zeros((num_train, num_classes), dtype=torch.float64, device='cuda')\n zeros[range(num_train), y] = -1\n minus_X = zeros.t().mm(X)\n dW += minus_X.t()\n dW += ((exp_scores / exp_scores_sum.view(-1, 1)).t().mm(X)).t()\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef softmax_get_search_params():\n learning_rates = [1e-4, 1e-3,1e-2, 1e-1, 1]\n regularization_strengths = [1e-4, 1e-3, 1e-2, 1e-1] \n return learning_rates, regularization_strengths\n
"},{"location":"AI/FFB6D/FFB6D_Conda/","title":"FFB6D\u73af\u5883\u914d\u7f6e\u6307\u5357\uff1a\u539f\u751f\u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#ffb6d","title":"FFB6D\u73af\u5883\u914d\u7f6e\u6307\u5357\uff1a\u539f\u751f\u7cfb\u7edf\u5b89\u88c5","text":"\u7ea6 293 \u4e2a\u5b57 96 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/FFB6D/FFB6D_Conda/#1","title":"1. \u7cfb\u7edf\u8981\u6c42","text":"# \u6dfb\u52a0NVIDIA\u5305\u4ed3\u5e93\nsudo add-apt-repository ppa:graphics-drivers/ppa\nsudo apt-get update\n\n# \u5b89\u88c5NVIDIA\u9a71\u52a8\nsudo apt-get install -y nvidia-driver-535 # \u6839\u636e\u9700\u8981\u9009\u62e9\u7248\u672c\n\n# \u91cd\u542f\u7cfb\u7edf\nsudo reboot\n\n# \u9a8c\u8bc1\u5b89\u88c5\nnvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#22-cudacudnn","title":"2.2 \u5b89\u88c5CUDA\u548ccuDNN","text":"Bash# \u4e0b\u8f7d\u5e76\u5b89\u88c5CUDA 11.0\nwget https://developer.download.nvidia.com/compute/cuda/11.0.3/local_installers/cuda_11.0.3_450.51.06_linux.run\nsudo sh cuda_11.0.3_450.51.06_linux.run\n\n# \u914d\u7f6e\u73af\u5883\u53d8\u91cf\necho 'export PATH=/usr/local/cuda-11.0/bin:$PATH' >> ~/.bashrc\necho 'export LD_LIBRARY_PATH=/usr/local/cuda-11.0/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc\nsource ~/.bashrc\n\n# \u4e0b\u8f7d\u5e76\u5b89\u88c5cuDNN 8.0\n# \u6ce8\uff1a\u9700\u8981\u4eceNVIDIA\u5f00\u53d1\u8005\u7f51\u7ad9\u4e0b\u8f7dcuDNN v8.0\uff0c\u89e3\u538b\u540e\uff1a\nsudo cp cuda/include/cudnn*.h /usr/local/cuda/include\nsudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64\nsudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#23","title":"2.3 \u5b89\u88c5\u7cfb\u7edf\u4f9d\u8d56","text":"Bashsudo apt-get update\nsudo apt-get install -y \\\n python3.6 \\\n python3.6-dev \\\n python3-pip \\\n git \\\n cmake \\\n build-essential \\\n libopencv-dev \\\n libglib2.0-0 \\\n libsm6 \\\n libxext6 \\\n libxrender-dev \\\n libboost-all-dev \\\n libeigen3-dev\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#24-python","title":"2.4 \u914d\u7f6ePython\u73af\u5883","text":"Bash# \u8bbe\u7f6ePython 3.6\u4e3a\u9ed8\u8ba4\u7248\u672c\nsudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1\nsudo update-alternatives --set python3 /usr/bin/python3.6\n\n# \u914d\u7f6epip\u955c\u50cf\u6e90\npip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n\n# \u5347\u7ea7pip\npython3 -m pip install --upgrade pip\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#3-pytorch","title":"3. \u5b89\u88c5PyTorch\u548c\u4f9d\u8d56\u5305","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#31-pytorch","title":"3.1 \u5b89\u88c5PyTorch","text":"Bashpip3 install torch==1.10.2+cu113 torchvision==0.11.3+cu113 -f https://download.pytorch.org/whl/torch_stable.html\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#32","title":"3.2 \u5b89\u88c5\u9879\u76ee\u4f9d\u8d56","text":"\u521b\u5efarequirements.txt\u5e76\u5b89\u88c5\u4f9d\u8d56\uff1a
Bashpip3 install -r requirements.txt\n
requirements.txt\u5185\u5bb9\uff1a
Text Onlyh5py \nnumpy \npyyaml==5.4.1\nenum34 \nfuture \nscipy==1.4.1 \nopencv_contrib_python==3.4.2.16 \ntransforms3d==0.3.1 \nscikit_image==0.13.1 \nlmdb==0.94 \nsetuptools==41.0.0 \ncffi==1.11.5 \neasydict==1.7 \nplyfile==0.6 \npillow==8.2.0 \ndataclasses\nglumpy \ntqdm\ntensorboardX \npandas\nscikit-learn \nscipy \ntermcolor\npybind11\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#4","title":"4. \u7f16\u8bd1\u548c\u5b89\u88c5\u7279\u6b8a\u7ec4\u4ef6","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#41-apex","title":"4.1 \u7f16\u8bd1apex","text":"Bashgit clone https://github.com/NVIDIA/apex\ncd apex\nexport TORCH_CUDA_ARCH_LIST=\"6.0;6.1;6.2;7.0;7.5\"\npython setup.py install -v\ncd ..\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#42-normalspeed","title":"4.2 \u5b89\u88c5\u548c\u7f16\u8bd1normalspeed","text":"Bash# 1. \u51c6\u5907OpenCV\u73af\u5883\npip uninstall opencv-python opencv-python-headless -y\npip install opencv-python==4.5.3.56\n\n# 2. \u514b\u9686\u5e76\u5b89\u88c5normalspeed\ngit clone https://github.com/hfutcgncas/normalspeed.git\ncd normalspeed/normalSpeed\n\n# \u5b89\u88c5\u7f16\u8bd1\u4f9d\u8d56\nsudo apt-get install python3-pybind11\npip3 install Cython==0.29.15\n\n# \u6e05\u7406\u5e76\u91cd\u65b0\u5b89\u88c5\nrm -rf build/ dist/ *.egg-info/\npython3 setup.py install --user\ncd ../..\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#5-ffb6d","title":"5. \u514b\u9686\u548c\u914d\u7f6eFFB6D","text":"Bash# \u514b\u9686\u4ee3\u7801\ngit clone https://github.com/ethnhe/FFB6D.git\ncd FFB6D\n\n# \u521b\u5efa\u5fc5\u8981\u7684\u76ee\u5f55\nmkdir -p datasets models train_log\n\n# \u914d\u7f6e\u73af\u5883\u53d8\u91cf\nexport PYTHONPATH=$PYTHONPATH:$(pwd)\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#6","title":"6. \u9a8c\u8bc1\u5b89\u88c5","text":"Bash# \u9a8c\u8bc1CUDA\u652f\u6301\npython3 -c \"import torch; print('CUDA available:', torch.cuda.is_available())\"\n\n# \u9a8c\u8bc1apex\u5b89\u88c5\npython3 -c \"from apex import amp; print('APEX installed')\"\n\n# \u9a8c\u8bc1normalspeed\u5b89\u88c5\npython3 -c \"import normalSpeed; print('normalspeed installed')\"\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#7","title":"7. \u5e38\u89c1\u95ee\u9898","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#71","title":"7.1 \u7f51\u7edc\u95ee\u9898","text":"Bash# \u4f7f\u7528\u4ee3\u7406\uff08\u5982\u9700\u8981\uff09\nexport http_proxy=\"http://proxy:port\"\nexport https_proxy=\"http://proxy:port\"\n\n# \u6216\u4f7f\u7528\u56fd\u5185\u955c\u50cf\u6e90\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#72","title":"7.2 \u7248\u672c\u517c\u5bb9\u6027\u95ee\u9898","text":"\u6309\u7167\u5b98\u65b9\u6587\u6863\u914d\u7f6eLineMOD\u6570\u636e\u96c6\u5e76\u5f00\u59cb\u8bad\u7ec3\u3002
"},{"location":"AI/FFB6D/FFB6D_Conda/#_1","title":"\u53c2\u8003\u8d44\u6599","text":"\u7ea6 653 \u4e2a\u5b57 213 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/FFB6D/FFB6D_Docker/#1","title":"1. \u7b80\u4ecb","text":"Docker\u662f\u4e00\u4e2a\u5f00\u6e90\u7684\u5e94\u7528\u5bb9\u5668\u5f15\u64ce\uff0c\u8ba9\u5f00\u53d1\u8005\u53ef\u4ee5\u6253\u5305\u4ed6\u4eec\u7684\u5e94\u7528\u4ee5\u53ca\u4f9d\u8d56\u5305\u5230\u4e00\u4e2a\u53ef\u79fb\u690d\u7684\u5bb9\u5668\u4e2d\uff0c\u7136\u540e\u53d1\u5e03\u5230\u4efb\u4f55\u6d41\u884c\u7684Linux\u6216Windows\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u3002\u672c\u6587\u5c06\u4ee5\u914d\u7f6eFFB6D\uff08\u4e00\u4e2a3D\u76ee\u6807\u68c0\u6d4b\u6a21\u578b\uff09\u7684\u8fd0\u884c\u73af\u5883\u4e3a\u4f8b\uff0c\u4ecb\u7ecdDocker\u7684\u57fa\u672c\u4f7f\u7528\u3002
"},{"location":"AI/FFB6D/FFB6D_Docker/#2","title":"2. \u73af\u5883\u51c6\u5907","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#21","title":"2.1 \u7cfb\u7edf\u8981\u6c42","text":"\u5b89\u88c5Docker
Bash# \u66f4\u65b0apt\u5305\u7d22\u5f15\nsudo apt-get update\n\n# \u5b89\u88c5\u5fc5\u8981\u7684\u7cfb\u7edf\u5de5\u5177\nsudo apt-get install -y \\\n apt-transport-https \\\n ca-certificates \\\n curl \\\n gnupg \\\n lsb-release\n\n# \u6dfb\u52a0Docker\u7684\u5b98\u65b9GPG\u5bc6\u94a5\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg\n\n# \u8bbe\u7f6e\u7a33\u5b9a\u7248\u4ed3\u5e93\necho \\\n \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\\n $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\n\n# \u5b89\u88c5Docker Engine\nsudo apt-get update\nsudo apt-get install -y docker-ce docker-ce-cli containerd.io\n\n# \u9a8c\u8bc1\u5b89\u88c5\nsudo docker run hello-world\n
\u5b89\u88c5NVIDIA\u9a71\u52a8
Bash# \u6dfb\u52a0NVIDIA\u5305\u4ed3\u5e93\nsudo add-apt-repository ppa:graphics-drivers/ppa\nsudo apt-get update\n\n# \u5b89\u88c5NVIDIA\u9a71\u52a8\nsudo apt-get install -y nvidia-driver-535 # \u6839\u636e\u9700\u8981\u9009\u62e9\u7248\u672c\n\n# \u91cd\u542f\u7cfb\u7edf\nsudo reboot\n\n# \u9a8c\u8bc1\u5b89\u88c5\nnvidia-smi\n
\u5b89\u88c5NVIDIA Container Toolkit
Bash# \u8bbe\u7f6e\u7a33\u5b9a\u7248\u4ed3\u5e93\ncurl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg\n\necho \"deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/ubuntu22.04/$(arch) /\" | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list\n\n# \u66f4\u65b0\u8f6f\u4ef6\u5305\u5217\u8868\nsudo apt-get update\n\n# \u5b89\u88c5nvidia-docker2\nsudo apt-get install -y nvidia-container-toolkit\n\n# \u91cd\u542fDocker\u670d\u52a1\nsudo systemctl restart docker\n\n# \u6d4b\u8bd5GPU\u652f\u6301\nsudo docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#23-docker","title":"2.3 Docker\u914d\u7f6e\u4f18\u5316","text":"\u914d\u7f6e\u955c\u50cf\u52a0\u901f
Bashsudo tee /etc/docker/daemon.json << EOF\n{\n \"registry-mirrors\": [\n \"https://docker.1panel.dev\",\n \"https://docker.zhai.cm\",\n \"https://hub.littlediary.cn\",\n \"https://docker.nastool.de\"\n ],\n \"dns\": [\"8.8.8.8\", \"8.8.4.4\"],\n \"max-concurrent-downloads\": 10,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"10m\",\n \"max-file\": \"3\"\n }\n}\nEOF\n\nsudo systemctl daemon-reload\nsudo systemctl restart docker\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#3-ffb6d","title":"3. FFB6D\u73af\u5883\u914d\u7f6e\u5b9e\u4f8b","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#31","title":"3.1 \u9879\u76ee\u7ed3\u6784","text":"Bashffb6d_docker/\n\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 build_and_run.sh\n\u251c\u2500\u2500 downloads/\n\u2502 \u251c\u2500\u2500 apex/\n\u2502 \u2514\u2500\u2500 normalspeed/\n\u251c\u2500\u2500 code/\n\u251c\u2500\u2500 datasets/\n\u251c\u2500\u2500 models/\n\u2514\u2500\u2500 train_log/\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#32-dockerfile","title":"3.2 \u521b\u5efaDockerfile","text":"Docker# \u4f7f\u7528\u8f83\u65b0\u7684 CUDA \u955c\u50cf\nFROM nvcr.io/nvidia/cuda:11.0.3-cudnn8-devel-ubuntu18.04\n\n# \u4f7f\u7528 NVIDIA CUDA 11.3 \u57fa\u7840\u955c\u50cf\n# FROM nvcr.io/nvidia/cuda:11.3.1-cudnn8-devel-ubuntu20.04\n\n# \u907f\u514d\u4ea4\u4e92\u5f0f\u63d0\u793a\nENV DEBIAN_FRONTEND=noninteractive\nENV PYTHONPATH=/workspace/code\nENV CUDA_HOME=/usr/local/cuda\nENV PATH=$CUDA_HOME/bin:$PATH\nENV LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH\n\nWORKDIR /workspace\n\n# \u5b89\u88c5\u7cfb\u7edf\u4f9d\u8d56\nRUN apt-get update && apt-get install -y \\\n python3.6 \\\n python3.6-dev \\\n python3-pip \\\n git \\\n cmake \\\n build-essential \\\n libopencv-dev \\\n libglib2.0-0 \\\n libsm6 \\\n libxext6 \\\n libxrender-dev \\\n libboost-all-dev \\\n libeigen3-dev \\\n wget \\\n && rm -rf /var/lib/apt/lists/*\n\n# \u8bbe\u7f6e Python 3.6 \u4e3a\u9ed8\u8ba4\u7248\u672c\nRUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1\nRUN update-alternatives --set python3 /usr/bin/python3.6\n\n# \u5347\u7ea7 pip\nRUN python3 -m pip install --upgrade pip\n\n# \u914d\u7f6epip\u955c\u50cf\u6e90\nRUN pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n\n# \u5148\u5b89\u88c5 PyTorch (\u4f7f\u7528\u8f83\u65b0\u4f46\u517c\u5bb9\u7684\u7248\u672c)\nRUN pip3 install torch==1.10.2+cu113 torchvision==0.11.3+cu113 -f https://download.pytorch.org/whl/torch_stable.html\n\n# \u590d\u5236\u9884\u4e0b\u8f7d\u7684\u6587\u4ef6\nCOPY downloads/apex /workspace/apex\nCOPY downloads/normalspeed /workspace/normalspeed\nCOPY code /workspace/code\n\n# \u5b89\u88c5 apex\n#RUN cd /workspace/apex && \\\n# pip install -v --no-cache-dir --global-option=\"--cpp_ext\" --global-option=\"--cuda_ext\" ./ || \\\n# (echo \"Apex installation failed. Check the error messages above.\" && exit 1)\n\n# \u5b89\u88c5 normalspeed\n#RUN cd /workspace/normalspeed && \\\n# python3 setup.py build_ext --inplace && \\\n# python3 setup.py install\n\nWORKDIR /workspace/code\n
\u66f4\u6539 requirement.txt
h5py \nnumpy \npyyaml==5.4.1\nenum34 \nfuture \nscipy==1.4.1 \nopencv_contrib_python==3.4.2.16 \ntransforms3d==0.3.1 \nscikit_image==0.13.1 \nlmdb==0.94 \nsetuptools==41.0.0 \ncffi==1.11.5 \neasydict==1.7 \nplyfile==0.6 \npillow==8.2.0 \ndataclasses\nglumpy \ntqdm\ntensorboardX \npandas\nscikit-learn \nscipy \ntermcolor\npybind11\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#33-docker-composeyml","title":"3.3 \u521b\u5efadocker-compose.yml","text":"YAMLversion: '3'\nservices:\n ffb6d:\n build: .\n image: ffb6d:latest\n container_name: ffb6d_container\n runtime: nvidia\n environment:\n - NVIDIA_VISIBLE_DEVICES=all\n volumes:\n - ./datasets:/workspace/code/datasets\n - ./train_log:/workspace/code/train_log\n - ./models:/workspace/code/models\n shm_size: '8gb'\n tty: true\n stdin_open: true\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#34","title":"3.4 \u6784\u5efa\u548c\u8fd0\u884c\u811a\u672c","text":"\u521b\u5efabuild_and_run.sh
\uff1a
#!/bin/bash\n\n# \u521b\u5efa\u5fc5\u8981\u76ee\u5f55\nmkdir -p downloads datasets models train_log\n\n# \u4e0b\u8f7d\u4f9d\u8d56\ncd downloads\nif [ ! -d \"apex\" ]; then\n git clone https://github.com/NVIDIA/apex.git\nfi\nif [ ! -d \"normalspeed\" ]; then\n git clone https://github.com/hfutcgncas/normalspeed.git\nfi\ncd ..\n\n# \u514b\u9686FFB6D\u4ee3\u7801\nif [ ! -d \"code\" ]; then\n git clone https://github.com/ethnhe/FFB6D.git code\nfi\n\n# \u6784\u5efa\u955c\u50cf\ndocker-compose build\n\n# \u8fd0\u884c\u5bb9\u5668\ndocker-compose up -d\ndocker exec -it ffb6d_container bash\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#35","title":"3.5 \u542f\u52a8\u548c\u9a8c\u8bc1","text":"Bash# \u6dfb\u52a0\u6267\u884c\u6743\u9650\nchmod +x build_and_run.sh\n\n# \u8fd0\u884c\n./build_and_run.sh\n\n# \u5728\u5bb9\u5668\u5185\u9a8c\u8bc1\npython3 -c \"import torch; print('CUDA available:', torch.cuda.is_available())\"\npython3 -c \"from apex import amp; print('APEX installed')\"\npython3 -c \"import normalspeed; print('normalspeed installed')\"\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#36-apex","title":"3.6 \u7f16\u8bd1 apex","text":"Text Onlygit clone https://github.com/NVIDIA/apex\ncd apex\nexport TORCH_CUDA_ARCH_LIST=\"6.0;6.1;6.2;7.0;7.5\"\npython setup.py install -v\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#37-normalspeed","title":"3.7 \u7f16\u8bd1 normalspeed","text":"Text Only# 1. \u5378\u8f7d\u5f53\u524dcv2\npip uninstall opencv-python opencv-python-headless -y\n\n# 2. \u5b89\u88c5\u7279\u5b9a\u7248\u672c\u7684OpenCV\uff0c\u9009\u62e9\u4e0ePython 3.6\u517c\u5bb9\u7684\u7248\u672c\npip install opencv-python==4.5.3.56\n\n# 3. \u9a8c\u8bc1\u5b89\u88c5\npython3 -c \"import cv2; print(cv2.__version__)\"\n
Text Only# \u8fdb\u5165normalSpeed\u76ee\u5f55\ncd /workspace/code/normalspeed/normalSpeed\n\n# \u5b89\u88c5\u4f9d\u8d56\napt-get update\napt-get install python3-pybind11\npip3 install Cython==0.29.15\n\n# \u6e05\u7406\u4e4b\u524d\u7684\u6784\u5efa\nrm -rf build/\nrm -rf dist/\nrm -rf *.egg-info/\n\n# \u91cd\u65b0\u5b89\u88c5\npython3 setup.py install\n\n# \u9a8c\u8bc1\u5b89\u88c5\npython3 -c \"import normalSpeed\"\n\n# \u8fd4\u56deffb6d\u76ee\u5f55\ncd /workspace/code/ffb6d/\n
Text Onlypython3 setup.py install --user\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#38","title":"3.8 \u8bad\u7ec3","text":"\u628a LineMOD \u590d\u5236\u5230\u5bf9\u5e94\u7684\u8def\u5f84\u4e0b\uff0c\u7136\u540e\u6309\u5b98\u7f51\u6765\u5c31\u597d\u4e86
"},{"location":"AI/FFB6D/FFB6D_Docker/#4","title":"4. \u5e38\u89c1\u95ee\u9898","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#41","title":"4.1 \u7f51\u7edc\u95ee\u9898","text":"\u5982\u679c\u9047\u5230\u4e0b\u8f7d\u6162\u6216\u5931\u8d25\uff1a
Bash# \u4e34\u65f6\u4f7f\u7528\u4ee3\u7406\nexport http_proxy=\"http://proxy:port\"\nexport https_proxy=\"http://proxy:port\"\n\n# \u6216\u4fee\u6539pip\u6e90\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
\u6ce8\u610f\u7528\u4e86\u4ee3\u7406\u7684\u8bdd\uff0cdocker hub \u955c\u50cf\u5c31\u4f1a\u88ab\u8986\u76d6\u6389\uff0c\u5bfc\u81f4\u901f\u5ea6\u5f88\u6162\u3002\u6240\u4ee5\u5230\u65f6\u5019\u4e00\u5b9a\u8981\u53d6\u6d88\u4ee3\u7406 / \u5220\u9664\u4ee3\u7406\u6587\u4ef6
docker hub \u955c\u50cf\u8bbe\u7f6e\u4e0a\u9762\u5199\u4e86\uff0c\u5b98\u7f51\u662f\u8fd9\u4e2a GitHub - dongyubin/DockerHub: 2024\u5e7411\u6708\u66f4\u65b0\uff0c\u76ee\u524d\u56fd\u5185\u53ef\u7528Docker\u955c\u50cf\u6e90\u6c47\u603b\uff0cDockerHub\u56fd\u5185\u955c\u50cf\u52a0\u901f\u5217\u8868\uff0c\ud83d\ude80DockerHub\u955c\u50cf\u52a0\u901f\u5668
"},{"location":"AI/FFB6D/FFB6D_Docker/#42-cuda","title":"4.2 CUDA\u517c\u5bb9\u6027","text":"\u786e\u4fddNVIDIA\u9a71\u52a8\u7248\u672c\u652f\u6301\u6240\u9700\u7684CUDA\u7248\u672c\uff1a
Bash# \u68c0\u67e5\u652f\u6301\u7684\u6700\u9ad8CUDA\u7248\u672c\nnvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#43","title":"4.3 \u5185\u5b58\u4e0d\u8db3","text":"\u8c03\u6574Docker\u5185\u5b58\u9650\u5236\uff1a
YAML# \u5728docker-compose.yml\u4e2d\u6dfb\u52a0\nservices:\n ffb6d:\n deploy:\n resources:\n limits:\n memory: 16G\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#5","title":"5. \u603b\u7ed3","text":"\u672c\u6587\u4ecb\u7ecd\u4e86\u4f7f\u7528Docker\u914d\u7f6e\u6df1\u5ea6\u5b66\u4e60\u73af\u5883\u7684\u5b8c\u6574\u6d41\u7a0b\uff0c\u4ee5FFB6D\u4e3a\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u5904\u7406\u590d\u6742\u4f9d\u8d56\u5173\u7cfb\u3002\u901a\u8fc7\u5bb9\u5668\u5316\u6280\u672f\uff0c\u6211\u4eec\u53ef\u4ee5\uff1a
\u5e0c\u671b\u672c\u6559\u7a0b\u80fd\u5e2e\u52a9\u4f60\u66f4\u597d\u5730\u7406\u89e3\u548c\u4f7f\u7528Docker\u3002
"},{"location":"AI/FFB6D/FFB6D_Docker/#_1","title":"\u53c2\u8003\u8d44\u6599","text":"Abstract
\u4e2a\u4eba\u535a\u5ba2
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
"},{"location":"Blogs/#selected-blogs","title":"Selected Blogs","text":"\u8bba\u6587\u7b14\u8bb0{{ blog_content }}
"},{"location":"Blogs/posts/24-12-29/","title":"\u5de5\u4f5c\u89c4\u5f8b","text":"\u7ea6 1038 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/24-12-29/#_1","title":"\u5de5\u4f5c\u89c4\u5f8b","text":"\u4e4b\u524d\u7684\u4e00\u4e9b\u611f\u60f3\u7eed\u5199\uff1a
Quote\u90a3\u4e48\u5982\u679c\u60f3\u8981\u63d0\u9ad8\u6548\u7387\u7684\u5bf9\u7b56\uff1a
\u6211\u60f3\u4e00\u4e2a\u5408\u7406\u7684\u751f\u6d3b\u4f5c\u606f\u5e94\u8be5\u6709\u4e00\u4e0b\u7279\u70b9\uff1a
\u5de5\u5177\uff1a obsidian\uff0c\u65f6\u95f4\u65e5\u5fd7\uff0c\u535a\u5ba2
\u7d2f\u4e86\u5c31\u4f11\u606f\uff0c\u4f11\u606f\u5b8c\u4e86\u5c31\u5de5\u4f5c
\u7684\u8fdb\u7a0b\u8f6c\u6362\u673a\u5236\u3002\u7ea6 2271 \u4e2a\u5b57 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 11 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_1","title":"\u4fe1\u606f","text":"\u6700\u8fd1\u7684\u4e00\u4e9b\u5173\u4e8e\u4fe1\u606f\u7684\u60f3\u6cd5\u3002
\u4e0b\u9762\u6211\u5148\u4e3e\u4e24\u4e2a\u4f8b\u5b50\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_2","title":"\u52c7\u6562\u53bb\u505a","text":"\u6211\u89c9\u5f97\u6211\u4e00\u76f4\u90fd\u662f\u5f88\u76f4\u63a5\u7684\u4eba\u3002 \u4e3e\u4e2a\u4f8b\u5b50\uff0c\u9ad8\u4e09\u5347\u5927\u4e00\u7684\u6691\u5047\uff0c\u6211\u5728\u8003\u8651\u8981\u4e0d\u8981\u8f6c\u4e13\u4e1a\u3002\u4e8e\u662f\u770b\u904d\u4e86\u6c34\u6e90\u6240\u6709\u76f8\u5173\u7684\u5e16\u5b50\uff0c\u95ee\u4e86\u5f88\u591a\u5b66\u957f\u5b66\u59d0\uff0c\u6574\u7406\u4e86\u5f88\u591a\u8def\u5f84\uff0c\u77e5\u9053\u4e86\u8f6c\u4e13\u4e1a\u8981\uff1a
\u4e5f\u8ba4\u8bc6\u4e86\u5f88\u591a\u5389\u5bb3\u7684\u4eba: xlb, \u661f\u7237\uff0ccl\uff0cKinnari\uff0c\u9c7c\u9c7c\u3002 \u77e5\u9053\u4e86\u5f88\u591a\u6761\u8def\uff0c\u5237\u8bfe\uff0c\u8fdb\u7ec4\uff0c\u6253 ACM\uff0c\u505a\u5f00\u6e90\uff0c\u76f4\u535a\uff0c\u8f6c\u4e13\u4e1a\u3002
\u4f46\u662f\uff0c\u518d\u540e\u6765\u6211\u4fbf\u4e0d\u60f3\u8f6c\u4e13\u4e1a\u4e86\uff08\u4e0d\u60f3\u4e0a\u5de5\u79d1\u5e73\u53f0\u7684\u91d1\u8bfe\uff09\u3002\u867d\u7136\u5230\u5934\u6765\u8fd8\u662f\u6ca1\u6709\u8f6c\u4e13\u4e1a\uff0c\u4f46\u662f\u5374\u6536\u83b7\u4e86\u4e0d\u5c11\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_3","title":"\u591a\u4ea4\u6d41","text":"\u4e00\u76f4\u611f\u89c9\u56fd\u5185\u7684\u6559\u80b2\u4e0d\u652f\u6301\u5408\u4f5c\uff0c\u5f3a\u70c8\u7684\u7ade\u4e89\u5173\u7cfb\u96be\u4ee5\u5f62\u6210\u5229\u76ca\u5171\u540c\u4f53\u3002
\u4f46\u662f\uff0c\u6700\u8fd1\u624d\u53d1\u73b0\uff0c\u6b63\u662f\u90a3\u4e9b\u4f60\u53bb\u5e2e\u52a9\u7684\u8fc7\u7a0b\u4e2d\u7684\u4ea4\u6d41\uff0c\u624d\u80fd\u591f\u8ba9\u4f60\u66f4\u597d\u7684\u53cd\u601d\uff0c\u4ea7\u751f\u65b0\u7684\u60f3\u6cd5\u3002
\u6bd4\u5982\u5728\u8fd9\u4e2a\u7cfb\u5217\u7684\u6587\u7ae0\u4e2d\uff0c Open and open again--\u5982\u4f55\u6709\u6781\u5f3a\u7684\u6267\u884c\u529b\uff1f\uff0c\u6240\u8c13\u7684 open \uff08\u4f5c\u8005\u610f\u601d\u5e94\u8be5\u662f\u548c\u4ed6\u4eba\u4ea4\u6d41\uff09\u4e5f\u53ea\u662f\u6444\u5165\u4fe1\u606f\u7684\u4e00\u79cd\u3002\u800c\u6b63\u662f\u56e0\u4e3a\u4e0e\u4eba\u4ea4\u6d41\u5f80\u5f80\u4f1a\u83b7\u5f97\u6bd4\u8f83\u9ad8\u8d28\u91cf\u7684\u4fe1\u606f\uff0c\u6240\u4ee5\u5448\u73b0\u51fa\u6765\u4ea4\u6d41\u6709\u5f88\u591a advantages\u3002\u4f46\u5b9e\u9645\u4e0a\uff0c\u662f\u4f18\u8d28\u7684\u4fe1\u606f\u5728\u53d1\u6325\u4f5c\u7528\u3002
\u4e8e\u662f\u8fc5\u901f\u548c @Kinnari \u4e00\u8d77\u7ec4\u5efa\u4e86\u4e00\u4e2a\u793e\u7fa4\uff0c\u5e0c\u671b\u80fd\u591f\u8ba9\u5927\u5bb6\u4e00\u8d77\u8ba8\u8bba\u60f3\u6cd5\uff0c\u8fed\u4ee3\u81ea\u5df1\u7684\u5de5\u4f5c\u6d41\u7a0b\uff0c\u51cf\u5c0f\u4fe1\u606f\u5dee\u3002
\u8fd9\u91cc\u662f\u7fa4\u4e8c\u7ef4\u7801 \u8fd9\u91cc\u662f\u7fa4\u89c4\u5219\u5b9e\u9645\u4e0a\uff0c\u4e0a\u6c34\u6e90\u641c\u7d22\uff0c\u53bb\u8ddf\u4ed6\u4eba\u4ea4\u6d41\u90fd\u662f\u4fe1\u606f\u8f93\u5165\u7684\u4e00\u73af\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_5","title":"\u4fe1\u606f\u7684\u8d28\u91cf","text":"\u73b0\u4ee3\u793e\u4f1a\u4e0d\u7f3a\u4f18\u8d28\u4fe1\u606f\uff0c\u7f3a\u7684\u662f\u5982\u4f55\u627e\u5230\u4f18\u8d28\u4fe1\u606f
\u5982\u4f55\u8fdc\u79bb\u4f4e\u8d28\u91cf\u4fe1\u606f\uff1f\u6211\u7684\u4e00\u4e9b\u901a\u7528\u7684\u539f\u5219\u662f\uff1a
\u5b66\u4e60\u67d0\u4e00\u9886\u57df\u77e5\u8bc6\u65f6\u9075\u5faa\u00a0\u81ea\u4f4e\u5411\u4e0a
\u00a0\u7684\u8fc7\u7a0b\uff1a
\u8f6e\u5ed3\u8ba4\u8bc6
\u3002\u6bd4\u8f83\u5168\u9762\u7684\u57fa\u672c\u8ba4\u8bc6
\u00a0\u540e\uff0c\u6211\u4f1a\u627e\u4e00\u4e9b\u76f8\u5173\u4e66\u7c4d\u53bb\u7cfb\u7edf\u6027\u7684\u5b66\u4e60\u8be5\u9886\u57df\u7684\u7406\u8bba\u77e5\u8bc6\u3002\u6211\u89c9\u5f97\u7126\u8651\u5e94\u8be5\u662f\u4fe1\u606f\u6444\u5165\u7684\u95ee\u9898\uff0c\u4e3b\u8981\u8fd8\u662f\u8981\u60f3\u6e05\u695a\u81ea\u5df1\u8981\u4ec0\u4e48\u3002
\u5176\u5b9e\u6211\u662f\u4e00\u76f4\u4e0d\u600e\u4e48\u7126\u8651\u7684\u4eba\u3002\u4f46\u662f\uff0c\u603b\u662f\u4f1a\u9047\u5230\u670b\u53cb\u6765\u54ed\u8bc9\u4ed6\u4eec\u7684\u7126\u8651\u3002\u6211\u662f\u8ba4\u4e3a\u7126\u8651\u65e0\u7528\u6240\u4ee5\u4e0d\u7126\u8651\uff0c\u8ba4\u4e3a\u73b0\u72b6\u80af\u5b9a\u6709\u5bf9\u5e94\u7684\u539f\u56e0\uff0c\u53ea\u8981\u628a\u5bf9\u5e94\u7684\u539f\u56e0\u89e3\u51b3\u4e86\u5c31\u4e0d\u4f1a\u7126\u8651\u4e86\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_12","title":"\u5b9a\u65f6\u53cd\u601d","text":"\u8fd9\u4e2a\u5e94\u8be5\u662f\u4fe1\u606f\u8f93\u5165\u4ee5\u540e\u7684\u5de5\u4f5c\u4e86\u3002
\u5728\u6211\u770b\u6765\uff0c\u53cd\u601d\u8fed\u4ee3\u662f\u6700\u4e3a\u91cd\u8981\u7684\u6280\u80fd\u4e4b\u4e00\u3002
\u4f46\u662f\u5177\u4f53\u7684\u53ef\u80fd\u4ee5\u540e\u4f1a\u53e6\u5199\u4e00\u7bc7\u6587\u7ae0\uff0c\u4e0d\u8fc7\u5728 24-12-29 \u8fd9\u7bc7\u6587\u7ae0\u4e2d\u4e5f\u6709\u63d0\u53ca\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#reference","title":"Reference","text":"\u7ea6 192 \u4e2a\u5b57 375 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u4e09\u7ef4\u91cd\u5efa
#\u590d\u73b0
","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/FreeSplatter%20%E4%BB%A3%E7%A0%81%E8%A7%A3%E8%AF%BB/#freesplatter","title":"FreeSplatter \u4ee3\u7801\u89e3\u8bfb","text":"","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/FreeSplatter%20%E4%BB%A3%E7%A0%81%E8%A7%A3%E8%AF%BB/#views_to_3d","title":"\u7a00\u758f\u91cd\u5efa\u5bf9\u8c61 views_to_3d","text":"Pythondef run_views_to_3d(\n self, \n image_files, # \u8f93\u5165\u7684\u56fe\u50cf\u6587\u4ef6\u5217\u8868\n do_rembg=False, # \u662f\u5426\u79fb\u9664\u56fe\u50cf\u80cc\u666f\n gs_type='2DGS', # \u9ad8\u65af\u6e32\u67d3\u7c7b\u578b\uff1a2DGS \u6216 3DGS\n mesh_reduction=0.5, # \u7f51\u683c\u7b80\u5316\u6bd4\u4f8b\n cache_dir=None, # \u7f13\u5b58\u76ee\u5f55\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\uff0c\u907f\u514d\u788e\u7247\u5316\n\n # \u521b\u5efa\u8f93\u51fa\u76ee\u5f55\n self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')\n os.makedirs(self.output_dir, exist_ok=True)\n\n # \u56fe\u50cf\u9884\u5904\u7406\uff1a\u52a0\u8f7d\u548c\u5904\u7406\u8f93\u5165\u56fe\u50cf\n images, alphas = [], [] # \u56fe\u50cf\u548c alpha \u901a\u9053\u5b58\u50a8\n for image_file in image_files:\n if isinstance(image_file, tuple): # \u517c\u5bb9\u4f20\u5165\u5143\u7ec4\u7684\u60c5\u51b5\n image_file = image_file[0]\n image = Image.open(image_file) # \u6253\u5f00\u56fe\u50cf\n w, h = image.size # \u83b7\u53d6\u56fe\u50cf\u5c3a\u5bf8\n\n # \u53ef\u9009\uff1a\u79fb\u9664\u80cc\u666f\n image_rgba = self.run_segmentation(image) # \u80cc\u666f\u79fb\u9664\n if image.mode == 'RGBA': # \u5982\u679c\u5df2\u6709 alpha \u901a\u9053\n image, alpha = rgba_to_white_background(image_rgba) # \u8f6c\u6362\u4e3a\u767d\u80cc\u666f\n image = v2.functional.center_crop(image, min(h, w)) # \u5c45\u4e2d\u88c1\u526a\n alpha = v2.functional.center_crop(alpha, min(h, w)) # \u88c1\u526a alpha \u901a\u9053\n else: # \u5982\u679c\u6ca1\u6709 alpha \u901a\u9053\n image_rgba = resize_foreground(image_rgba, 0.9) # \u7f29\u653e\u524d\u666f\n image, alpha = rgba_to_white_background(image_rgba) # \u8f6c\u6362\u4e3a\u767d\u80cc\u666f\n\n # \u8c03\u6574\u5206\u8fa8\u7387\u81f3 512x512\n image = v2.functional.resize(image, 512, interpolation=3, antialias=True).clamp(0, 1)\n alpha = v2.functional.resize(alpha, 512, interpolation=0, antialias=True).clamp(0, 1)\n\n # \u4fdd\u5b58\u5904\u7406\u540e\u7684\u56fe\u50cf\u548c alpha \u901a\u9053\n images.append(image)\n alphas.append(alpha)\n\n # \u5c06\u56fe\u50cf\u548c alpha \u901a\u9053\u5806\u53e0\u4e3a\u5f20\u91cf\n images = torch.stack(images, dim=0)\n alphas = torch.stack(alphas, dim=0)\n\n # \u751f\u6210\u53ef\u89c6\u5316\u62fc\u63a5\u56fe\u50cf\n images_vis = v2.functional.to_pil_image(rearrange(images, 'n c h w -> c h (n w)'))\n\n # \u8c03\u7528\u6838\u5fc3\u91cd\u5efa\u51fd\u6570\n legends = [f'V{i}' for i in range(1, 1 + len(images))] # \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u751f\u6210\u56fe\u4f8b\n gs_vis_path, video_path, mesh_fine_path, fig = self.run_freesplatter_object(\n images, alphas, legends=legends, gs_type=gs_type, mesh_reduction=mesh_reduction\n )\n\n return images_vis, gs_vis_path, video_path, mesh_fine_path, fig\n\n\ndef run_freesplatter_object(\n self, \n images, # \u8f93\u5165\u56fe\u50cf\u5f20\u91cf\n alphas, # \u56fe\u50cf\u7684 alpha \u901a\u9053\u5f20\u91cf\n legends=None, # \u56fe\u50cf\u89c6\u89d2\u7684\u56fe\u4f8b\n gs_type='2DGS', # \u9ad8\u65af\u6e32\u67d3\u7c7b\u578b\n mesh_reduction=0.5, # \u7f51\u683c\u7b80\u5316\u6bd4\u4f8b\n):\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n device = self.device\n\n # \u6839\u636e\u6e32\u67d3\u7c7b\u578b\u9009\u62e9\u6a21\u578b\n freesplatter = self.freesplatter_2dgs if gs_type == '2DGS' else self.freesplatter\n\n # \u5c06\u56fe\u50cf\u548c alpha \u901a\u9053\u79fb\u52a8\u5230 GPU\n images, alphas = images.to(device), alphas.to(device)\n\n # **\u6b65\u9aa4 1\uff1a\u751f\u6210\u9ad8\u65af\u70b9\u4e91**\n t0 = time.time()\n with torch.inference_mode():\n gaussians = freesplatter.forward_gaussians(images.unsqueeze(0)) # \u751f\u6210\u9ad8\u65af\u70b9\u4e91\n t1 = time.time()\n\n # **\u6b65\u9aa4 2\uff1a\u4f30\u8ba1\u76f8\u673a\u53c2\u6570\u5e76\u53ef\u89c6\u5316**\n c2ws_pred, focals_pred = freesplatter.estimate_poses(\n images, gaussians, masks=alphas, use_first_focal=True, pnp_iter=10\n ) # \u4f30\u8ba1\u76f8\u673a\u5916\u53c2\u548c\u7126\u8ddd\n fig = self.visualize_cameras_object(images, c2ws_pred, focals_pred, legends=legends) # \u53ef\u89c6\u5316\u76f8\u673a\u4f4d\u59ff\n t2 = time.time()\n\n # **\u6b65\u9aa4 3\uff1a\u4fdd\u5b58\u9ad8\u65af\u70b9\u4e91**\n gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')\n save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3, pad_2dgs_scale=True)\n print(f'Save gaussian at {gs_vis_path}')\n\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 4\uff1a\u751f\u6210\u73af\u7ed5\u89c6\u89d2\u89c6\u9891**\n with torch.inference_mode():\n c2ws_video = get_circular_cameras(N=120, elevation=0, radius=2.0, normalize=True).to(device) # \u73af\u7ed5\u76f8\u673a\u8f68\u8ff9\n fx = fy = focals_pred.mean() / 512.0 # \u8ba1\u7b97\u5f52\u4e00\u5316\u7126\u8ddd\n cx = cy = torch.ones_like(fx) * 0.5 # \u4e2d\u5fc3\u70b9\u5f52\u4e00\u5316\n fxfycxcy_video = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_video.shape[0], 1).to(device)\n\n video_frames = freesplatter.forward_renderer(\n gaussians, c2ws_video.unsqueeze(0), fxfycxcy_video.unsqueeze(0)\n )['image'][0].clamp(0, 1) # \u6e32\u67d3\u89c6\u9891\u5e27\n\n video_path = os.path.join(self.output_dir, 'gs.mp4')\n save_video(video_frames, video_path, fps=30) # \u4fdd\u5b58\u89c6\u9891\n print(f'Save video at {video_path}')\n t3 = time.time()\n\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 5\uff1aTSDF \u878d\u5408\u751f\u6210\u7f51\u683c**\n with torch.inference_mode():\n c2ws_fusion = get_fibonacci_cameras(N=120, radius=2.0) # TSDF \u878d\u5408\u76f8\u673a\u8f68\u8ff9\n c2ws_fusion, _ = normalize_cameras(\n c2ws_fusion, camera_position=torch.tensor([0., -2., 0.]), camera_system='opencv'\n ) # \u76f8\u673a\u5f52\u4e00\u5316\n c2ws_fusion = c2ws_fusion.to(device)\n c2ws_fusion_reference = torch.linalg.inv(c2ws_fusion[0:1]) @ c2ws_fusion\n fx = fy = focals_pred.mean() / 512.0\n cx = cy = torch.ones_like(fx) * 0.5\n fov = np.rad2deg(np.arctan(0.5 / fx.item())) * 2\n fxfycxcy_fusion = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_fusion.shape[0], 1).to(device)\n\n fusion_render_results = freesplatter.forward_renderer(\n gaussians, c2ws_fusion_reference.unsqueeze(0), fxfycxcy_fusion.unsqueeze(0)\n )\n images_fusion = fusion_render_results['image'][0].clamp(0, 1).permute(0, 2, 3, 1)\n alphas_fusion = fusion_render_results['alpha'][0].permute(0, 2, 3, 1)\n depths_fusion = fusion_render_results['depth'][0].permute(0, 2, 3, 1)\n\n # TSDF \u878d\u5408\u5904\u7406\n fusion_images = (images_fusion.detach().cpu().numpy() * 255).clip(0, 255).astype(np.uint8)\n fusion_depths = depths_fusion.detach().cpu().numpy()\n fusion_alphas = alphas_fusion.detach().cpu().numpy()\n fusion_masks = (fusion_alphas > 1e-2).astype(np.uint8)\n fusion_depths = fusion_depths * fusion_masks - np.ones_like(fusion_depths) * (1 - fusion_masks)\n\n fusion_c2ws = c2ws_fusion.detach().cpu().numpy()\n\n # \u751f\u6210\u7f51\u683c\u6587\u4ef6\n mesh_path = os.path.join(self.output_dir, 'mesh.obj')\n rgbd_to_mesh(\n fusion_images, fusion_depths, fusion_c2ws, fov, mesh_path, cam_elev_thr=-90\n ) # TSDF \u878d\u5408\u751f\u6210\u7f51\u683c\n print(f'Save mesh at {mesh_path}')\n t4 = time.time()\n\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 6\uff1a\u4f18\u5316\u7eb9\u7406**\n cam_pos = c2ws_fusion[:, :3, 3].cpu().numpy() # \u83b7\u53d6\u76f8\u673a\u4f4d\u7f6e\n cam_inds = torch.from_numpy(fpsample.fps_sampling(cam_pos, 16).astype(int)).to(device=device) # \u91c7\u6837\u5173\u952e\u5e27\u76f8\u673a\n\n # \u4f18\u5316\u7f51\u683c\u7eb9\u7406\n alphas_bake = alphas_fusion[cam_inds]\n images_bake = (images_fusion[cam_inds] - (1 - alphas_bake)) / alphas_bake.clamp(min=1e-6)\n\n fxfycxcy = fxfycxcy_fusion[cam_inds].clone()\n intrinsics = torch.eye(3).unsqueeze(0).repeat(len(cam_inds), 1, 1).to(fxfycxcy)\n intrinsics[:, 0, 0] = fxfycxcy[:, 0]\n intrinsics[:, 0, 2] = fxfycxcy[:, 2]\n intrinsics[:, 1, 1] = fxfycxcy[:, 1]\n intrinsics[:, 1, 2] = fxfycxcy[:, 3]\n\n out_mesh = trimesh.load(str(mesh_path), process=False) # \u52a0\u8f7d\u7f51\u683c\n out_mesh = optimize_mesh(\n out_mesh, \n images_bake, \n alphas_bake.squeeze(-1), \n c2ws_fusion[cam_inds].inverse(), \n intrinsics,\n simplify=mesh_reduction,\n verbose=False\n ) # \u4f18\u5316\u7eb9\u7406\n mesh_fine_path = os.path.join(self.output_dir, 'mesh.glb')\n out_mesh.export(mesh_fine_path) # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7f51\u683c\n print(f\"Save optimized mesh at {mesh_fine_path}\")\n t5 = time.time()\n\n # \u6253\u5370\u65f6\u95f4\u7edf\u8ba1\n print(f'Generate Gaussians: {t1-t0:.2f} seconds.')\n print(f'Estimate poses: {t2-t1:.2f} seconds.')\n print(f'Generate video: {t3-t2:.2f} seconds.')\n print(f'Generate mesh: {t4-t3:.2f} seconds.')\n print(f'Optimize mesh: {t5-t4:.2f} seconds.')\n\n return gs_vis_path, video_path, mesh_fine_path, fig\n
def visualize_cameras_object(\n self, \n images, # \u8f93\u5165\u7684\u56fe\u50cf\n c2ws, # \u76f8\u673a\u4f4d\u59ff\uff08\u4e16\u754c\u5750\u6807\u7cfb\u5230\u76f8\u673a\u5750\u6807\u7cfb\u7684\u53d8\u6362\u77e9\u9635\uff09\n focal_length, # \u7126\u8ddd\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\uff0c\u9ed8\u8ba4\u65e0\n):\n # **1. \u5904\u7406\u56fe\u50cf**\uff1a\u8c03\u6574\u56fe\u50cf\u5927\u5c0f\uff0c\u9650\u5236\u50cf\u7d20\u503c\u5728 [0, 1] \u8303\u56f4\uff0c\u7136\u540e\u8f6c\u6362\u4e3a NumPy \u683c\u5f0f\n images = v2.functional.resize(images, 128, interpolation=3, antialias=True).clamp(0, 1)\n images = (images.permute(0, 2, 3, 1).detach().cpu().numpy() * 255).astype(np.uint8)\n\n # **2. \u76f8\u673a\u4f4d\u59ff\u8f6c\u6362**\uff1a\u5c06 c2ws\uff08\u76f8\u673a\u4f4d\u59ff\uff09\u8f6c\u6362\u5230\u4e16\u754c\u5750\u6807\u7cfb\u4e0b\n cam2world = create_camera_to_world(torch.tensor([0, -2, 0]), camera_system='opencv').to(c2ws) # \u521b\u5efa\u4ece\u76f8\u673a\u5230\u4e16\u754c\u7684\u53d8\u6362\n transform = cam2world @ torch.linalg.inv(c2ws[0:1]) # \u8ba1\u7b97\u7b2c\u4e00\u4e2a\u76f8\u673a\u7684\u53c2\u8003\u53d8\u6362\n c2ws = transform @ c2ws # \u66f4\u65b0\u6240\u6709\u76f8\u673a\u7684\u4f4d\u59ff\n c2ws = c2ws.detach().cpu().numpy()\n c2ws[:, :, 1:3] *= -1 # \u4ece OpenCV \u5230 OpenGL \u5750\u6807\u7cfb\u7684\u8f6c\u6362\n\n # **3. \u8ba1\u7b97\u76f8\u673a\u89c6\u573a\u89d2\uff08FOV\uff09**\n focal_length = focal_length.mean().detach().cpu().numpy()\n fov = np.rad2deg(np.arctan(256.0 / focal_length)) * 2\n\n # **4. \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u6307\u5b9a\u989c\u8272**\n colors = [cmap(i / len(images))[:3] for i in range(len(images))]\n\n # **5. \u8bbe\u7f6e\u56fe\u4f8b**\uff1a\u5982\u679c\u672a\u63d0\u4f9b\uff0c\u9ed8\u8ba4\u4e3a\u7a7a\n legends = [None] * len(images) if legends is None else legends\n\n # **6. \u8c03\u7528\u53ef\u89c6\u5316\u5de5\u5177 CameraVisualizer**\n viz = CameraVisualizer(c2ws, legends, colors, images=images)\n fig = viz.update_figure(\n 3, # \u7ef4\u5ea6\n height=320, # \u56fe\u5f62\u9ad8\u5ea6\n line_width=5, # \u76f8\u673a\u7ebf\u5bbd\n base_radius=1, # \u57fa\u51c6\u76f8\u673a\u4f4d\u7f6e\u534a\u5f84\n zoom_scale=1, # \u7f29\u653e\u6bd4\u4f8b\n fov_deg=fov, # \u89c6\u573a\u89d2\n show_grid=True, # \u662f\u5426\u663e\u793a\u7f51\u683c\n show_ticklabels=True, # \u662f\u5426\u663e\u793a\u5750\u6807\u8f74\u523b\u5ea6\n show_background=True, # \u662f\u5426\u663e\u793a\u80cc\u666f\n y_up=False, # Y \u8f74\u65b9\u5411\u5411\u4e0b\n )\n return fig\n\n\ndef run_views_to_scene(\n self, \n image1, # \u8f93\u5165\u7684\u7b2c\u4e00\u4e2a\u56fe\u50cf\n image2, # \u8f93\u5165\u7684\u7b2c\u4e8c\u4e2a\u56fe\u50cf\n cache_dir=None, # \u8f93\u51fa\u7f13\u5b58\u76ee\u5f55\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n # **1. \u521b\u5efa\u8f93\u51fa\u76ee\u5f55**\n self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')\n os.makedirs(self.output_dir, exist_ok=True)\n\n # **2. \u56fe\u50cf\u9884\u5904\u7406**\n images = []\n for image in [image1, image2]:\n w, h = image.size # \u83b7\u53d6\u56fe\u50cf\u5bbd\u9ad8\n image = torch.from_numpy(np.asarray(image) / 255.0).float() # \u8f6c\u4e3a NumPy\uff0c\u518d\u8f6c\u4e3a\u5f20\u91cf\n image = rearrange(image, 'h w c -> c h w') # \u8c03\u6574\u7ef4\u5ea6\u4e3a (C, H, W)\n image = v2.functional.center_crop(image, min(h, w)) # \u4e2d\u5fc3\u88c1\u526a\n image = v2.functional.resize(image, 512, interpolation=3, antialias=True).clamp(0, 1) # \u8c03\u6574\u5927\u5c0f\u5e76\u5f52\u4e00\u5316\n images.append(image) # \u6dfb\u52a0\u5230\u5217\u8868\n\n # **3. \u5c06\u56fe\u50cf\u5806\u53e0\u6210\u4e00\u4e2a\u5f20\u91cf**\n images = torch.stack(images, dim=0)\n\n # **4. \u751f\u6210\u62fc\u63a5\u53ef\u89c6\u5316\u56fe\u50cf**\n images_vis = v2.functional.to_pil_image(rearrange(images, 'n c h w -> c h (n w)'))\n\n # **5. \u8c03\u7528\u573a\u666f\u91cd\u5efa\u65b9\u6cd5**\n legends = [f'V{i}' for i in range(1, 1+len(images))] # \u4e3a\u89c6\u89d2\u751f\u6210\u56fe\u4f8b\n gs_vis_path, video_path, fig = self.run_freesplatter_scene(images, legends=legends)\n\n return images_vis, gs_vis_path, video_path, fig\n\n\ndef run_freesplatter_scene(\n self, \n images, # \u8f93\u5165\u56fe\u50cf\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n freesplatter = self.freesplatter_scene # \u4f7f\u7528 FreeSplatter \u573a\u666f\u6a21\u578b\n\n device = self.device\n images = images.to(device) # \u5c06\u56fe\u50cf\u79fb\u52a8\u5230 GPU\n\n # **1. \u751f\u6210\u9ad8\u65af\u70b9\u4e91**\n t0 = time.time()\n with torch.inference_mode():\n gaussians = freesplatter.forward_gaussians(images.unsqueeze(0)) # \u8c03\u7528\u9ad8\u65af\u751f\u6210\u5668\n t1 = time.time()\n\n # **2. \u4f30\u8ba1\u76f8\u673a\u4f4d\u59ff**\n c2ws_pred, focals_pred = freesplatter.estimate_poses(images, gaussians, use_first_focal=True, pnp_iter=10)\n # **2.1 \u5f52\u4e00\u5316\u76f8\u673a\u57fa\u7ebf**\n baseline_pred = (c2ws_pred[:, :3, 3] - c2ws_pred[:1, :3, 3]).norm() + 1e-2 # \u8ba1\u7b97\u76f8\u673a\u57fa\u7ebf\n scale_factor = 1.0 / baseline_pred # \u5f52\u4e00\u5316\u6bd4\u4f8b\n c2ws_pred = c2ws_pred.clone()\n c2ws_pred[:, :3, 3] *= scale_factor # \u7f29\u653e\u76f8\u673a\u4f4d\u7f6e\n\n # **3. \u53ef\u89c6\u5316\u76f8\u673a**\n fig = self.visualize_cameras_scene(images, c2ws_pred, focals_pred, legends=legends)\n t2 = time.time()\n\n # **4. \u4fdd\u5b58\u9ad8\u65af\u70b9\u4e91**\n gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')\n save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3) # \u4fdd\u5b58\u70b9\u4e91\n print(f'Save gaussian at {gs_vis_path}')\n\n # **5. \u6e32\u67d3\u89c6\u9891**\n with torch.inference_mode():\n c2ws_video = generate_interpolated_path(c2ws_pred.detach().cpu().numpy()[:, :3, :], n_interp=120) # \u751f\u6210\u63d2\u503c\u8def\u5f84\n c2ws_video = torch.cat([\n torch.from_numpy(c2ws_video), \n torch.tensor([0, 0, 0, 1]).reshape(1, 1, 4).repeat(c2ws_video.shape[0], 1, 1)\n ], dim=1).to(gaussians) # \u5c06\u8def\u5f84\u8f6c\u6362\u4e3a\u9f50\u6b21\u5750\u6807\n fx = fy = focals_pred.mean() / 512.0 # \u8ba1\u7b97\u5f52\u4e00\u5316\u7126\u8ddd\n cx = cy = torch.ones_like(fx) * 0.5 # \u5f52\u4e00\u5316\u4e2d\u5fc3\u70b9\n fxfycxcy_video = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_video.shape[0], 1).to(device)\n\n video_frames = freesplatter.forward_renderer(\n gaussians, # \u9ad8\u65af\u70b9\u4e91\n c2ws_video.unsqueeze(0), # \u76f8\u673a\u8f68\u8ff9\n fxfycxcy_video.unsqueeze(0), # \u76f8\u673a\u53c2\u6570\n rescale=scale_factor.reshape(1).to(gaussians) # \u7f29\u653e\u6bd4\u4f8b\n )['image'][0].clamp(0, 1) # \u6e32\u67d3\u56fe\u50cf\u5e27\n\n video_path = os.path.join(self.output_dir, 'gs.mp4')\n save_video(video_frames, video_path, fps=30) # \u4fdd\u5b58\u89c6\u9891\n print(f'Save video at {video_path}')\n t3 = time.time()\n\n # **6. \u6253\u5370\u65f6\u95f4\u7edf\u8ba1**\n print(f'Generate Gaussians: {t1-t0:.2f} seconds.')\n print(f'Estimate poses: {t2-t1:.2f} seconds.')\n print(f'Generate video: {t3-t2:.2f} seconds.')\n\n return gs_vis_path, video_path, fig\n\n\ndef visualize_cameras_scene(\n self, \n images, # \u8f93\u5165\u7684\u56fe\u50cf\n c2ws, # \u76f8\u673a\u4f4d\u59ff\n focal_length, # \u7126\u8ddd\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\n):\n # **1. \u5904\u7406\u56fe\u50cf**\uff1a\u8c03\u6574\u5206\u8fa8\u7387\uff0c\u5f52\u4e00\u5316\uff0c\u8f6c\u6362\u4e3a NumPy \u683c\u5f0f\n images = v2.functional.resize(images, 128, interpolation=3, antialias=True).clamp(0, 1)\n images = (images.permute(0, 2, 3, 1).detach().cpu().numpy() * 255).astype(np.uint8)\n\n # **2. \u8f6c\u6362\u76f8\u673a\u4f4d\u59ff\u5750\u6807\u7cfb**\n c2ws = c2ws.detach().cpu().numpy()\n c2ws[:, :, 1:3] *= -1 # OpenCV \u5230 OpenGL \u8f6c\u6362\n\n # **3. \u8ba1\u7b97\u89c6\u573a\u89d2\uff08FOV\uff09**\n focal_length = focal_length.mean().detach().cpu().numpy()\n fov = np.rad2deg(np.arctan(256.0 / focal_length)) * 2\n\n # **4. \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u5206\u914d\u989c\u8272**\n colors = [cmap(i / len(images))[:3] for i in range(len(images))]\n\n # **5. \u8bbe\u7f6e\u56fe\u4f8b**\n legends = [None] * len(images) if legends is None else legends\n\n # **6. \u53ef\u89c6\u5316\u76f8\u673a**\n viz = CameraVisualizer(c2ws, legends, colors, images=images)\n fig = viz.update_figure(\n 2, \n height=320,\n line_width=5,\n base_radius=1, \n zoom_scale=1, \n fov_deg=fov, \n show_grid=True, \n show_ticklabels=True, \n show_background=True, \n y_up=False,\n )\n return fig\n
","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/","title":"Gaussian_Splatting_Code","text":"\u7ea6 982 \u4e2a\u5b57 34 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u590d\u73b0
#\u4e09\u7ef4\u91cd\u5efa
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#gaussian_splatting_code","title":"Gaussian_Splatting_Code","text":"\u4e3b\u8981\u6709 colmap \u548c blender \u4e24\u79cd\u6570\u636e\u7c7b\u578b\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#1-colmap","title":"1. Colmap \u6570\u636e\u96c6\u52a0\u8f7d\u8fc7\u7a0b","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#11","title":"1.1 \u52a0\u8f7d\u51fd\u6570","text":"readColmapSceneInfo
\uff0c\u8c03\u7528\u4e86\u4e00\u7cfb\u5217\u5b50\u51fd\u6570\u4ee5\u52a0\u8f7d\u76f8\u673a\u53c2\u6570\u3001\u70b9\u4e91\u548c\u76f8\u5173\u6587\u4ef6\u3002sparse/
\u6587\u4ef6\u5939\uff0c\u5305\u542b\u76f8\u673a\u53c2\u6570\u6587\u4ef6\u3001\u70b9\u4e91\u6587\u4ef6\u7b49\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythoncameras_extrinsic_file = os.path.join(path, \"sparse/0\", \"images.bin\")\ncam_extrinsics = read_extrinsics_binary(cameras_extrinsic_file)\n
\u5982\u679c images.bin
\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u52a0\u8f7d images.txt
\uff1a
cameras_extrinsic_file = os.path.join(path, \"sparse/0\", \"images.txt\")\ncam_extrinsics = read_extrinsics_text(cameras_extrinsic_file)\n
\u5916\u53c2\u5305\u62ec\uff1a
R
)\u3002T
)\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythoncameras_intrinsic_file = os.path.join(path, \"sparse/0\", \"cameras.bin\")\ncam_intrinsics = read_intrinsics_binary(cameras_intrinsic_file)\n
\u5982\u679c cameras.bin
\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u52a0\u8f7d cameras.txt
\uff1a
cameras_intrinsic_file = os.path.join(path, \"sparse/0\", \"cameras.txt\")\ncam_intrinsics = read_intrinsics_text(cameras_intrinsic_file)\n
\u5185\u53c2\u5305\u62ec\uff1a
focal length
\uff09\u3002principal point
\uff09\u3002width
\u548c height
\uff09\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonply_path = os.path.join(path, \"sparse/0/points3D.ply\")\nbin_path = os.path.join(path, \"sparse/0/points3D.bin\")\ntxt_path = os.path.join(path, \"sparse/0/points3D.txt\")\n\nif not os.path.exists(ply_path):\n print(\"Converting point3d.bin to .ply, will happen only the first time you open the scene.\")\n xyz, rgb, _ = read_points3D_binary(bin_path)\n storePly(ply_path, xyz, rgb)\npcd = fetchPly(ply_path)\n
points3D.bin
points3D.txt
points3D.ply
\uff08\u5982\u679c\u5b58\u5728\u5219\u76f4\u63a5\u52a0\u8f7d\uff0c\u5426\u5219\u4ece bin
\u6216 txt
\u8f6c\u6362\u4e3a .ply
\uff09\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonif eval:\n cam_names = [cam_extrinsics[cam_id].name for cam_id in cam_extrinsics]\n cam_names = sorted(cam_names)\n test_cam_names_list = [name for idx, name in enumerate(cam_names) if idx % llffhold == 0]\nelse:\n test_cam_names_list = []\n
eval
\u53c2\u6570\u542f\u7528\u3002llffhold=8
\uff09\u9009\u53d6\u4e00\u4e2a\u4f5c\u4e3a\u6d4b\u8bd5\u96c6\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonnerf_normalization = getNerfppNorm(train_cam_infos)\n
translate
) \u548c\u534a\u5f84 (radius
)\u3002\u51fd\u6570\u8fd4\u56de\u4e00\u4e2a SceneInfo
\u6570\u636e\u7ed3\u6784\uff1a
point_cloud
\uff1a\u70b9\u4e91\u6570\u636e\u3002train_cameras
\uff1a\u8bad\u7ec3\u76f8\u673a\u5217\u8868\u3002test_cameras
\uff1a\u6d4b\u8bd5\u76f8\u673a\u5217\u8868\u3002nerf_normalization
\uff1a\u573a\u666f\u5f52\u4e00\u5316\u53c2\u6570\u3002ply_path
\uff1a\u70b9\u4e91\u6587\u4ef6\u8def\u5f84\u3002readNerfSyntheticInfo
\uff0c\u4ece Blender \u5bfc\u51fa\u7684 JSON \u6587\u4ef6\u52a0\u8f7d\u76f8\u673a\u548c\u56fe\u50cf\u4fe1\u606f\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythontrain_cam_infos = readCamerasFromTransforms(path, \"transforms_train.json\", depths_folder, white_background, False, extension)\ntest_cam_infos = readCamerasFromTransforms(path, \"transforms_test.json\", depths_folder, white_background, True, extension)\n
transforms_train.json
\u548c transforms_test.json
\u3002transforms_train.json
:transform_matrix
\uff08\u76f8\u673a\u5230\u4e16\u754c\u7684\u53d8\u6362\u77e9\u9635\uff09\u3002camera_angle_x
) \u7528\u4e8e\u8ba1\u7b97\u7126\u8ddd\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonif not os.path.exists(ply_path):\n num_pts = 100_000\n print(f\"Generating random point cloud ({num_pts})...\")\n xyz = np.random.random((num_pts, 3)) * 2.6 - 1.3\n shs = np.random.random((num_pts, 3)) / 255.0\n storePly(ply_path, xyz, SH2RGB(shs) * 255)\npcd = fetchPly(ply_path)\n
[-1.3, 1.3]
\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonnerf_normalization = getNerfppNorm(train_cam_infos)\n
translate
) \u548c\u534a\u5f84 (radius
)\u3002\u51fd\u6570\u8fd4\u56de\u4e00\u4e2a SceneInfo
\u6570\u636e\u7ed3\u6784\uff1a
point_cloud
\uff1a\u751f\u6210\u7684\u70b9\u4e91\u3002train_cameras
\uff1a\u8bad\u7ec3\u76f8\u673a\u5217\u8868\u3002test_cameras
\uff1a\u6d4b\u8bd5\u76f8\u673a\u5217\u8868\u3002nerf_normalization
\uff1a\u573a\u666f\u5f52\u4e00\u5316\u53c2\u6570\u3002ply_path
\uff1a\u70b9\u4e91\u6587\u4ef6\u8def\u5f84\u3002images.bin
\u548c cameras.bin
\u4e2d\u52a0\u8f7d\u5916\u53c2\u548c\u5185\u53c2 \u4ece transforms_train.json
\u4e2d\u52a0\u8f7d\u53d8\u6362\u77e9\u9635 \u70b9\u4e91 \u4ece points3D.bin
\u6216 points3D.txt
\u52a0\u8f7d \u968f\u673a\u751f\u6210 10 \u4e07\u4e2a\u70b9 \u56fe\u50cf\u6570\u636e \u5b58\u50a8\u5728 images/
\u6587\u4ef6\u5939 \u8def\u5f84\u7531 JSON \u6587\u4ef6\u6307\u5b9a \u6df1\u5ea6\u56fe \u53ef\u9009\uff0c\u9700 depth_params.json
\u5b9a\u4e49 \u53ef\u9009\uff0c\u9700\u63d0\u4f9b\u6df1\u5ea6\u56fe\u6587\u4ef6\u5939 \u5f52\u4e00\u5316 \u57fa\u4e8e\u76f8\u673a\u4f4d\u7f6e\u8ba1\u7b97\u573a\u666f\u4e2d\u5fc3\u548c\u534a\u5f84 \u540c\u4e0a \u6d4b\u8bd5\u96c6\u5212\u5206 \u6bcf 8 \u4e2a\u89c6\u89d2\u5212\u5206\u4e00\u4e2a\u5230\u6d4b\u8bd5\u96c6\uff0c\u6216\u8bfb\u53d6 test.txt
\u6d4b\u8bd5\u96c6\u901a\u8fc7 transforms_test.json
\u6307\u5b9a \u80cc\u666f\u989c\u8272 \u65e0 \u53ef\u9009\u767d\u8272\u6216\u9ed1\u8272\u80cc\u666f","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#4_1","title":"4. \u6240\u9700\u51c6\u5907\u7684\u6587\u4ef6","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#colmap","title":"Colmap \u6570\u636e\u96c6","text":"sparse/0/images.bin
\u6216 images.txt
\u3002sparse/0/cameras.bin
\u6216 cameras.txt
\u3002sparse/0/points3D.bin
\u6216 points3D.txt
\u3002images/
\u3002sparse/0/depth_params.json
\uff08\u6df1\u5ea6\u53c2\u6570\uff09\u3002sparse/0/test.txt
\uff08\u6d4b\u8bd5\u96c6\u5212\u5206\u6587\u4ef6\uff09\u3002transforms_train.json
\u3002transforms_test.json
\u3002white_background
\uff09\u3002Random Point Initialization \u00b7 Issue #39 \u00b7 graphdeco-inria/gaussian-splatting \u00b7 GitHub
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/","title":"Gaussian Splatting \u590d\u73b0","text":"\u7ea6 1407 \u4e2a\u5b57 4 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u590d\u73b0
#\u4e09\u7ef4\u91cd\u5efa
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#gaussian-splatting","title":"Gaussian Splatting \u590d\u73b0","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#_1","title":"\u5b98\u65b9\u6570\u636e\u96c6\u590d\u73b0","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#prepare","title":"prepare","text":"Text Onlygit clone https://github.com/graphdeco-inria/gaussian-splatting --recursive\nconda env create --file environment.yml\nconda activate gaussian_splatting\n
python train.py -s ./data/tandt/train/ -m ./output/train/ --eval\n\nOptimizing ./output/train/\nOutput folder: ./output/train/ [31/12 20:58:06]\nTensorboard not available: not logging progress [31/12 20:58:06]\n------------LLFF HOLD------------- [31/12 20:58:08]\nReading camera 301/301 [31/12 20:58:08]\nConverting point3d.bin to .ply, will happen only the first time you open the scene. [31/12 20:58:08]\nLoading Training Cameras [31/12 20:58:09]\nLoading Test Cameras [31/12 20:58:19]\nNumber of points at initialisation : 182686 [31/12 20:58:20]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2589 | 7000/30000 [02:04<07:36, 50.34it/s, Loss=0.0985708, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.07567951896865116 PSNR 19.8115311672813 [31/12 21:00:25]\n\n[ITER 7000] Evaluating train: L1 0.05251172706484795 PSNR 21.924707794189455 [31/12 21:00:25]\n\n[ITER 7000] Saving Gaussians [31/12 21:00:25]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [10:58<00:00, 45.54it/s, Loss=0.0425664, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating test: L1 0.05784237639684426 PSNR 22.03640069459614 [31/12 21:09:19]\n\n[ITER 30000] Evaluating train: L1 0.025540136173367502 PSNR 27.51155662536621 [31/12 21:09:19]\n\n[ITER 30000] Saving Gaussians [31/12 21:09:19]\n\nTraining complete. [31/12 21:09:28]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#render","title":"render","text":"Text Onlypython render.py -m ./output/train/\n\nLooking for config file in ./output/train/cfg_args\nConfig file found: ./output/train/cfg_args\nRendering ./output/train/\nLoading trained model at iteration 30000 [31/12 21:14:40]\n------------LLFF HOLD------------- [31/12 21:14:41]\nReading camera 301/301 [31/12 21:14:41]\nLoading Training Cameras [31/12 21:14:41]\nLoading Test Cameras [31/12 21:14:53]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 263/263 [01:41<00:00, 2.58it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 38/38 [00:15<00:00, 2.42it/s]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#evaluate","title":"evaluate","text":"Text Onlypython metrics.py -m ./output/train/\n\nScene: ./output/train/\nMethod: ours_30000\nMetric evaluation progress: 0%| | 0/38 [00:00<?, ?it/s]Downloading: \"https://download.pytorch.org/models/vgg16-397923af.pth\" to /home/fanghaotian/.cache/torch/hub/checkpoints/vgg16-397923af.pth\n100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 528M/528M [00:28<00:00, 19.4MB/s]\nDownloading: \"https://raw.githubusercontent.com/richzhang/PerceptualSimilarity/master/lpips/weights/v0.1/vgg.pth\" to /home/fanghaotian/.cache/torch/hub/checkpoints/vgg.pth\n100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 7.12k/7.12k [00:03<00:00, 2.29kB/s]\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 38/38 [07:57<00:00, 12.58s/it] 7.12k/7.12k [00:03<00:00, 2.29kB/s]\n SSIM : 0.8192384\n PSNR : 22.0094910\n LPIPS: 0.1966141\n
\u770b\u8d77\u6765\u6bd4\u8bba\u6587\u91cc\u7684\u6570\u636e\u4f4e\u3002
.\\SIBR_remoteGaussian_app.exe
\u8fdc\u7a0b\u4e0d\u80fd\u7528\uff0c issue \u4e2d\u4e5f\u672a\u89e3\u51b3scp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/ C:\\Users\\fanghaotian\\Desktop\\\n\n./SIBR_gaussianViewer_app -m C:\\Users\\fanghaotian\\Desktop\\data\\82ea91ef-6\\\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#blender","title":"\u7528 blender \u6570\u636e\u96c6","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#prepare_1","title":"prepare","text":"nerf_synthetic/lego
\u90a3\u4e2a\u662f blender \u7684\u683c\u5f0ftree -I \"*.png\"\n.\n\u2514\u2500\u2500 lego\n \u251c\u2500\u2500 test\n \u251c\u2500\u2500 train\n \u251c\u2500\u2500 transforms_test.json\n \u251c\u2500\u2500 transforms_train.json\n \u251c\u2500\u2500 transforms_val.json\n \u2514\u2500\u2500 val\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iterations30000-no-evaluation","title":"Iterations=30000 no evaluation","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#train_1","title":"train","text":"Text Onlypython train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego/\n\nOptimizing ./output/lego/\nOutput folder: ./output/lego/ [01/01 13:31:23]\nTensorboard not available: not logging progress [01/01 13:31:23]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:31:23]\nReading Training Transforms [01/01 13:31:23]\nReading Test Transforms [01/01 13:31:31]\nGenerating random point cloud (100000)... [01/01 13:31:38]\nLoading Training Cameras [01/01 13:31:39]\nLoading Test Cameras [01/01 13:31:53]\nNumber of points at initialisation : 100000 [01/01 13:31:53]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7000/30000 [01:15<04:12, 91.02it/s, Loss=0.0152277, Depth Loss=0.0000000]\n[ITER 7000] Evaluating train: L1 0.3646775007247925 PSNR 5.983335494995117 [01/01 13:33:09]\n\n[ITER 7000] Saving Gaussians [01/01 13:33:09]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [05:26<00:00, 91.97it/s, Loss=0.0105094, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating train: L1 0.6417351365089417 PSNR 2.185275435447693 [01/01 13:37:19]\n\n[ITER 30000] Saving Gaussians [01/01 13:37:19]\n\nTraining complete. [01/01 13:37:21]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#render_1","title":"render","text":"Text Onlypython render.py -m ./output/lego/\n\nLooking for config file in ./output/lego/cfg_args\nConfig file found: ./output/lego/cfg_args\nRendering ./output/lego/\nLoading trained model at iteration 30000 [01/01 13:41:14]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:41:14]\nReading Training Transforms [01/01 13:41:14]\nReading Test Transforms [01/01 13:41:20]\nLoading Training Cameras [01/01 13:41:28]\nLoading Test Cameras [01/01 13:41:44]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 300/300 [01:06<00:00, 4.48it/s]\nRendering progress: 0it [00:00, ?it/s]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#metric","title":"metric","text":"Text Onlypython metrics.py -m ./output/lego/\n\nScene: ./output/lego/\nMethod: ours_30000\nMetric evaluation progress: 0it [00:00, ?it/s]\n SSIM : nan\n PSNR : nan\n LPIPS: nan\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#interactive-viewers_1","title":"Interactive Viewers","text":"Text Onlyscp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/lego C:\\Users\\fanghaotian\\Desktop\\\n\n./SIBR_gaussianViewer_app -m C:\\Users\\fanghaotian\\Desktop\\lego\n
\ud83e\udd14\uff0c\u597d\u50cf\u4e00\u5b9a\u8981 --eval\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iteratations30000-evaluation","title":"Iteratations=30000 + evaluation","text":"\u90a3\u4e48\u52a0\u4e0a\u4ee5\u540e\u7528 iterations=300000\uff08default\uff09\u518d\u8dd1\u4e00\u6b21\u3002
Text Onlypython train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego_eval/ --eval\n\nOptimizing ./output/lego_eval/\nOutput folder: ./output/lego_eval/ [01/01 13:43:45]\nTensorboard not available: not logging progress [01/01 13:43:45]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:43:45]\nReading Training Transforms [01/01 13:43:45]\nReading Test Transforms [01/01 13:43:51]\nLoading Training Cameras [01/01 13:43:58]\nLoading Test Cameras [01/01 13:44:06]\nNumber of points at initialisation : 100000 [01/01 13:44:12]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7000/30000 [01:24<04:48, 79.82it/s, Loss=0.0153927, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.34677238538861277 PSNR 6.254974584579468 [01/01 13:45:38]\n\n[ITER 7000] Evaluating train: L1 0.3650033831596375 PSNR 5.939675426483155 [01/01 13:45:38]\n\n[ITER 7000] Saving Gaussians [01/01 13:45:38]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [05:47<00:00, 86.33it/s, Loss=0.0095609, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating test: L1 0.557637879550457 PSNR 3.0822176444530487 [01/01 13:50:00]\n\n[ITER 30000] Evaluating train: L1 0.5475435316562652 PSNR 3.064222288131714 [01/01 13:50:00]\n\n[ITER 30000] Saving Gaussians [01/01 13:50:00]\n\nTraining complete. [01/01 13:50:04]\n\n\npython render.py -m ./output/lego_eval/\n\nLooking for config file in ./output/lego_eval/cfg_args\nConfig file found: ./output/lego_eval/cfg_args\nRendering ./output/lego_eval/\nLoading trained model at iteration 30000 [01/01 13:51:20]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:51:20]\nReading Training Transforms [01/01 13:51:20]\nReading Test Transforms [01/01 13:51:26]\nLoading Training Cameras [01/01 13:51:33]\nLoading Test Cameras [01/01 13:51:40]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:25<00:00, 3.94it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [00:48<00:00, 4.13it/s]\n\n\npython metrics.py -m ./output/lego_eval/\n\nScene: ./output/lego_eval/\nMethod: ours_30000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [04:00<00:00, 1.20s/it]\n SSIM : 0.2604475\n PSNR : 3.0649595\n LPIPS: 0.5116847\n
\u770b\u8d77\u6765\u6548\u679c\u4e0d\u592a\u597d\u3002 \u5e94\u8be5\u662f\u521d\u59cb\u5316\u7684\u95ee\u9898\uff0cL1 \u751a\u81f3\u8fd8\u662f\u4e0a\u6b21\u7684 10 \u500d, Evaluating train: L1 0.5475435316562652 PSNR 3.064222288131714
\u3002
\u628a iterations \u8c03\u5230 100000 \u518d\u6765\u4e00\u6b21\uff0c\u770b\u770b\u6536\u655b\u60c5\u51b5\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iterations100000-evaluation","title":"Iterations=100000 + evaluation","text":"Text Only python train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego_eval_100000/ --iterations 100000 --eval\n\nOptimizing ./output/lego_eval_100000/\nOutput folder: ./output/lego_eval_100000/ [01/01 14:00:46]\nTensorboard not available: not logging progress [01/01 14:00:46]\nFound transforms_train.json file, assuming Blender data set! [01/01 14:00:46]\nReading Training Transforms [01/01 14:00:46]\nReading Test Transforms [01/01 14:00:53]\nLoading Training Cameras [01/01 14:01:00]\nLoading Test Cameras [01/01 14:01:08]\nNumber of points at initialisation : 100000 [01/01 14:01:15]\nTraining progress: 7%|\u2588\u2588\u2588\u2588\u2588\u2589 | 7000/100000 [01:23<17:42, 87.50it/s, Loss=0.0159089, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.34856061153113843 PSNR 6.298382818698883 [01/01 14:02:40]\n\n[ITER 7000] Evaluating train: L1 0.36839944720268253 PSNR 5.857858657836914 [01/01 14:02:40]\n\n[ITER 7000] Saving Gaussians [01/01 14:02:40]\nTraining progress: 30%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2589 | 29990/100000 [05:45<10:51, 107.52it/s, Loss=0.0095307, Depth Loss=0.0000000]\n[ITER 30000] Evaluating test: L1 0.6024469056725502 PSNR 2.6481225460767748 [01/01 14:07:02]\n\n[ITER 30000] Evaluating train: L1 0.5561836898326874 PSNR 2.9405082702636722 [01/01 14:07:02]\n\n[ITER 30000] Saving Gaussians [01/01 14:07:02]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100000/100000 [16:33<00:00, 100.62it/s, Loss=0.0109117, Depth Loss=0.0000000]\n\n[ITER 100000] Saving Gaussians [01/01 14:17:49]\n\nTraining complete. [01/01 14:17:51]\n
Text Onlypython render.py -m ./output/lego_eval_100000/\nLooking for config file in ./output/lego_eval_100000/cfg_args\nConfig file found: ./output/lego_eval_100000/cfg_args\nRendering ./output/lego_eval_100000/\nLoading trained model at iteration 100000 [01/01 14:21:43]\nFound transforms_train.json file, assuming Blender data set! [01/01 14:21:43]\nReading Training Transforms [01/01 14:21:43]\nReading Test Transforms [01/01 14:21:50]\nLoading Training Cameras [01/01 14:21:57]\nLoading Test Cameras [01/01 14:22:06]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:22<00:00, 4.39it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [00:42<00:00, 4.65it/s]\n
Text Onlypython metrics.py -m ./output/lego_eval_100000/\n\nScene: ./output/lego_eval_100000/\nMethod: ours_100000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [04:03<00:00, 1.22s/it]\n SSIM : 0.2404845\n PSNR : 2.4990394\n LPIPS: 0.5251624\n
\u597d\u50cf\u8bc4\u4f30\u4ecd\u7136\u4e0d\u592a\u884c\uff0c\u8fd8\u8d8a\u8bad\u7ec3\u8d8a\u5dee\u4e86\u3002
Text Onlyscp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/lego_eval_100000/ C:\\Users\\fanghaotian\\Desktop\\\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#blender-colmap","title":"Blender \u8f6c Colmap","text":"colmap automatic_reconstructor --workspace_path . --image_path ./images --sparse 1 --camera_model SIMPLE_PINHOLE --dense 0\n# colmap automatic_reconstructor: \u8fd9\u662f\u8c03\u7528COLMAP\u7a0b\u5e8f\u4e2d\u7684\u81ea\u52a8\u91cd\u5efa\u6a21\u5757\uff0c\u5b83\u4f1a\u81ea\u52a8\u5b8c\u6210\u7279\u5f81\u63d0\u53d6\u3001\u5339\u914d\u3001\u91cd\u6295\u5f71\u8bef\u5dee\u4f18\u5316\u548c\u4e09\u89d2\u5316\u7b49\u6b65\u9aa4\uff0c\u4ee5\u751f\u6210\u573a\u666f\u7684\u7a00\u758f3D\u70b9\u4e91\u6a21\u578b\u3002\n# --workspace_path .: \u6307\u5b9a\u4e86\u5de5\u4f5c\u7a7a\u95f4\u8def\u5f84\u4e3a\u5f53\u524d\u76ee\u5f55(.)\uff0c\u5728\u8fd9\u4e2a\u8def\u5f84\u4e0b\uff0cCOLMAP\u5c06\u5b58\u50a8\u4e2d\u95f4\u7ed3\u679c\u4ee5\u53ca\u6700\u7ec8\u7684\u91cd\u5efa\u8f93\u51fa\u6587\u4ef6\u3002\n# --image_path ./images: \u5b9a\u4e49\u4e86\u56fe\u50cf\u6570\u636e\u96c6\u6240\u5728\u7684\u8def\u5f84\uff0c\u5373\u6240\u6709\u53c2\u4e0e\u91cd\u5efa\u7684\u56fe\u7247\u90fd\u4f4d\u4e8e./images\u76ee\u5f55\u4e0b\u3002\n# --sparse 1: \u8fd9\u4e2a\u53c2\u6570\u8868\u793a\u8fdb\u884c\u7a00\u758f\u91cd\u5efa\uff08\u4e0e\u5bc6\u96c6\u91cd\u5efa\u76f8\u5bf9\uff09\uff0c\u5373\u53ea\u6784\u5efa\u51fa\u573a\u666f\u4e2d\u7684\u5173\u952e\u70b9\u53ca\u5176\u5bf9\u5e94\u5173\u7cfb\uff0c\u5e76\u901a\u8fc7\u8fd9\u4e9b\u4fe1\u606f\u751f\u6210\u4e00\u4e2a\u7531\u7a00\u758f\u70b9\u4e91\u7ec4\u6210\u7684\u4e09\u7ef4\u6a21\u578b\u3002\n# --camera_model SIMPLE_PINHOLE: \u6307\u5b9a\u4f7f\u7528\u7684\u76f8\u673a\u6a21\u578b\u4e3a\u201c\u7b80\u5355\u9488\u5b54\u6a21\u578b\u201d\uff08Simple Pinhole Model\uff09\u3002\u8fd9\u610f\u5473\u7740COLMAP\u5728\u8fdb\u884c\u91cd\u5efa\u65f6\u5c06\u5047\u8bbe\u76f8\u673a\u9075\u5faa\u7684\u662f\u6700\u57fa\u7840\u7684\u51e0\u4f55\u6295\u5f71\u6a21\u578b\uff0c\u5176\u4e2d\u4e0d\u5305\u62ec\u50cf\u5f84\u5411\u7578\u53d8\u8fd9\u6837\u7684\u590d\u6742\u56e0\u7d20\u3002\n# --dense 0\uff0c\u51cf\u5c11\u4e0d\u9700\u8981\u7684\u8ba1\u7b97\u64cd\u4f5c\u3002\n
\u7136\u540e train render metric
Text Only(gaussian_splatting) fanghaotian@rhos-Super-Server:~/3DGS/gaussian-splatting$ python metrics.py -m ./output/lego_colmap/\n\nScene: ./output/lego_colmap/\nMethod: ours_30000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 13/13 [00:23<00:00, 1.83s/it]\n SSIM : 0.2915006\n PSNR : 4.3199711\n LPIPS: 0.4333871\n
\u611f\u89c9\u662f\u8f6c\u6362\u7684\u65f6\u5019\u56fe\u7247\u592a\u5c11\u4e86\uff0c\u7136\u540e\u5c31\u53d8\u5dee\u4e86\u3002render \u7684\u65f6\u5019\u5f88\u5feb\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#ffmpeg","title":"ffmpeg \u7684\u95ee\u9898","text":"ffmpeg: error while loading shared libraries: libopenh264.so.5:-CSDN\u535a\u5ba2
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#_2","title":"\u4ee3\u7801\u89e3\u8bfb","text":"Gaussian_Splatting_Code
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#reference","title":"Reference","text":"\u7ea6 374 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/OCRN/#beyond-object-recognition-a-new-benchmark-towards-object-concept-learning","title":"Beyond Object Recognition: A New Benchmark towards Object Concept Learning","text":"\u6587\u7ae0\u4fe1\u606f Understanding objects is a central building block of AI, especially for embodied AI. Even though object recognition excels with deep learning, current machines struggle to learn higher-level knowledge, e.g., what attributes an object has, and what we can do with it. Here, we propose a challenging Object Concept Learning (OCL) task to push the envelope of object understanding. It requires machines to reason out affordances and simultaneously give the reason: what attributes make an object possess these affordances. To support OCL, we build a densely annotated knowledge base including extensive annotations for three levels of object concept (category, attribute, affordance), and the clear causal relations of three levels. By analyzing the causal structure of OCL, we present a baseline, Object Concept Reasoning Network (OCRN). It leverages concept instantiation and causal intervention to infer the three levels. In experiments, OCRN effectively infers the object knowledge while following the causalities well. Our data and code are available at https://mvig-rhos.com/ocl.
ConclusionIn this work, we introduce object concept learning (OCL) expecting machines to infer affordances and explain what attributes enable an object to possess them. Accordingly, we build an extensive dataset and present OCRN based on casual intervention and instantiation. OCRN achieves decent performance and follows the causalities well. However, OCL remains challenging and would inspire a line of studies on reasoning-based object understanding.
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/OCRN/#model","title":"Model","text":"\u7ea6 1428 \u4e2a\u5b57 7 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#ulip-2-towards-scalable-multimodal-pre-training-for-3d-understanding","title":"ULIP-2: Towards Scalable Multimodal Pre-training for 3D Understanding","text":"\u6587\u7ae0\u4fe1\u606f Recent advancements in multimodal pre-training have shown promising efficacy in 3D representation learning by aligning multimodal features across 3D shapes, their 2D counterparts, and language descriptions. However, the methods used by existing frameworks to curate such multimodal data, in particular language descriptions for 3D shapes, are not scalable, and the collected language descriptions are not diverse. To address this, we introduce ULIP-2, a simple yet effective tri-modal pre-training framework that leverages large multimodal models to automatically generate holistic language descriptions for 3D shapes. It only needs 3D data as input, eliminating the need for any manual 3D annotations, and is therefore scalable to large datasets. ULIP-2 is also equipped with scaled-up backbones for better multimodal representation learning. We conduct experiments on two large-scale 3D datasets, Objaverse and ShapeNet, and augment them with tri-modal datasets of 3D point clouds, images, and language for training ULIP-2. Experiments show that ULIP-2 demonstrates substantial benefits in three downstream tasks: zero-shot 3D classification, standard 3D classification with fine-tuning, and 3D captioning (3D-tolanguage generation). It achieves a new SOTA of 50.6% (top1) on Objaverse-LVIS and 84.7% (top-1) on ModelNet40 in zero-shot classification. In the ScanObjectNN benchmark for standard fine-tuning, ULIP-2 reaches an overall accuracy of 91.5% with a compact model of only 1.4 million parameters. ULIP-2 sheds light on a new paradigm for scalable multimodal 3D representation learning without human annotations and shows significant improvements over existing baselines. The code and datasets are released at https://github.com/salesforce/ULIP.
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#task","title":"Task","text":"\u6bd4\u5982\u8fd9\u5f20\u56fe\uff0c\u539f\u59cb\u6807\u6ce8\u7684\u8bed\u4e49\u4fe1\u606f\u5c31\u4e0d\u592a\u591f\uff0c\u4f46\u662f\u7528 ULIP-2 \u6807\u6ce8\u7684\u5c31\u6bd4\u8f83\u5168\u9762\u3002
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#our-pipeline","title":"Our Pipeline","text":"ULIP-2 \u91c7\u7528\u5927\u578b\u591a\u6a21\u6001\u6a21\u578b\uff0c\u4ece 3D \u5f62\u72b6\u7684\u6574\u4f53\u89d2\u5ea6\u4e3a\u6bcf\u4e2a 2D \u6e32\u67d3\u7684\u56fe\u50cf\u81ea\u52a8\u751f\u6210\u8be6\u7ec6\u63cf\u8ff0\u3002ULIP-2 \u5229\u7528\u9884\u5148\u5bf9\u9f50\u548c\u51bb\u7ed3\u7684\u89c6\u89c9\u8bed\u8a00\u7279\u5f81\u7a7a\u95f4\u6765\u5b9e\u73b0\u4e09\u5143\u4f53\u6a21\u6001\u4e4b\u95f4\u7684\u5bf9\u9f50\uff1a\u6574\u4f53\u6587\u672c\u3001\u56fe\u50cf\u548c 3D \u70b9\u4e91\u3002\u9884\u8bad\u7ec3\u540e\uff0c3D \u7f16\u7801\u5668\u5c06\u7528\u4e8e\u4e0b\u6e38\u4efb\u52a1\u3002
Example ","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#key-insight","title":"Key insight","text":"We present ULIP-2, a novel framework for multimodal 3D representation learning. By leveraging large multimodal models for language description generation and scaling up the multimodal 3D pre-training, ULIP-2 not only addresses the quality and scalability challenges in existing multimodal 3D datasets but also demonstrates significant improvements in all downstream tasks. We also release \"ULIP-Objaverse\" triplets and \"ULIP-ShapeNet\" triplets, two large-scale trimodal datasets to foster further research. Limitations. ULIP-2\u2019s pre-training primarily utilizes object-level 3D shape datasets, which inherently differ from scene-level 3D data in their distribution and complexity. Exploring the application of the ULIP-2 framework to scenelevel 3D data understanding, and leveraging the knowledge learned from object-level 3D data for this purpose, represents a compelling avenue for future research. Broader Impact. ULIP-2 aims to minimize human annotation in 3D multimodal pre-training, reducing labor but potentially impacting low-skilled job markets. This dual impact, a common concern in AI advancements, underscores the need for broader considerations in AI research.
\u7ea6 2374 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 12 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#ai","title":"\u4e00\u4e9b AI \u4e0e\u4e2a\u4eba\u5b66\u4e60\u7684\u601d\u8003","text":"","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#_1","title":"\u4e2a\u4eba\u4f7f\u7528\u60c5\u51b5","text":"\u8ba9\u6211\u4eec\u6765\u7ec6\u5316\u4e00\u4e0b\u8fd9\u4e2a\u95ee\u9898\uff0c\u4e00\u822c\u6765\u8bf4\uff0c\u6211\u4f1a\u6709\u4ee5\u4e0b\u51e0\u79cd\u60c5\u51b5\uff1a
\u4f9d\u8d56 LLM\uff0c\u4f46\u662f\u8981\u610f\u8bc6\u5230\u5b83\u7684\u5c40\u9650\u6027\uff0c\u9519\u8bef\u7684\u5bf9\u8bdd\u5386\u53f2\u4f1a\u8ba9\u5b83\u8d8a\u9519\u8d8a\u8fdc\uff0c\u4f60\u8981\u77e5\u9053\u9002\u65f6\u7684\u91cd\u542f\u5bf9\u8bdd\u6765\u907f\u514d\u201c\u964d\u667a\u201d\u3002
\u6bd4\u5982\u6211\u66fe\u7ecf\u5c1d\u8bd5\u8fd9\u4e2a\u4f7f\u7528\u6280\u5de7\uff0c\u4f46\u662f\u5f88\u96be\u8fbe\u5230\u6bd4\u8f83\u597d\u7684\u6548\u679c\u3002
\u5f15\u7528\u522b\u4eba\u7684\u603b\u7ed3\u6765\u8bf4\uff1a
\u4e00\u3001LLM \u4e0a\u4e0b\u6587\u662f\u53d7\u9650\u7684\uff0c\u4e14\u4e0a\u4e0b\u6587\u8d8a\u591a\uff0c\u5b83\u8d8a\u96be\u6355\u83b7\u5230\u4f60\u7684\u610f\u56fe\u3002 \u4e8c\u3001LLM \u8f93\u51fa\u662f\u4e25\u91cd\u53d7\u9650\u7684\uff0c\u76ee\u524d\u5e38\u7528\u7684\u6700\u591a\u4e3a 8192 Tokens\u3002 \u4e09\u3001\u65e0\u8bba\u662fCursor\u3001Windsurf\u3001Copilot\u8fd8\u662fCline\uff0c\u5b83\u4eec\u90fd\u53ea\u662f\u4f60\u7684\u52a9\u624b\uff0c\u8bf7\u5168\u7a0b\u53c2\u4e0e\u5e76\u628a\u63e1\u4e3b\u5bfc\u6743\u548c\u51b3\u7b56\u6743\u3002
\u6bd4\u65b9\u8bf4\uff1a - \u6211\u4eec\u5e94\u8be5\u8ba9 AI \u5e2e\u52a9\u6211\u4eec\u8bfb\u4ee3\u7801\uff0c\u4ece\u800c\u77e5\u9053\u81ea\u5df1\u5e94\u8be5\u5982\u4f55\u6539\u4ee3\u7801\u3002 - \u800c\u4e0d\u662f\u8ba9\u5b83\u7ed9\u6211\u4eec\u76f4\u63a5\u4fee\u6539\u4ee3\u7801\u3002 - \u6211\u4eec\u5e94\u8be5\u8ba9 AI \u7ed9\u6211\u4eec\u89e3\u91ca\u77e5\u8bc6\u70b9\uff0c\u4e3e\u4f8b\u5b50\uff0c\u4ece\u800c\u8ba9\u6211\u4eec\u66f4\u52a0\u5feb\u901f\u7684\u5438\u6536\u77e5\u8bc6\u3002 - \u800c\u4e0d\u662f\u8ba9\u5b83\u7ed9\u6211\u4eec\u751f\u6210\u7b14\u8bb0\uff0c\u53d6\u4ee3\u81ea\u5df1\u5b66\u4e60\u7684\u8fc7\u7a0b\u3002
\u7528\u4e00\u4e2a\u66f4\u52a0\u5168\u9762\u7684\u4f8b\u5b50\u6765\u8bf4\uff0c\u5982\u679c\u6211\u4eec\u60f3\u8981\u6784\u5efa\u4e00\u4e2a\u7f51\u7ad9\uff0c\u4e0b\u9762\u662f\u4e00\u4e9b\u6700\u4f73\u5b9e\u8df5\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#21","title":"2.1. \u660e\u786e\u5b9a\u4f4d","text":"\u4e00\u5f00\u59cb\u6211\u5c31\u660e\u786e\u4e86\u81ea\u5df1\u7684\u89d2\u8272\u5b9a\u4f4d\uff1a\u4ea7\u54c1\u7ecf\u7406\u3002\u6211\u4e0d\u61c2\u7f16\u7a0b\u8bed\u8a00\u548c\u4ee3\u7801\u5b9e\u73b0\uff0c\u6211\u7684\u804c\u8d23\u5c31\u662f\u8bbe\u8ba1\u6307\u5bfc LLM \u5b9e\u73b0\u9879\u76ee\uff0c\u5728\u8fc7\u7a0b\u4e2d\u901a\u8fc7\u54a8\u8be2\u7ec6\u8282\u518d\u8c03\u6574\u5177\u4f53\u7684\u5b9e\u73b0\u6b65\u9aa4\u3002
\u5728\u95ee\u7b54\u7684\u8fc7\u7a0b\u4e2d\uff0c\u4e00\u5b9a\u8981\u5f53\u4e00\u4e2a\u597d\u5947\u5b9d\u5b9d\uff0c\u4e0d\u505c\u7684\u95ee\u600e\u4e48\u505a\u548c\u4e3a\u4ec0\u4e48\uff0c\u4f60\u8ddf LLM \u5ba2\u6c14\u4ec0\u4e48\uff1f\u4e0d\u61c2\u5c31\u95ee\uff0c\u54ea\u91cc\u4e0d\u4f1a\u95ee\u54ea\u91cc\uff01
\u6211\u4e00\u5f00\u59cb\u5c31\u662f\u4ec0\u4e48\u90fd\u4e0d\u61c2\uff0c\u7136\u540e\u518d\u548c LLM \u7684\u4ea4\u6d41\u57fa\u7840\u4e0a\uff0c\u4ee5\u5b83\u7684\u56de\u7b54\u4f5c\u4e3a\u9636\u68af\u4e00\u6b65\u6b65\u4f18\u5316\u63d0\u95ee\u5185\u5bb9\u3002 \u4e0b\u9762\u662f\u6211\u7684\u7b2c\u4e00\u6b21\u505a\u7f51\u7ad9\u7684\u5bf9\u8bdd\u8fc7\u7a0b\uff1a
\u81f3\u6b64\uff0c\u6211\u5c31\u5b8c\u6210\u4e86 Next. js \u9879\u76ee\u7684\u521b\u5efa\uff0c\u5341\u5206\u949f\u524d\u6211\u4e00\u7a8d\u4e0d\u901a\uff0c\u5341\u5206\u949f\u540e\u6211\u89c9\u5f97\u6211\u5df2\u7ecf\u4e86\u89e3\u4e86\u4e00\u4e2a\u4ea7\u54c1\u7ecf\u7406\u9700\u8981\u638c\u63e1\u7684\u5185\u5bb9\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#22","title":"2.2. \u9879\u76ee\u89c4\u5212","text":"\u5728\u5b9e\u73b0\u9879\u76ee\u524d\u671f\u5c31\u4e00\u5b9a\u8981\u505a\u597d\u89c4\u5212\uff0c\u8fd9\u662f\u4e0e LLM \u914d\u5408\u987a\u5229\u7684\u57fa\u7840\u3002\u4e3a\u4e86\u4e0d\u91cd\u8e48\u9879\u76ee\u6df7\u4e71\uff0c\u65e0\u6cd5\u8c03\u6574\uff0c\u5fc3\u70e6\u610f\u4e71\u7684\u8986\u8f99\uff0c\u5728\u4efb\u4f55\u9879\u76ee\u5f00\u59cb\u524d\uff0c\u6700\u597d\u90fd\u8981\u6839\u636e\u5b9e\u73b0\u96be\u5ea6\uff0c\u82b1\u4e0a\u4e00\u5b9a\u65f6\u95f4\u53bb\u548c LLM \u597d\u597d\u68b3\u7406\u9879\u76ee\u7ed3\u6784\uff0c\u8ba9\u5b83\u4e0d\u8981\u7ed9\u51fa\u5177\u4f53\u4ee3\u7801\u800c\u662f\u7ed9\u51fa\u9879\u76ee\u7684\u76ee\u5f55\u7ed3\u6784\uff0c\u8fd9\u6837\u4f60\u5fc3\u91cc\u5c31\u6709\u6570\uff0c\u4e4b\u540e\u5982\u679c\u51fa\u73b0\u9519\u6f0f\uff0c\u4f60\u4e5f\u80fd\u6839\u636e\u8fd9\u4e2a\u7ed3\u6784\u5355\u72ec\u5411 LLM \u8be2\u95ee\u5177\u4f53\u7ec6\u8282\u3002
\u9879\u76ee\u89c4\u5212\u5c31\u901a\u8fc7 README \u6765\u7f16\u5199\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\u9700\u8981\u6709\uff1a
\u4e4b\u540e\u5c31\u56f4\u7ed5 README \u53bb\u5b9e\u73b0\u5c31\u5fc3\u91cc\u6709\u5e95\u4e86\u3002
\u76ee\u5f55\u7ed3\u6784
\u4e4b\u540e\u57fa\u672c\u90fd\u662f\u8981\u6539\u53d8\u7684\uff0c\u53ea\u662f\u4f5c\u4e3a\u53c2\u8003\uff0c\u4e0d\u7528\u8fc7\u4e8e\u5173\u6ce8\u3002 \u5927\u90e8\u5206\u65f6\u5019\u6211\u4e00\u76f4\u4fee\u6539\u7684\u662f \u9879\u76ee\u529f\u80fd
\uff0c\u6211\u4f1a\u4f7f\u7528 - []
\u6e05\u5355\u6765\u7ba1\u7406\u529f\u80fd\u5b9e\u73b0\u5217\u8868\uff0c\u907f\u514d\u9057\u6f0f\u548c\u5173\u6ce8\u70b9\u504f\u79fb\uff0c\u56e0\u4e3a LLM \u5f88\u8f7b\u6613\u7684\u5c31\u80fd\u5199\u51fa\u8ba9\u4f60\u89c9\u5f97\u8d3c\u725b\u903c\u7684\u4ee3\u7801\uff0c\u4f46\u662f\u5207\u5fcc\u81ea\u6211\u611f\u52a8\uff0c\u5728\u9879\u76ee\u57fa\u7840\u529f\u80fd\u5b9e\u73b0\u524d\uff0c\u4e0d\u8981\u8ba9 LLM \u81ea\u6211\u53d1\u6325\uff0c\u5148\u628a Demo \u5b8c\u6210\u518d\u8bf4\u5176\u4ed6\u3002
\u4e00\u5b9a\u8981\u4f7f\u7528 git \u7ba1\u7406\u4ee3\u7801\uff0c\u7f16\u7a0b\u4e60\u60ef\u51b3\u5b9a\u4e86\u5b9e\u73b0\u6548\u7387\u3002\u6211\u7684\u7ecf\u9a8c\u5c31\u662f\uff1a\u591a\u6682\u5b58\u3001\u52e4\u63d0\u4ea4\u3001\u63a7\u7248\u672c
\u5728\u89c4\u5212\u597d\u9879\u76ee\u7cfb\u7edf\u67b6\u6784\u540e\uff0c\u8ba9 LLM \u5b9e\u73b0\u4e00\u4e2a\u57fa\u7840\u7684\u7f51\u7ad9\u6846\u67b6\uff0c\u6211\u5c31\u4f1a commit \u7b2c\u4e00\u4e2a\u7248\u672c\uff0c\u5728\u8fd9\u4e2a\u57fa\u7840\u4e0a\u8fdb\u884c\u589e\u5220\u6539\u67e5\u3002\u56e0\u4e3a\u4f7f\u7528 LLM \u7f16\u5199\u4ee3\u7801\uff0c\u6700\u5fcc\u8bb3\u4e00\u53e3\u6c14\u7528 LLM \u5b9e\u73b0\u592a\u591a\u529f\u80fd\uff0c\u5bfc\u81f4\u51fa\u73b0\u95ee\u9898\u4e86\u79ef\u91cd\u96be\u8fd4\u8eab\u5fc3\u4ff1\u75b2\u3002
\u6bcf\u6b21\u5728\u8fdb\u884c\u5927\u89c4\u6a21\u6539\u52a8\u6216\u8005\u662f\u8c03\u6574\u529f\u80fd\u4e4b\u524d\uff0c\u4e00\u5b9a\u8981\u53bb\u4f7f\u7528 Stage All Changes
\u6682\u5b58\u6539\u52a8\uff0c\u907f\u514d\u5f71\u54cd\u4e86\u672c\u6765\u5df2\u7ecf\u5b9e\u73b0\u7684\u4ee3\u7801\u3002
\u5e76\u4e14\u4e00\u5b9a\u8981\u505a\u597d\u529f\u80fd\u62c6\u5206\uff0c\u514b\u5236\u514b\u5236\u518d\u514b\u5236\uff0c\u53ea\u8981\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5c31\u63d0\u4ea4\uff0c\u4e0d\u7136\u7275\u4e00\u53d1\u800c\u52a8\u5168\u8eab\uff0c\u8d8a\u6539\u8d8a\u4e71\u3002\u6211\u5df2\u7ecf\u5728\u8fd9\u4e0a\u9762\u5403\u4e8f\u592a\u591a\u6b21\u4e86\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#23","title":"2.3. \u62c6\u5206\u6a21\u5757","text":"\u62ff\u7f51\u7ad9\u6765\u4e3e\u4f8b\uff0c\u62c6\u5206\u6a21\u5757\u5c31\u662f\u62bd\u6837\u4ee3\u7801\u529f\u80fd\uff0c\u6bd4\u5982\u5728 page \u4e2d\u6709\u4e24\u4e2a\u90e8\u5206\uff1a\u9876\u680f\u548c\u5185\u5bb9\u533a\u57df\uff0c\u90a3\u4e48\u6211\u4eec\u6700\u597d\u62c6\u5206\u51fa HeadBar.tsx
\u4e13\u95e8\u8d1f\u8d23\u9876\u680f\u7684\u903b\u8f91\uff1b\u7136\u540e\u5728\u9876\u680f\u4e2d\u6709\u5934\u50cf\u3001\u4e3b\u9875\u6309\u94ae\u3001logo \u4e09\u90e8\u5206\uff0c\u90a3\u4e48\u6211\u5c31\u62c6\u5206\u51fa\uff1a Avatar.tsx
\u3001 HomeButton.tsx
\u3001 Logo.tsx
\uff0c\u5206\u522b\u8d1f\u8d23\u81ea\u5df1\u7ec4\u4ef6\u7684\u529f\u80fd\u3002
\u6309\u7167\u8fd9\u4e2a\u601d\u8def\uff0c\u8fd8\u53ef\u4ee5\u62c6\u5206\u529f\u80fd\u903b\u8f91\uff0c\u6bd4\u5982\u521b\u5efa\u7f51\u7edc\u8bf7\u6c42\u7ec4\u4ef6\u3001\u8def\u7531\u8c03\u7528\u5207\u7247\u3001\u5de5\u5382\u6a21\u5f0f\u7ec4\u4ef6\u7b49\uff0c\u4e0d\u8981\u770b\u540d\u5b57\u9ad8\u5927\u4e0a\u542c\u4e0d\u61c2\uff0c\u5b9e\u9645\u4e0a\u8fd9\u4e9b\u90fd\u662f LLM \u4f1a\u5728\u5b9e\u73b0\u8fc7\u7a0b\u4e2d\u81ea\u7136\u5448\u73b0\u7684\u903b\u8f91\uff0c\u76ee\u7684\u5c31\u662f\u4e3a\u4e86\u62bd\u6837\u4ee3\u7801\uff0c\u907f\u514d\u91cd\u590d\u5b9e\u73b0\u548c\u65b9\u4fbf\u7edf\u4e00\u7ba1\u7406\u3002
\u5c3d\u53ef\u80fd\u4fdd\u8bc1\u6bcf\u4e2a\u6587\u4ef6\u53ea\u8d1f\u8d23\u5355\u72ec\u7684\u6a21\u5757\u529f\u80fd\uff0c\u4ee3\u7801\u884c\u6570\u63a7\u5236\u5728 200 \u884c\u4ee5\u5185\u3002
\u4e0d\u8981\u5acc\u9ebb\u70e6\uff0c\u521b\u5efa\u6587\u4ef6\u4e0d\u9700\u8981\u81ea\u5df1\u52a8\u624b\uff0c\u76f4\u63a5\u8ba9 LLM \u5e2e\u4f60\u62c6\u5206\u5b9e\u73b0\uff0c\u4f60\u70b9\u51fb Apply
\u6309\u94ae\u5b83\u5c31\u4f1a\u81ea\u52a8\u521b\u5efa\u5e76\u586b\u5165\u4ee3\u7801\u3002
\u8fd9\u662f\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u4e60\u60ef\uff0c\u5148\u6267\u884c\uff0c\u7b49\u56de\u8fc7\u5934\u6765\u4f60\u81ea\u7136\u4f1a\u610f\u8bc6\u5230\u5b83\u7684\u4ef7\u503c\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#24","title":"2.4. \u521b\u5efa\u65b0\u5bf9\u8bdd\uff0c\u7cbe\u7b80\u4e0a\u4e0b\u6587","text":"\u4e0a\u4e0b\u6587\u957f\u5ea6\u76f4\u63a5\u51b3\u5b9a\u4e86 LLM \u56de\u7b54\u7684\u8d28\u91cf\u3002
\u4e3a\u4e86\u6700\u597d\u7684\u56de\u7b54\u6548\u679c\uff0c\u6211\u4f1a\u5c3d\u53ef\u80fd\u7684\u907f\u514d\u8fc7\u957f\u7684\u5bf9\u8bdd\u5185\u5bb9\uff0c\u5e76\u4e14\u4fdd\u8bc1\u4e00\u6b21\u5bf9\u8bdd\u53ea\u89e3\u51b3\u4e00\u4e2a\u95ee\u9898\uff0c\u4e4b\u540e\u8fd8\u53ef\u4ee5\u901a\u8fc7\u56de\u770b\u5bf9\u8bdd\u5386\u53f2\u6765\u67e5\u7f3a\u8865\u6f0f\u3002
\u4e0a\u9762\u62c6\u5206\u6a21\u5757\u4e5f\u80fd\u6781\u5927\u7684\u51cf\u5c11\u4e0a\u4e0b\u6587\uff0c\u4f60\u53ea\u9700\u8981\u6dfb\u52a0\u76f8\u5173\u7684\u4ee3\u7801\uff0c\u5bf9\u8bdd\u5373\u53ef\u89e3\u51b3\u9700\u6c42\uff0c\u800c\u4e0d\u9700\u8981\u6bcf\u6b21\u643a\u5e26\u591a\u4f59\u7684\u4ee3\u7801\u8fdb\u884c\u63d0\u95ee\u3002
\u5982\u679c\u5728\u4e00\u6b21\u5bf9\u8bdd\u4e2d\uff0c\u4e00\u76f4\u6ca1\u6709\u89e3\u51b3\u95ee\u9898\uff0c\u6700\u597d\u521b\u5efa\u65b0\u5bf9\u8bdd\uff0c\u9000\u540e\u4e00\u6b65\uff0c\u8ba9 LLM \u4ece\u66f4\u591a\u7684\u89d2\u5ea6\u53bb\u601d\u8003\u95ee\u9898\u51fa\u73b0\u5728\u54ea\uff0c\u7136\u540e\u4f60\u518d\u6839\u636e\u5b83\u7684\u56de\u7b54\uff0c\u4f9d\u6b21\u63d0\u95ee\u5c1d\u8bd5\u89e3\u51b3\u3002
\u6211\u5728\u5b9e\u73b0 telegram bot \u7684\u65f6\u5019\u5c31\u9047\u5230\u8fc7\u65e0\u6cd5\u542f\u52a8\u673a\u5668\u4eba\u7684\u60c5\u51b5\uff0cLLM \u4e00\u76f4\u6267\u7740\u4e8e\u89e3\u51b3\u65f6\u5ef6\u548c\u65f6\u5e8f\u95ee\u9898\uff0c\u4f46\u662f\u5728\u4e00\u6b21\u56de\u7b54\u4e2d\u5b83\u63d0\u5230\u4e86\u53ef\u80fd\u662f\u4ee3\u7406\u8bbe\u7f6e\u9519\u8bef\uff0c\u6211\u6355\u6349\u5230\u4e86\u8fd9\u4e2a\u7b54\u6848\uff0c\u5e76\u4e14\u9a6c\u4e0a\u5c1d\u8bd5\uff0c\u679c\u7136\u89e3\u51b3\u4e86\u95ee\u9898\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#_4","title":"\u603b\u7ed3","text":"\u4e0d\u5e94\u8be5\u4e0d\u4f7f\u7528 AI\uff0c\u800c\u662f\u4e0d\u8981\u8ba9\u5b83\u4ee3\u66ff\u4f60\u7684\u601d\u8003\u8fc7\u7a0b\u3002\u5bf9\u4e8e\u9879\u76ee / \u4efb\u52a1 / \u95ee\u9898\uff0c\u4f60\u9700\u8981\u81ea\u5df1\u638c\u63a7\uff0c\u5373\uff0c\u4f60\u8981\u77e5\u9053 AI \u7ed9\u4f60\u7684\u56de\u7b54\u6b63\u786e\u4e0e\u5426\u800c\u4e0d\u662f\u4efb\u7531\u5b83\u751f\u6210\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#reference","title":"Reference","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
CS61A\u7ea6 997 \u4e2a\u5b57 36 \u884c\u4ee3\u7801 14 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/15-213/CSAPP/#1","title":"1 \u8ba1\u7b97\u673a\u7cfb\u7edf\u6f2b\u6e38","text":""},{"location":"CS_Basic/15-213/CSAPP/#2","title":"2 \u4fe1\u606f\u7684\u8868\u793a\u548c\u5904\u7406","text":"#include <stdio.h>\n\n\n\ntypedef unsigned char *byte_pointer;\n\nvoid show_bytes(byte_pointer start, size_t len) {\n\u00a0 size_t i;\n\u00a0 for (i = 0; i < len; i++)\n\u00a0 \u00a0 printf(\" %.2x\", start[i]);\n\u00a0 printf(\"\\n\");\n}\n\nvoid show_int(int x) { show_bytes((byte_pointer)&x, sizeof(int)); }\n\nvoid show_float(float x) { show_bytes((byte_pointer)&x, sizeof(float)); }\n\nvoid show_pointer(void *x) { show_bytes((byte_pointer)&x, sizeof(void *)); }\n\nvoid test_show_bytes(int val) {\n\u00a0 int ival = val;\n\u00a0 float fval = (float)ival;\n\u00a0 int *pval = &ival;\n\u00a0 show_int(ival);\n\u00a0 show_float(fval);\n\u00a0 show_pointer(pval);\n}\n\nint main() {\n\u00a0 int val = 12345;\n\u00a0 test_show_bytes(val);\n\u00a0 return 0;\n}\n
Text Only 39 30 00 00 //\u5c0f\u7aef\u6cd5\n 00 e4 40 46\n 8c f6 bf ef b4 00 00 00\n
"},{"location":"CS_Basic/15-213/CSAPP/#214","title":"2.1.4 \u8868\u793a\u5b57\u7b26\u4e32","text":""},{"location":"CS_Basic/15-213/CSAPP/#215","title":"2.1.5 \u8868\u793a\u4ee3\u7801","text":"x>>k
\u662f\u7b97\u6570\u53f3\u79fb\uff0c x>>>k
\u662f\u903b\u8f91\u53f3\u79fb\\(\\displaystyle \u51fd\u6570B2T_w\u662f\u4e00\u4e2a\u53cc\u5c04\u3002\\)
\u53cd\u7801
\u7ea6 2520 \u4e2a\u5b57 489 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 19 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#0-c","title":"0 \u5f00\u59cb\u5b66\u4e60 C++","text":"C++#include <iostream>\n\nint main()\n{\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#01","title":"0.1 \u6ce8\u91ca","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#02-displaystyle-include","title":"0.2 \\(\\displaystyle \\#\\)include \u6307\u4ee4","text":"(std::cout << \"Hello, World!\") << std::endl\n
#include <iostream>\n#include <string>\n\nint main() \n{\n std::cout << \"Please enter your first name:\";\n\n std::string name;\n std::cin >> name;\n\n std::cout << \"Hello\" << name << \"!\" << std::endl;\n return 0;\n}\n
std::string stars(10, '*')\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#13","title":"1.3 \u5c0f\u7ed3","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2","title":"2 \u5faa\u73af\u548c\u8ba1\u6570","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#21","title":"2.1 \u95ee\u9898","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#22","title":"2.2 \u7a0b\u5e8f\u7684\u6574\u4f53\u7ed3\u6784","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#23","title":"2.3 \u8f93\u51fa\u6570\u76ee\u672a\u77e5\u7684\u884c","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#231-while","title":"2.3.1 while \u8bed\u53e5","text":"const std::string::size_type cols = greeting.size() + pad * 2 + 2;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#241","title":"2.4.1 \u8f93\u51fa\u8fb9\u754c\u5b57\u7b26","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2411-if","title":"2.4.1.1 if \u8bed\u53e5","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2412","title":"2.4.1.2 \u903b\u8f91\u8fd0\u7b97\u7b26","text":"for (int r = 0; r != rows; ++r) {\n\n}\n
for (init-statement condition; expression)\n statement\n\n#equals to\n\n{\n inti-statement\n while (condition) {\n statement\n expression;\n }\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#253","title":"2.5.3 \u538b\u7f29\u68c0\u6d4b","text":"#include <iomanip>\n#include <ios>\n#include <iostream>\n#include <string>\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::precision;\n\nint main() {\n cout << \"Please enter your first name:\";\n string name;\n cin >> name;\n cout << \"Hello, \" << name << \"!\" << endl;\n\n cout << \"Please enter your midterm and final exam grades:\";\n double midterm, final;\n cin >> midterm >> final;\n\n cout << \"Enter all your homework grades, \" \n \"followed by end-of-file:\";\n\n int count = 0;\n double sum = 0;\n\n double x;\n\n while (cin >> x) {\n ++ count;\n sum += x;\n }\n\n streamsize prec = cout.precision();\n cout << \"Your final grade is \" << setprecision(3)\n << 0.2 * midterm + 0.4 * final + 0.4 * sum / count\n << setprecision(prec) << endl; //\u91cd\u7f6e\u6709\u6548\u4f4d\u6570 \u6216\u5199\u6210cout.precision(prec);\n return 0;\n}\n
\u4e0d\u662f\u5f88\u61c2
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#32","title":"3.2 \u7528\u4e2d\u503c\u4ee3\u66ff\u5e73\u5747\u503c","text":"\u90a3\u4e48\u5c31\u8981\u6392\u5e8f\u4e86
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#321","title":"3.2.1 \u628a\u6570\u636e\u96c6\u5408\u5b58\u50a8\u5728\u5411\u91cf\u4e2d","text":"C++double x;\nvector<double> homework;\n\nwhile(cin >> x)\n homework.push_back(x);\n
typedef vector<double>::size_type vec_sz;\nvec_sz size = homework.size();\n
if (size == 0) {\n cout << endl << \"You must enter your grades. \"\n \"Please try again.\" << endl;\n return 1;\n}\n\nsort (homework.begin(), homework.end());\n\nvec_sz mid = size / 2;\ndouble median;\nmedian = size % 2 == 0 ? (homework[mid] + homework[mid - 1]) / 2\n : homework[mid];\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#323","title":"3.2.3 \u4e00\u4e9b\u66f4\u4e3a\u6df1\u5165\u7684\u89c2\u5bdf","text":"double median(vector<double> vec)\n{\n typedef vector<double>::size_type vec_sz;\n vec_sz size = vec.size();\n if (size == 0)\n throw domain_error(\"median of an empty vector\");\n sort(vec.begin(), vec.end());\n vec_sz mid = size / 2;\n return size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];\n}\n
istream read_hw(istream& in, vector<double>& hw)\n{\n if (in) {\n hw.clear();\n double x;\n while (in >> x) \n hw.push_back(x);\n in.clear();\n }\n return in;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#414","title":"4.1.4 \u4e09\u79cd\u51fd\u6570\u53c2\u6570","text":"struct Student_info {\n string name;\n double midterm, final;\n vector<double> homework;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#422","title":"4.2.2 \u5904\u7406\u5b66\u751f\u8bb0\u5f55","text":"C++istream& read(istream& is, Student_info& s)\n{\n is >> s.name >> s.midterm >> s.final;\n read_hw(is, s.homework);\n return is;\n}\n\ndouble grade(const Student_info& s) \n{\n return grade(s.midterm, s.final, s.homework);\n}\n\nbool compare(const Student_info& x, const Studeng_info& y)\n{\n return x.name < y.name;\n}\n\nsort(students.begin(), students.end(), compare;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#423","title":"4.2.3 \u751f\u6210\u62a5\u8868","text":"C++cout << setw(maxlen + 1) << student[i].name;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#43","title":"4.3 \u628a\u5404\u90e8\u5206\u4ee3\u7801\u8fde\u63a5\u5230\u4e00\u8d77","text":"Text Only#ifndef GUARD_median_h\n#define GUARD_median_h //\u9884\u5904\u7406\u7a0b\u5e8f\n\n#include <vector>\ndouble median(vector<double>);\n\n#endif\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#44","title":"4.4 \u628a\u8ba1\u7b97\u6210\u7ee9\u7684\u7a0b\u5e8f\u5206\u5757","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#45","title":"4.5 \u4fee\u6b63\u540e\u7684\u8ba1\u7b97\u6210\u7ee9\u7684\u7a0b\u5e8f","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#46","title":"4.6 \u5c0f\u7ed3","text":"try{\n} catch (t) { }\n
vector<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> pass, fail;\n for (vector<Student_info>::size_type i = 0; i != students.size(); ++i;)\n if (fgrade(student[i]))\n fail.push_back(student[i]);\n else\n pass.push_back(student[i]);\n students = pass;\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#511","title":"5.1.1 \u5c31\u5730\u5220\u9664\u51fd\u6570","text":"C++vector<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> fail;\n vector<Student_info>::size_type i = 0;\n while (i != students.size()) {\n if (fgrade(studentp[i])) {\n fail.push_back(students[i]);\n students.erase(students.begin() + i);\n } else\n ++i;\n }\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#512","title":"5.1.2 \u987a\u5e8f\u5b58\u53d6\u4e0e\u968f\u673a\u5b58\u53d6","text":"for (vector<Student_info>::size_type i = 0; i != students.end(); ++i)\n cout << students[i].name << endl;\nfor (vector<Student_info>::const_iterator iter = students.begin();\n iter != students.end(); ++iter) {\n cout << (*iter).name << endl; }\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#521","title":"5.2.1 \u8fed\u4ee3\u5668\u7c7b\u578b","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#522","title":"5.2.2 \u8fed\u4ee3\u5668\u64cd\u4f5c","text":"(*iter).name\niter->name\n//both are ok\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#524-students-erase-students-begin-i","title":"5.2.4 students. erase (students. begin () + i) \u7684\u542b\u4e49","text":"vecotr<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> fail;\n vector<Student_info>::iterator iter = students.begin();\n while (iter != students.end()) {\n if (fgrade(*iter)) {\n fail.push_back(*iter);\n iter = students.erase(iter); //important\n } else\n ++iter;\n }\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#54","title":"5.4 \u91cd\u65b0\u601d\u8003\u6570\u636e\u7ed3\u6784\u4ee5\u5b9e\u73b0\u66f4\u597d\u7684\u6027\u80fd","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#55-list","title":"5.5 list \u7c7b\u578b","text":"vector<string> split(const string& s)\n{\n vector<string> ret;\n typedef string::size_def string_size;\n string_size i = 0;\n while (i != s.size()) {\n while (i != s.size() && isspace(s[i])) // is from <cctype>\n ++i;\n string_size j = i;\n while (j != s.size() && !isspace(s[i]))\n ++j;\n if (i != j) {\n ret.push_back(s.substr(i, j - i));\n i = j;\n }\n }\n return ret;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#57-split","title":"5.7 \u6d4b\u8bd5 split \u51fd\u6570","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#58","title":"5.8 \u8fde\u63a5\u5b57\u7b26\u4e32","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#581","title":"5.8.1 \u4e3a\u56fe\u6848\u88c5\u6846","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#582","title":"5.8.2 \u7eb5\u5411\u8fde\u63a5","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#583","title":"5.8.3 \u6a2a\u5411\u8fde\u63a5","text":"TODO
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#59","title":"5.9 \u5c0f\u7ed3","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#6","title":"6 \u4f7f\u7528\u5e93\u7b97\u6cd5","text":"for (vector<string>::const_iterator it = bottom.begin(); it != bottom.end(); ++i)\n ret.push_back(*it);\n\nret.insert(ret.end(), bottom.begin(), bottom.end());\n\ncopy(bottom.begin(), bottom.end(), back_inserter(ret));\n
copy(begin, end, out);\n//equals to\nwhile (begin != end)\n *out++ = *begin++;\n // equals to \n // *out = *begin; ++out; ++begin;\n\nit = begin++;\n//equals to\nit = begin;\n++begin;\n
bool space(char c) {\n return isspace(c);\n}\nbool not_space(char c) {\n return !isspace(c);\n}\nvector<string> split(const string& str) {\n typedef string::const_iterator iter;\n vector<string> ret;\n iter i = str.begin();\n while(i != str.end()) {\n i = find_if(i, str.end(), not_space);\n iter j = find_if(i, str.end(), space);\n if (i != str.end()) ret.push_back(string(i, j));\n i = j; \n }\n return ret;\n}\n
bool is_palindrome(const string& s) {\n return equal(s.begin(), s.end(), s.rbegin());\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#613-url","title":"6.1.3 \u67e5\u627e URL","text":"vector<string> find_urls(const string& s) {\n vector<string> ret;\n typedef string::const_iterator iter;\n iter b = s.begin(), e = s.end();\n while (b != e) {\n b = url_beg(b, e);\n if (b != e) {\n iter after = url_end(b, e);\n ret.push_back(string(b, after));\n b = after;\n }\n }\n return ret;\n}\n\nstring::const_iterator url_end(string::const_iterator b, string::const_iterator e) {\n return find_if(b, e, not_url_char);\n}\n\nbool not_url_char(char c) {\n static const string url_ch = \"~;/?@=&$-_.+!*{},'\";\n return !(isalnum(c)) || find(url_ch.begin(), url_ch.end(), c) != url_end());\n //static\u58f0\u660e\u7684\u5c40\u90e8\u53d8\u91cf\u5177\u6709\u5168\u5c40\u5bff\u547d\uff0c\u751f\u5b58\u671f\u8d2f\u7a7f\u6574\u4e2a\u51fd\u6570\u8c03\u7528\u8fc7\u7a0b\n}\n\nstring::const_iterator url_beg(string::const_iterator b, string::const_iterator e) {\n static const string sep = \"://\";\n typedef string::const_iterator iter;\n iter i = b;\n while ((i = search(i, e, sep.begin(), sep.end())) != e) {\n if (i != b && i + sep.size() != e) {\n iter beg = i;\n while (beg != b && isalpha(beg[-1]))\n --beg;\n if (beg != i && i + sep.size() != e && !not_url_char(i[sep.size()])) return beg;\n }\n if (i != e) i += sep.size();\n }\n return e;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#62","title":"6.2 \u5bf9\u8ba1\u7b97\u6210\u7ee9\u7684\u65b9\u6848\u8fdb\u884c\u6bd4\u8f83","text":"bool did_all_hw(const Student_info& s) {\n reutrn ((fint(s.homework.begin(), s.homework.end(), 0)) == s.homework.end());\n}\n\nvector<Student_info> did, didnt;\nStudent_info student;\n\nwhile (read(cin, student)) {\n if (did_all_hw(student))\n did.push_back(student);\n else\n didnt.push_back(student);\n}\nif (did.empty()) {\n cout << \"No student did all the homework!\" << endl;\n return 1;\n}\nif (didnt.empty()) {\n cout << \"Every student did all the homework!\" << endl;\n return 1;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#622","title":"6.2.2 \u5206\u6790\u6210\u7ee9","text":"C++write_analysis(cout, \"median\", median_analysis, did, didn't);\n\ndouble grade_aux(const Student_info& s) {\n tru {\n return grade(s);\n } catch (domain_error) {\n return grade(s.midterm, s.final, 0);\n }\n}\n\ndouble median_analysis(const vector<Student_info>& students) {\n vector<double> grades;\n transdorm(students.begin(), students.end(), back_inserter(grades), grade_aux);\n return medina(grades);\n}\n\nvoid write_analysis(ostream& out, const string& name, double analysis(const vector<Student_info>&), const vector<Student_info>& did, const vector<Student_info>& didnt) {\n out << name << \": median(did) = \" << analysis(did) << \", median(didnt) = \" << analysis(didnt) << endl; \n}\n\nint main() {\n vector<Student_info> did, didnt;\n Student_info student;\n while (read(cin, student)) {\n if (did_all_hw(student))\n did.push_back(student);\n else \n didnt.push_back(student);\n }\n if (did.empty()) {\n cout << \"No student did all the homework!\" << endl;\n return 1;\n }\n if (didnt.empty()) {\n cout << \"Every student did all the homework!\" << endl;\n return 1;\n }\n write_analysis(cout, \"median\", median_analysis, did, didnt);\n write_analysis(cout, \"average\", average_analysis, did, didnt);\n write_analysis(cout, \"medina of homework turned in\", optimistic_median_analysis, did, didnt);\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#623","title":"6.2.3 \u8ba1\u7b97\u57fa\u4e8e\u5bb6\u5ead\u4f5c\u4e1a\u5e73\u5747\u6210\u7ee9\u7684\u603b\u6210\u7ee9","text":"C++double average(const vector<double>& v) {\n return accumulate(v.begin(), v.end(), 0.0) / v.size();\n}\n\ndouble average_analysis(const Student_info& s) {\n return grade(s.midterm, s.final, average(s.homework));\n}\n\ndouble average_analysis(const vector<Student_info>& students) {\n vector<double> grades;\n transform(students.begin(), students.end(), back_inserter(grades), average_grade);\n return median(grades);\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#624","title":"6.2.4 \u4e0a\u4ea4\u7684\u5bb6\u5ead\u4f5c\u4e1a\u7684\u4e2d\u503c","text":"C++double optimistic_median(const Student_info& s) {\n vector<double> nonzero;\n remove_copy(s.homework.begin(), s.homework.end(), back_inserter(nonzero), 0);\n if (nonzero.empty())\n return grade(s.midterm, s.final, 0);\n else \n return grade(s.midterm, s.final, median(nonzero));\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#63","title":"6.3 \u5bf9\u5b66\u751f\u8fdb\u884c\u5206\u7c7b\u5e76\u56de\u987e\u4e00\u4e0b\u6211\u4eec\u7684\u95ee\u9898","text":"vector<Student_info> extract_fails(vector<Student_info>& students) {\n vector<Student_info> fail;\n remove_copy_if(students.begin(), students.end(), back_inserter(fail), pgrade);\n students.earse(remove_if(students.begin(), students.end(), fgrade), student.end());\n return fail;\n}\n\nbool pgrade(const Student_info& s) {\n return !fgrade(s);\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#64","title":"6.4 \u4e00\u79cd\u4e00\u6b21\u4f20\u9012\u7684\u89e3\u51b3\u65b9\u6848","text":"C++vector<Student_info> extract_fails(vector<Student_info>& students) {\n vector<Student_info>::iterator iter = stable_partition(students.begin(), students.end(), pgrade);\n vector<Student_info> fail(iter, students.end());\n students.erase(iter, students.end());\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#65","title":"6.5 \u7b97\u6cd5\u3001\u5bb9\u5668\u4ee5\u53ca\u8fed\u4ee3\u5668","text":"int main() {\n string s;\n map<string, int> counters;\n while (cin >> s) ++counters[s];\n for (map<string, int>::const_iterator it = counters.begin(); it != couners.end(); ++it) {\n cout << it->first << \"\\t\" << it->second << endl;\n }\n return 0;\n}\n
map<string, vector<int> > xref(istream& in, vector<string> find_words(const string&) = split) {\n string line;\n int line_number = 0'\n map<string, vector<int>> ret;\n while (getline(in, line)) {\n ++line_number;\n vector<string> words = find_words(line);\n for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it)\n ret(*it).push_back(line_number);\n }\n return ret;\n}\n\n\nint main() {\n map<string, vector<int> > ret = cref(cin);\n for (map<string, vector<int> >::const_iterator it = ret.begin(); it != ret.end(); ++it) {\n cout << it->first << \" occurs on line(s): \";\n vector<int>::const_iterator line_it = it->second.begin();\n cout << *lint_it;\n ++line_it;\n while (line_it != it->second.end()) {\n cout << \", \" << *line_it;\n ++line_it;\n }\n cout << endl;\n }\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#74","title":"7.4 \u751f\u6210\u53e5\u5b50","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#741","title":"7.4.1 \u8868\u793a\u89c4\u5219","text":"C++typedef vector<string> Rule;\ntypedef vector<Rule> Rule_collection;\ntypedef map<string, Rule_collection> Grammer;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#742","title":"7.4.2 \u8bfb\u5165\u6587\u6cd5","text":"C++Grammer read_grammer(istream& in) {\n Grammer ret;\n string line;\n while (getline(in, line)) {\n vector<string> entry = split(line);\n if (!entry.empty())\n ret[entry[0]].push_back(Rule(entry.begin() + 1, entry.end()));\n }\n return ret;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#743","title":"7.4.3 \u751f\u6210\u53e5\u5b50","text":"C++vector<string> gen_sentence(const Grammar& g) {\n vector<string> ret;\n gen_aux(g, \"<sentence>\", ret);\n return ret;\n}\n\nbool bracketed(const string& s) {\n return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';\n}\n\nvoid gen_aux(const Grammar& g, const string& word, vector<string>& ret) {\n if (!bracketed(word)) {\n ret.push_back(word);\n } else {\n Grammar::const_iterator it = g.find(word);\n if (it == g.end())\n throw logic_error(\"empty rule\");\n const Rule_collection& c = it->seond;\n const Rule& r = c[nrand(c.size())];\n for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)\n gen_aux(g, *i, ret);\n }\n}\n\nint main() {\n vector<string> sentence = gen_sentence(read_grammar(cin));\n vector<string>::const_iterator it = sentence.begin();\n if (!sentence.empty()) {\n cout << *it;\n ++it; \n }\n while (it != sentence.end()) {\n cout << \" \" << *it;\n ++it;\n }\n cout << endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#744","title":"7.4.4 \u9009\u62e9\u4e00\u4e2a\u968f\u673a\u51fd\u6570","text":"C++int nrand(int n) {\n if (n <= 0 || n > RAND_MAX)\n throw domain_error(\"Argument to nrand is out of range\");\n const int bucket_size = RAND_MAX / n;\n int r;\n do r = rand() / bucket_size;\n while (r >= n);\n return r;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#75","title":"7.5 \u5173\u4e8e\u6027\u80fd\u7684\u4e00\u70b9\u8bf4\u660e","text":"\u7ea6 3115 \u4e2a\u5b57 523 \u884c\u4ee3\u7801 9 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 22 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#1","title":"1 \u6587\u4ef6\u64cd\u4f5c","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#11","title":"1.1 \u6587\u4ef6\u7684\u6982\u5ff5","text":"FILE* freopen(const char* filename, const char* mode, FILE* stream);\n
filename
: \u8981\u6253\u5f00\u7684\u6587\u4ef6\u540dmode
: \u6587\u4ef6\u6253\u5f00\u7684\u6a21\u5f0f\uff0c\u8868\u793a\u6587\u4ef6\u8bbf\u95ee\u7684\u6743\u9650stream
: \u6587\u4ef6\u6307\u9488\uff0c\u901a\u5e38\u4f7f\u7528\u6807\u51c6\u6587\u4ef6\u6d41 (stdin/stdout
) \u6216\u6807\u51c6\u9519\u8bef\u8f93\u51fa\u6d41 (stderr
)r
\uff1a\u4ee5\u53ea\u8bfb\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u53ea\u5141\u8bb8\u8bfb\u5165\u6570\u636e\u00a0\uff08\u5e38\u7528\uff09r+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636erb
\uff1a\u4ee5\u53ea\u8bfb\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u53ea\u5141\u8bb8\u8bfb\u5165\u6570\u636erb+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ert+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u672c\u6587\u4ef6\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ew
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u4f1a\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u53ea\u5141\u8bb8\u5199\u5165\u6570\u636e\u00a0\uff08\u5e38\u7528\uff09w+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ewb
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u4f1a\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u53ea\u5141\u8bb8\u5199\u5165\u6570\u636ewb+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ea
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e\uff08\u4fdd\u7559 EOF \u7b26\uff09a+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e\uff08\u4e0d\u4fdd\u7559 EOF \u7b26\uff09at+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u672c\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3eab+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e \u4f7f\u7528\u65b9\u5f0f#include <cstdio>\n#include <iostream>\nint mian(void) {\n freopen(\"data.in\", \"r\", stdin); \n // data.in \u5c31\u662f\u8bfb\u53d6\u7684\u6587\u4ef6\u540d\uff0c\u8981\u548c\u53ef\u6267\u884c\u6587\u4ef6\u653e\u5728\u540c\u4e00\u76ee\u5f55\u4e0b\n freopen(\"data.out\", \"w\", stdout); \n // data.out \u5c31\u662f\u8f93\u51fa\u6587\u4ef6\u7684\u6587\u4ef6\u540d\uff0c\u548c\u53ef\u6267\u884c\u6587\u4ef6\u5728\u540c\u4e00\u76ee\u5f55\u4e0b\n fclose(stdin);\n fclose(stdout);\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#132-fopen","title":"1.3.2 fopen \u51fd\u6570","text":"C++FILE* fopen(const char* path, const char* mode)\n
\u4f7f\u7528\u65b9\u5f0f
C++FILE *in, *out; // \u5b9a\u4e49\u6587\u4ef6\u6307\u9488 \nin = fopen(\"data.in\", \"r\"); \nout = fopen(\"data.out\", \"w\"); \n/* do what you want to do */ \nfclose(in); \nfclose(out);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#14-c-ifstreamofstream","title":"1.4 C++ \u7684\u00a0ifstream/ofstream
\u00a0\u6587\u4ef6\u8f93\u5165\u8f93\u51fa\u6d41","text":"C++#include <fstream> \nusing namespace std; \n// \u4e24\u4e2a\u7c7b\u578b\u90fd\u5728 std \u547d\u540d\u7a7a\u95f4\u91cc \nifstream fin(\"data.in\"); \nofstream fout(\"data.out\"); \nint main(void) { \n /* \u4e2d\u95f4\u7684\u4ee3\u7801\u6539\u53d8 cin \u4e3a fin \uff0ccout \u4e3a fout \u5373\u53ef */ \n fin.close(); \n fout.close(); \n return 0; \n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#2","title":"2 \u6807\u51c6\u5e93","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#21-stl","title":"2.1 STL \u5bb9\u5668","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#211","title":"2.1.1 \u5e8f\u5217\u5f0f\u5bb9\u5668","text":"vector
) \u540e\u7aef\u53ef\u9ad8\u6548\u589e\u52a0\u5143\u7d20\u7684\u987a\u5e8f\u8868\u3002array
)C++11\uff0c\u5b9a\u957f\u7684\u987a\u5e8f\u8868\uff0cC \u98ce\u683c\u6570\u7ec4\u7684\u7b80\u5355\u5305\u88c5\u3002deque
) \u53cc\u7aef\u90fd\u53ef\u9ad8\u6548\u589e\u52a0\u5143\u7d20\u7684\u987a\u5e8f\u8868\u3002list
) \u53ef\u4ee5\u6cbf\u53cc\u5411\u904d\u5386\u7684\u94fe\u8868\u3002forward_list
) \u53ea\u80fd\u6cbf\u4e00\u4e2a\u65b9\u5411\u904d\u5386\u7684\u94fe\u8868\u3002set
) \u7528\u4ee5\u6709\u5e8f\u5730\u5b58\u50a8\u00a0\u4e92\u5f02\u00a0\u5143\u7d20\u7684\u5bb9\u5668\u3002\u5176\u5b9e\u73b0\u662f\u7531\u8282\u70b9\u7ec4\u6210\u7684\u7ea2\u9ed1\u6811\uff0c\u6bcf\u4e2a\u8282\u70b9\u90fd\u5305\u542b\u7740\u4e00\u4e2a\u5143\u7d20\uff0c\u8282\u70b9\u4e4b\u95f4\u4ee5\u67d0\u79cd\u6bd4\u8f83\u5143\u7d20\u5927\u5c0f\u7684\u8c13\u8bcd\u8fdb\u884c\u6392\u5217\u3002multiset
) \u7528\u4ee5\u6709\u5e8f\u5730\u5b58\u50a8\u5143\u7d20\u7684\u5bb9\u5668\u3002\u5141\u8bb8\u5b58\u5728\u76f8\u7b49\u7684\u5143\u7d20\u3002map
) \u7531 {\u952e\uff0c\u503c} \u5bf9\u7ec4\u6210\u7684\u96c6\u5408\uff0c\u4ee5\u67d0\u79cd\u6bd4\u8f83\u952e\u5927\u5c0f\u5173\u7cfb\u7684\u8c13\u8bcd\u8fdb\u884c\u6392\u5217\u3002multimap
) \u7531 {\u952e\uff0c\u503c} \u5bf9\u7ec4\u6210\u7684\u591a\u91cd\u96c6\u5408\uff0c\u4ea6\u5373\u5141\u8bb8\u952e\u6709\u76f8\u7b49\u60c5\u51b5\u7684\u6620\u5c04\u3002unordered_set
/unordered_multiset
)C++11\uff0c\u4e0e\u00a0set
/multiset
\u00a0\u7684\u533a\u522b\u5728\u4e8e\u5143\u7d20\u65e0\u5e8f\uff0c\u53ea\u5173\u5fc3\u300c\u5143\u7d20\u662f\u5426\u5b58\u5728\u300d\uff0c\u4f7f\u7528\u54c8\u5e0c\u5b9e\u73b0\u3002unordered_map
/unordered_multimap
)C++11\uff0c\u4e0e\u00a0map
/multimap
\u00a0\u7684\u533a\u522b\u5728\u4e8e\u952e (key) \u65e0\u5e8f\uff0c\u53ea\u5173\u5fc3 \"\u952e\u4e0e\u503c\u7684\u5bf9\u5e94\u5173\u7cfb\"\uff0c\u4f7f\u7528\u54c8\u5e0c\u5b9e\u73b0\u3002\u5bb9\u5668\u9002\u914d\u5668\u5176\u5b9e\u5e76\u4e0d\u662f\u5bb9\u5668\u3002\u5b83\u4eec\u4e0d\u5177\u6709\u5bb9\u5668\u7684\u67d0\u4e9b\u7279\u70b9\uff08\u5982\uff1a\u6709\u8fed\u4ee3\u5668\u3001\u6709\u00a0clear()
\u00a0\u51fd\u6570\u2026\u2026\uff09\u3002
\u300c\u9002\u914d\u5668\u662f\u4f7f\u4e00\u79cd\u4e8b\u7269\u7684\u884c\u4e3a\u7c7b\u4f3c\u4e8e\u53e6\u5916\u4e00\u79cd\u4e8b\u7269\u884c\u4e3a\u7684\u4e00\u79cd\u673a\u5236\u300d\uff0c\u9002\u914d\u5668\u5bf9\u5bb9\u5668\u8fdb\u884c\u5305\u88c5\uff0c\u4f7f\u5176\u8868\u73b0\u51fa\u53e6\u5916\u4e00\u79cd\u884c\u4e3a\u3002
stack
) \u540e\u8fdb\u5148\u51fa (LIFO) \u7684\u5bb9\u5668\uff0c\u9ed8\u8ba4\u662f\u5bf9\u53cc\u7aef\u961f\u5217\uff08deque
\uff09\u7684\u5305\u88c5\u3002queue
) \u5148\u8fdb\u5148\u51fa (FIFO) \u7684\u5bb9\u5668\uff0c\u9ed8\u8ba4\u662f\u5bf9\u53cc\u7aef\u961f\u5217\uff08deque
\uff09\u7684\u5305\u88c5\u3002priority_queue
) \u5143\u7d20\u7684\u6b21\u5e8f\u662f\u7531\u4f5c\u7528\u4e8e\u6240\u5b58\u50a8\u7684\u503c\u5bf9\u4e0a\u7684\u67d0\u79cd\u8c13\u8bcd\u51b3\u5b9a\u7684\u7684\u4e00\u79cd\u961f\u5217\uff0c\u9ed8\u8ba4\u662f\u5bf9\u5411\u91cf\uff08vector
\uff09\u7684\u5305\u88c5\u3002containerName<typeName,...> name
\u00a0\u7684\u5f62\u5f0f\uff0c\u4f46\u6a21\u677f\u53c2\u6570\uff08<>
\u00a0\u5185\u7684\u53c2\u6570\uff09\u7684\u4e2a\u6570\u3001\u5f62\u5f0f\u4f1a\u6839\u636e\u5177\u4f53\u5bb9\u5668\u800c\u53d8\u3002vector<int> data(10);\n\nfor (int i = 0; i < data.size(); i++)\n cout << data[i] << endl;\n\nfor (vector<int>::iterator iter = data.begin(); iter != data.end(); iter++)\n cout << *iter << endl;\n//C++11 \u4ee5\u540e\u53ef\u4ee5\u7528 auto iter = data.begin() \u6765\u7b80\u5316\n
a + n
\u00a0\u6ee1\u8db3\u00a0*(a + n)
\u00a0\u4e0e\u00a0*(std::address_of(*a) + n)
\u00a0\u7b49\u4ef7\uff08\u5373\u8fde\u7eed\u5b58\u50a8\uff0c\u5176\u4e2d\u00a0a
\u00a0\u4e3a\u8fde\u7eed\u8fed\u4ee3\u5668\u3001n
\u00a0\u4e3a\u6574\u578b\u503c\uff09\u3002=
\uff1a\u6709\u8d4b\u503c\u8fd0\u7b97\u7b26\u4ee5\u53ca\u590d\u5236\u6784\u9020\u51fd\u6570\u3002begin()
\uff1a\u8fd4\u56de\u6307\u5411\u5f00\u5934\u5143\u7d20\u7684\u8fed\u4ee3\u5668\u3002end()
\uff1a\u8fd4\u56de\u6307\u5411\u672b\u5c3e\u7684\u4e0b\u4e00\u4e2a\u5143\u7d20\u7684\u8fed\u4ee3\u5668\u3002end()
\u00a0\u4e0d\u6307\u5411\u67d0\u4e2a\u5143\u7d20\uff0c\u4f46\u5b83\u662f\u672b\u5c3e\u5143\u7d20\u7684\u540e\u7ee7\u3002size()
\uff1a\u8fd4\u56de\u5bb9\u5668\u5185\u7684\u5143\u7d20\u4e2a\u6570\u3002max_size()
\uff1a\u8fd4\u56de\u5bb9\u5668\u00a0\u7406\u8bba\u4e0a\u00a0\u80fd\u5b58\u50a8\u7684\u6700\u5927\u5143\u7d20\u4e2a\u6570\u3002\u4f9d\u5bb9\u5668\u7c7b\u578b\u548c\u6240\u5b58\u50a8\u53d8\u91cf\u7684\u7c7b\u578b\u800c\u53d8\u3002empty()
\uff1a\u8fd4\u56de\u5bb9\u5668\u662f\u5426\u4e3a\u7a7a\u3002swap()
\uff1a\u4ea4\u6362\u4e24\u4e2a\u5bb9\u5668\u3002clear()
\uff1a\u6e05\u7a7a\u5bb9\u5668\u3002==
/!=
/<
/>
/<=
/>=
\uff1a\u6309\u00a0\u5b57\u5178\u5e8f\u00a0\u6bd4\u8f83\u4e24\u4e2a\u5bb9\u5668\u7684\u5927\u5c0f\u3002\uff08\u6bd4\u8f83\u5143\u7d20\u5927\u5c0f\u65f6\u00a0map
\u00a0\u7684\u6bcf\u4e2a\u5143\u7d20\u76f8\u5f53\u4e8e\u00a0set<pair<key, value> >
\uff0c\u65e0\u5e8f\u5bb9\u5668\u4e0d\u652f\u6301\u00a0<
/>
/<=
/>=
\u3002\uff09find
\uff1a\u987a\u5e8f\u67e5\u627e\u3002find(v.begin(), v.end(), value)
\uff0c\u5176\u4e2d\u00a0value
\u00a0\u4e3a\u9700\u8981\u67e5\u627e\u7684\u503c\u3002reverse
\uff1a\u7ffb\u8f6c\u6570\u7ec4\u3001\u5b57\u7b26\u4e32\u3002reverse(v.begin(), v.end())
\u00a0\u6216\u00a0reverse(a + begin, a + end)
\u3002unique
\uff1a\u53bb\u9664\u5bb9\u5668\u4e2d\u76f8\u90bb\u7684\u91cd\u590d\u5143\u7d20\u3002unique(ForwardIterator first, ForwardIterator last)
\uff0c\u8fd4\u56de\u503c\u4e3a\u6307\u5411\u00a0\u53bb\u91cd\u540e\u00a0\u5bb9\u5668\u7ed3\u5c3e\u7684\u8fed\u4ee3\u5668\uff0c\u539f\u5bb9\u5668\u5927\u5c0f\u4e0d\u53d8\u3002\u4e0e\u00a0sort
\u00a0\u7ed3\u5408\u4f7f\u7528\u53ef\u4ee5\u5b9e\u73b0\u5b8c\u6574\u5bb9\u5668\u53bb\u91cd\u3002sort
\uff1a\u6392\u5e8f\u3002sort(v.begin(), v.end(), cmp)
\u00a0\u6216\u00a0sort(a + begin, a + end, cmp)
\uff0c\u5176\u4e2d\u00a0end
\u00a0\u662f\u6392\u5e8f\u7684\u6570\u7ec4\u6700\u540e\u4e00\u4e2a\u5143\u7d20\u7684\u540e\u4e00\u4f4d\uff0ccmp
\u00a0\u4e3a\u81ea\u5b9a\u4e49\u7684\u6bd4\u8f83\u51fd\u6570\u3002stable_sort
\uff1a\u7a33\u5b9a\u6392\u5e8f\uff0c\u7528\u6cd5\u540c\u00a0sort()
\u3002nth_element
\uff1a\u6309\u6307\u5b9a\u8303\u56f4\u8fdb\u884c\u5206\u7c7b\uff0c\u5373\u627e\u51fa\u5e8f\u5217\u4e2d\u7b2c \\(\\displaystyle n\\) \u5927\u7684\u5143\u7d20\uff0c\u4f7f\u5176\u5de6\u8fb9\u5747\u4e3a\u5c0f\u4e8e\u5b83\u7684\u6570\uff0c\u53f3\u8fb9\u5747\u4e3a\u5927\u4e8e\u5b83\u7684\u6570\u3002 nth_element(v.begin(), v.begin() + mid, v.end(), cmp)
\u00a0\u6216\u00a0nth_element(a + begin, a + begin + mid, a + end, cmp)
\u3002binary_search
\uff1a\u4e8c\u5206\u67e5\u627e\u3002binary_search(v.begin(), v.end(), value)
\uff0c\u5176\u4e2d\u00a0value
\u00a0\u4e3a\u9700\u8981\u67e5\u627e\u7684\u503c\u3002merge
\uff1a\u5c06\u4e24\u4e2a\uff08\u5df2\u6392\u5e8f\u7684\uff09\u5e8f\u5217\u00a0\u6709\u5e8f\u5408\u5e76\u00a0\u5230\u7b2c\u4e09\u4e2a\u5e8f\u5217\u7684\u00a0\u63d2\u5165\u8fed\u4ee3\u5668\u00a0\u4e0a\u3002merge(v1.begin(), v1.end(), v2.begin(), v2.end() ,back_inserter(v3))
\u3002inplace_merge
\uff1a\u5c06\u4e24\u4e2a\uff08\u5df2\u6309\u5c0f\u4e8e\u8fd0\u7b97\u7b26\u6392\u5e8f\u7684\uff09\uff1a[first,middle), [middle,last)
\u00a0\u8303\u56f4\u00a0\u539f\u5730\u5408\u5e76\u4e3a\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u3002inplace_merge(v.begin(), v.begin() + middle, v.end())
\u3002lower_bound
\uff1a\u5728\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u4e2d\u8fdb\u884c\u4e8c\u5206\u67e5\u627e\uff0c\u8fd4\u56de\u6307\u5411\u7b2c\u4e00\u4e2a\u00a0\u5927\u4e8e\u7b49\u4e8e \u00a0\u7684\u5143\u7d20\u7684\u4f4d\u7f6e\u7684\u8fed\u4ee3\u5668\u3002\u5982\u679c\u4e0d\u5b58\u5728\u8fd9\u6837\u7684\u5143\u7d20\uff0c\u5219\u8fd4\u56de\u5c3e\u8fed\u4ee3\u5668\u3002lower_bound(v.begin(),v.end(),x)
\u3002upper_bound
\uff1a\u5728\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u4e2d\u8fdb\u884c\u4e8c\u5206\u67e5\u627e\uff0c\u8fd4\u56de\u6307\u5411\u7b2c\u4e00\u4e2a\u00a0\u5927\u4e8e \u00a0\u7684\u5143\u7d20\u7684\u4f4d\u7f6e\u7684\u8fed\u4ee3\u5668\u3002\u5982\u679c\u4e0d\u5b58\u5728\u8fd9\u6837\u7684\u5143\u7d20\uff0c\u5219\u8fd4\u56de\u5c3e\u8fed\u4ee3\u5668\u3002upper_bound(v.begin(),v.end(),x)
\u3002next_permutation
\uff1a\u5c06\u5f53\u524d\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u4e0b\u4e00\u4e2a\u6392\u5217\u3002\u5982\u679c\u5f53\u524d\u6392\u5217\u5df2\u7ecf\u662f\u00a0\u5168\u6392\u5217\u4e2d\u7684\u6700\u540e\u4e00\u4e2a\u6392\u5217\uff08\u5143\u7d20\u5b8c\u5168\u4ece\u5927\u5230\u5c0f\u6392\u5217\uff09\uff0c\u51fd\u6570\u8fd4\u56de\u00a0false
\u00a0\u5e76\u5c06\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u7b2c\u4e00\u4e2a\u6392\u5217\uff08\u5143\u7d20\u5b8c\u5168\u4ece\u5c0f\u5230\u5927\u6392\u5217\uff09\uff1b\u5426\u5219\uff0c\u51fd\u6570\u8fd4\u56de\u00a0true
\u3002next_permutation(v.begin(), v.end())
\u00a0\u6216\u00a0next_permutation(v + begin, v + end)
\u3002prev_permutation
\uff1a\u5c06\u5f53\u524d\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u4e0a\u4e00\u4e2a\u6392\u5217\u3002\u7528\u6cd5\u540c\u00a0next_permutation
\u3002partial_sum
\uff1a\u6c42\u524d\u7f00\u548c\u3002\u8bbe\u6e90\u5bb9\u5668\u4e3a\u00a0\uff0c\u76ee\u6807\u5bb9\u5668\u4e3a\u00a0\uff0c\u5219\u4ee4\u00a0\u3002partial_sum(src.begin(), src.end(), back_inserter(dst))
\u3002TODO bitset - OI Wiki
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#23-string","title":"2.3 string","text":"std::string s;\nprintf(\"%s\", s.c_str());\nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", s.size()); \nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", s.length()); \nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", strlen(s.c_str()));\nsubstr(pos, len);\ninsert(index, count, ch);\ninsert(index, str);\nerase(index, count);\nreplace(pos, count, str);\nreplace(first, last, str);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#24-pair","title":"2.4 pair","text":"pair
\u4e0d\u9700\u8981\u989d\u5916\u5b9a\u4e49\u7ed3\u6784\u4e0e\u91cd\u8f7d\u8fd0\u7b97\u7b26pair<int, double> p0(1, 2.0);\npair<int, double> p2 = make_pair(1, 2.0);\nauto p3 = make_pair(1, 2.0);\n\nint i = p0.first; \ndouble d = p0.second;\np1.first++;\n\npriority_queue<pair<int, double> > q;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3","title":"3 \u8fdb\u9636","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#31","title":"3.1 \u7c7b","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#32","title":"3.2 \u52a8\u6001\u5185\u5b58","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#321-new-delete","title":"3.2.1 new \u548c delete \u8fd0\u7b97\u7b26","text":"new data-type;\n\ndouble* pvalue = NULL;\npvalue = new double;\n\nif (!(pvalue = new double)) {\n cout << \"Error: out of memory.\" << endl;\n exit(1);\n}\n\ndelete pvalue;\n
int ***array;\n// \u5047\u5b9a\u6570\u7ec4\u7b2c\u4e00\u7ef4\u4e3a m\uff0c \u7b2c\u4e8c\u7ef4\u4e3a n\uff0c \u7b2c\u4e09\u7ef4\u4e3ah\n// \u52a8\u6001\u5206\u914d\u7a7a\u95f4\narray = new int **[m];\nfor( int i=0; i<m; i++ )\n{\n array[i] = new int *[n];\n for( int j=0; j<n; j++ )\n {\n array[i][j] = new int [h];\n }\n}\n//\u91ca\u653e\nfor( int i=0; i<m; i++ )\n{\n for( int j=0; j<n; j++ )\n {\n delete [] array[i][j];\n }\n delete [] array[i];\n}\ndelete [] array;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#323","title":"3.2.3 \u5bf9\u8c61\u7684\u52a8\u6001\u5185\u5b58\u5206\u914d","text":"C++#include <iostream>\nusing namespace std;\n\nclass Box\n{\n public:\n Box() { \n cout << \"\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\" <<endl; \n }\n ~Box() { \n cout << \"\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\" <<endl; \n }\n};\n\nint main( )\n{\n Box* myBoxArray = new Box[4]; // \u4e00\u4e2a\u5305\u542b 4 \u4e2a Box \u5bf9\u8c61\u7684\u6570\u7ec4\n\n delete [] myBoxArray; // \u5220\u9664\u6570\u7ec4\n return 0;\n}\n
Text Only\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#33","title":"3.3 \u547d\u540d\u7a7a\u95f4","text":"namespace namespace_name {\n // code\n}\n\nnamespace_name::code;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#332-using","title":"3.3.2 using \u6307\u4ee4","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#333","title":"3.3.3 \u4e0d\u8fde\u7eed\u7684\u547d\u540d\u7a7a\u95f4","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#334","title":"3.3.4 \u5d4c\u5957\u7684\u547d\u540d\u7a7a\u95f4","text":"C++namespace namespace_name1 {\n // \u4ee3\u7801\u58f0\u660e\n namespace namespace_name2 {\n // \u4ee3\u7801\u58f0\u660e\n }\n}\n\n// \u8bbf\u95ee namespace_name2 \u4e2d\u7684\u6210\u5458\nusing namespace namespace_name1::namespace_name2;\n\n// \u8bbf\u95ee namespace_name1 \u4e2d\u7684\u6210\u5458\nusing namespace namespace_name1;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#34","title":"3.4 \u6a21\u677f","text":"template <typename type> ret-type func-name(parameter list)\n{\n // \u51fd\u6570\u7684\u4e3b\u4f53\n}\n
C++#include <iostream>\n#include <string>\n\nusing namespace std;\n\ntemplate <typename T>\ninline T const& Max (T const& a, T const& b) \n{ \n return a < b ? b:a; \n} \n\nint main ()\n{\n\n int i = 39;\n int j = 20;\n cout << \"Max(i, j): \" << Max(i, j) << endl; \n\n double f1 = 13.5; \n double f2 = 20.7; \n cout << \"Max(f1, f2): \" << Max(f1, f2) << endl; \n\n string s1 = \"Hello\"; \n string s2 = \"World\"; \n cout << \"Max(s1, s2): \" << Max(s1, s2) << endl; \n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#342","title":"3.4.2 \u7c7b\u6a21\u677f","text":"C++template <class type> class class-name {\n// code\n}\n
C++#include <iostream>\n#include <vector>\n#include <cstdlib>\n#include <string>\n#include <stdexcept>\n\nusing namespace std;\n\ntemplate <class T>\nclass Stack { \n private: \n vector<T> elems; // \u5143\u7d20 \n\n public: \n void push(T const&); // \u5165\u6808\n void pop(); // \u51fa\u6808\n T top() const; // \u8fd4\u56de\u6808\u9876\u5143\u7d20\n bool empty() const{ // \u5982\u679c\u4e3a\u7a7a\u5219\u8fd4\u56de\u771f\u3002\n return elems.empty(); \n } \n}; \n\ntemplate <class T>\nvoid Stack<T>::push (T const& elem) \n{ \n // \u8ffd\u52a0\u4f20\u5165\u5143\u7d20\u7684\u526f\u672c\n elems.push_back(elem); \n} \n\ntemplate <class T>\nvoid Stack<T>::pop () \n{ \n if (elems.empty()) { \n throw out_of_range(\"Stack<>::pop(): empty stack\"); \n }\n // \u5220\u9664\u6700\u540e\u4e00\u4e2a\u5143\u7d20\n elems.pop_back(); \n} \n\ntemplate <class T>\nT Stack<T>::top () const \n{ \n if (elems.empty()) { \n throw out_of_range(\"Stack<>::top(): empty stack\"); \n }\n // \u8fd4\u56de\u6700\u540e\u4e00\u4e2a\u5143\u7d20\u7684\u526f\u672c \n return elems.back(); \n} \n\nint main() \n{ \n try { \n Stack<int> intStack; // int \u7c7b\u578b\u7684\u6808 \n Stack<string> stringStack; // string \u7c7b\u578b\u7684\u6808 \n\n // \u64cd\u4f5c int \u7c7b\u578b\u7684\u6808 \n intStack.push(7); \n cout << intStack.top() <<endl; \n\n // \u64cd\u4f5c string \u7c7b\u578b\u7684\u6808 \n stringStack.push(\"hello\"); \n cout << stringStack.top() << std::endl; \n stringStack.pop(); \n stringStack.pop(); \n } \n catch (exception const& ex) { \n cerr << \"Exception: \" << ex.what() <<endl; \n return -1;\n } \n}\n
Text Only7\nhello\nException: Stack<>::pop(): empty stack\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#35","title":"3.5 \u9884\u5904\u7406\u5668","text":"#define macro-name replacement-text \n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#352","title":"3.5.2 \u53c2\u6570\u5b8f","text":"C++#include <iostream>\nusing namespace std;\n\n#define MIN(a,b) (a<b ? a : b)\n\nint main ()\n{\n int i, j;\n i = 100;\n j = 30;\n cout <<\"\u8f83\u5c0f\u7684\u503c\u4e3a\uff1a\" << MIN(i, j) << endl;\n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#353","title":"3.5.3 \u6761\u4ef6\u7f16\u8bd1","text":"C++#ifdef NULL\n #define NULL 0\n#endif\n\n#ifdef DEBUG\n cerr <<\"Variable x = \" << x << endl;\n#endif\n\n#if 0\n \u4e0d\u8fdb\u884c\u7f16\u8bd1\u7684\u4ee3\u7801\n#endif\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#354","title":"3.5.4 # \u548c ## \u8fd0\u7b97\u7b26","text":"C++#include <iostream>\nusing namespace std;\n\n#define MKSTR( x ) #x\n\nint main ()\n{\n cout << MKSTR(HELLO C++) << endl;\n\n return 0;\n}\n
C++#include <iostream>\nusing namespace std;\n\n#define concat(a, b) a ## b\nint main()\n{\n int xy = 100;\n\n cout << concat(x, y);\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#355","title":"3.5.5 \u9884\u5b9a\u4e49\u5b8f","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#36","title":"3.6 \u4fe1\u53f7\u5904\u7406","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#361-signal","title":"3.6.1 signal () \u51fd\u6570","text":"C++void (*signal (int sig, void (*func)(int)))(int); \n\nsignal(registered signal, signal handler)\n
C++#include <iostream>\n#include <csignal>\n#include <unistd.h>\n\nusing namespace std;\n\nvoid signalHandler( int signum )\n{\n cout << \"Interrupt signal (\" << signum << \") received.\\n\";\n\n // \u6e05\u7406\u5e76\u5173\u95ed\n // \u7ec8\u6b62\u7a0b\u5e8f \n\n exit(signum); \n\n}\n\nint main ()\n{\n // \u6ce8\u518c\u4fe1\u53f7 SIGINT \u548c\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\n signal(SIGINT, signalHandler); \n\n while(1){\n cout << \"Going to sleep....\" << endl;\n sleep(1);\n }\n\n return 0;\n}\n
\u6309 Ctrl + C \u4e2d\u65ad\u7a0b\u5e8f:
Text OnlyGoing to sleep....\nGoing to sleep....\nGoing to sleep....\nInterrupt signal (2) received.\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#362-raise","title":"3.6.2 raise () \u51fd\u6570","text":"C++int raise (signal sig);\n
C++#include <iostream>\n#include <csignal>\n#include <unistd.h>\n\nusing namespace std;\n\nvoid signalHandler( int signum )\n{\n cout << \"Interrupt signal (\" << signum << \") received.\\n\";\n\n // \u6e05\u7406\u5e76\u5173\u95ed\n // \u7ec8\u6b62\u7a0b\u5e8f \n\n exit(signum); \n\n}\n\nint main ()\n{\n int i = 0;\n // \u6ce8\u518c\u4fe1\u53f7 SIGINT \u548c\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\n signal(SIGINT, signalHandler); \n\n while(++i){\n cout << \"Going to sleep....\" << endl;\n if( i == 3 ){\n raise(SIGINT);\n }\n sleep(1);\n }\n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#37","title":"3.7 \u591a\u7ebf\u7a0b","text":"#include<thread>\nstd::thread thread_object(callable, args...);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3721","title":"3.7.2.1 \u4f7f\u7528\u51fd\u6570\u6307\u9488","text":"C++#include <iostream>\n#include <thread>\n\nvoid printMessage(int count) {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (function pointer)!\\n\";\n }\n}\n\nint main() {\n std::thread t1(printMessage, 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012\u51fd\u6570\u6307\u9488\u548c\u53c2\u6570\n t1.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3722","title":"3.7.2.2 \u4f7f\u7528\u51fd\u6570\u5bf9\u8c61","text":"C++#include <iostream>\n#include <thread>\n\nclass PrintTask {\npublic:\n void operator()(int count) const {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (function object)!\\n\";\n }\n }\n};\n\nint main() {\n std::thread t2(PrintTask(), 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012\u51fd\u6570\u5bf9\u8c61\u548c\u53c2\u6570\n t2.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3723-lambda","title":"3.7.2.3 \u4f7f\u7528 Lambda \u8868\u8fbe\u5f0f","text":"C++#include <iostream>\n#include <thread>\n\nint main() {\n std::thread t3([](int count) {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (lambda)!\\n\";\n }\n }, 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012 Lambda \u8868\u8fbe\u5f0f\u548c\u53c2\u6570\n t3.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3724","title":"3.7.2.4 \u7ebf\u7a0b\u7ba1\u7406","text":"C++t.join();\nt.detach();\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3725","title":"3.7.2.5 \u7ebf\u7a0b\u7684\u4f20\u53c2","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3726","title":"3.7.2.6 \u503c\u4f20\u9012","text":"C++std::thread t(funx, arg1, arg2);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3727","title":"3.7.2.7 \u5f15\u7528\u4f20\u9012","text":"C++#include <iostream>\n#include <thread>\n\nvoid increment(int& x) {\n ++x;\n}\n\nint main() {\n int num = 0;\n std::thread t(increment, std::ref(num)); // \u4f7f\u7528 std::ref \u4f20\u9012\u5f15\u7528\n t.join();\n std::cout << \"Value after increment: \" << num << std::endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#373","title":"3.7.3 \u7ebf\u7a0b\u540c\u6b65\u4e0e\u4e92\u65a5","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3731-mutex","title":"3.7.3.1 \u4e92\u65a5\u91cf\uff08Mutex\uff09","text":"C++std::mutex mtx;\nmtx.lock(); // \u9501\u5b9a\u4e92\u65a5\u9501\n// \u8bbf\u95ee\u5171\u4eab\u8d44\u6e90\nmtx.unlock();// \u91ca\u653e\u4e92\u65a5\u9501\n\nstd::lock_guard<std::mutex> lock(mtx); // \u81ea\u52a8\u9501\u5b9a\u548c\u89e3\u9501\n// \u8bbf\u95ee\u5171\u4eab\u8d44\u6e90\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3732-locks","title":"3.7.3.2 \u9501\uff08Locks\uff09","text":"std::lock_guard
\uff1a\u4f5c\u7528\u57df\u9501\uff0c\u5f53\u6784\u9020\u65f6\u81ea\u52a8\u9501\u5b9a\u4e92\u65a5\u91cf\uff0c\u5f53\u6790\u6784\u65f6\u81ea\u52a8\u89e3\u9501\u3002std::unique_lock
\uff1a\u4e0e std::lock_guard
\u7c7b\u4f3c\uff0c\u4f46\u63d0\u4f9b\u4e86\u66f4\u591a\u7684\u7075\u6d3b\u6027\uff0c\u4f8b\u5982\u53ef\u4ee5\u8f6c\u79fb\u6240\u6709\u6743\u548c\u624b\u52a8\u89e3\u9501\u3002#include <mutex>\n\nstd::mutex mtx;\n\nvoid safeFunctionWithLockGuard() {\n std::lock_guard<std::mutex> lk(mtx);\n // \u8bbf\u95ee\u6216\u4fee\u6539\u5171\u4eab\u8d44\u6e90\n}\n\nvoid safeFunctionWithUniqueLock() {\n std::unique_lock<std::mutex> ul(mtx);\n // \u8bbf\u95ee\u6216\u4fee\u6539\u5171\u4eab\u8d44\u6e90\n // ul.unlock(); // \u53ef\u9009\uff1a\u624b\u52a8\u89e3\u9501\n // ...\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3733-condition-variable","title":"3.7.3.3 \u6761\u4ef6\u53d8\u91cf\uff08Condition Variable\uff09","text":"C++std::condition_variable cv;\nstd::mutex mtx;\nbool ready = false;\n\nstd::unique_lock<std::mutex> lock(mtx);\ncv.wait(lock, []{ return ready; }); // \u7b49\u5f85\u6761\u4ef6\u6ee1\u8db3\n// \u6761\u4ef6\u6ee1\u8db3\u540e\u6267\u884c\n
C++#include <mutex>\n#include <condition_variable>\n\nstd::mutex mtx;\nstd::condition_variable cv;\nbool ready = false;\n\nvoid workerThread() {\n std::unique_lock<std::mutex> lk(mtx);\n cv.wait(lk, []{ return ready; }); // \u7b49\u5f85\u6761\u4ef6\n // \u5f53\u6761\u4ef6\u6ee1\u8db3\u65f6\u6267\u884c\u5de5\u4f5c\n}\n\nvoid mainThread() {\n {\n std::lock_guard<std::mutex> lk(mtx);\n // \u51c6\u5907\u6570\u636e\n ready = true;\n } // \u79bb\u5f00\u4f5c\u7528\u57df\u65f6\u89e3\u9501\n cv.notify_one(); // \u901a\u77e5\u4e00\u4e2a\u7b49\u5f85\u7684\u7ebf\u7a0b\n}\n
TODO
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3734-atomic-operations","title":"3.7.3.4 \u539f\u5b50\u64cd\u4f5c\uff08Atomic Operations\uff09","text":"#include <atomic>\n#include <thread>\n\nstd::atomic<int> count(0);\n\nvoid increment() {\n count.fetch_add(1, std::memory_order_relaxed);\n}\n\nint main() {\n std::thread t1(increment);\n std::thread t2(increment);\n t1.join();\n t2.join();\n return count; // \u5e94\u8fd4\u56de2\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3735-thread-local-storagetls","title":"3.7.3.5 \u7ebf\u7a0b\u5c40\u90e8\u5b58\u50a8\uff08Thread Local Storage\uff0cTLS\uff09","text":"#include <iostream>\n#include <thread>\n\nthread_local int threadData = 0;\n\nvoid threadFunction() {\n threadData = 42; // \u6bcf\u4e2a\u7ebf\u7a0b\u90fd\u6709\u81ea\u5df1\u7684threadData\u526f\u672c\n std::cout << \"Thread data: \" << threadData << std::endl;\n}\n\nint main() {\n std::thread t1(threadFunction);\n std::thread t2(threadFunction);\n t1.join();\n t2.join();\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3736-deadlock","title":"3.7.3.6 \u6b7b\u9501\uff08Deadlock\uff09\u548c\u907f\u514d\u7b56\u7565","text":"std::promise<int> p;\nstd::future<int> f = p.get_future();\n\nstd::thread t([&p] {\n p.set_value(10); // \u8bbe\u7f6e\u503c\uff0c\u89e6\u53d1 future\n});\n\nint result = f.get(); // \u83b7\u53d6\u503c\n
C++17 \u5f15\u5165\u4e86\u5e76\u884c\u7b97\u6cd5\u5e93
C++#include <algorithm>\n#include <vector>\n#include <execution>\n\nstd::vector<int> vec = {1, 2, 3, 4, 5};\nstd::for_each(std::execution::par, vec.begin(), vec.end(), [](int &n) {\n n *= 2;\n});\n
TODO \u591a\u7ebf\u7a0b\u5b9e\u4f8b
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#38-web","title":"3.8 Web \u7f16\u7a0b","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#381-cgi","title":"3.8.1 \u4ec0\u4e48\u662f CGI\uff1f","text":"TODO
"},{"location":"CS_Basic/CS61A/CS61A/","title":"CS61A","text":""},{"location":"CS_Basic/CS61A/CS61A/#cs61a","title":"CS61A","text":"\u7ea6 24 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u7ea6 2713 \u4e2a\u5b57 651 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 22 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/CS61A/Composing_Programs/#1","title":"1 \u4f7f\u7528\u51fd\u6570\u6784\u5efa\u62bd\u8c61","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#11","title":"1.1 \u5f00\u59cb","text":"\u7a0b\u5e8f\u7531\u4e24\u90e8\u5206\u7ec4\u6210:
\u6c42\u503c\u7a0b\u5e8f\u672c\u8d28\u4e0a\u662f\u9012\u5f52\u7684
Pure functions None-pure functions which has a side effect
"},{"location":"CS_Basic/CS61A/Composing_Programs/#13","title":"1.3 \u5b9a\u4e49\u65b0\u7684\u51fd\u6570","text":"Pythondef <name>(<formal parameters>):\n return <return expression> \n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#131","title":"1.3.1 \u73af\u5883","text":"environment has some frames frames have some bindings
PEP 8 \u2013 Style Guide for Python Code | peps.python.org
"},{"location":"CS_Basic/CS61A/Composing_Programs/#136","title":"1.3.6 \u62bd\u8c61\u51fd\u6570","text":"docstring
"},{"location":"CS_Basic/CS61A/Composing_Programs/#142","title":"1.4.2 \u53c2\u6570\u9ed8\u8ba4\u503c","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#15","title":"1.5 \u63a7\u5236","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#151","title":"1.5.1 \u8bed\u53e5","text":"header suite
Python<header>:\n <statement>\n <statement>\n ...\n<separating header>:\n <statement>\n <statement>\n ...\n...\n
def \u662f\u590d\u5408\u8bed\u53e5 the header controls its suite \u8fd9\u4e2a\u5b9a\u4e49\u63ed\u793a\u4e86\u9012\u5f52\u5b9a\u4e49\u5e8f\u5217\uff08sequence\uff09\u7684\u57fa\u672c\u7ed3\u6784\uff1a\u4e00\u4e2a\u5e8f\u5217\u53ef\u4ee5\u5206\u89e3\u6210\u5b83\u7684\u7b2c\u4e00\u4e2a\u5143\u7d20\u548c\u5176\u4f59\u5143\u7d20 redirected control
"},{"location":"CS_Basic/CS61A/Composing_Programs/#153-ii","title":"1.5.3 \u00a0\u5b9a\u4e49\u51fd\u6570 II\uff1a\u5c40\u90e8\u8d4b\u503c","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#154","title":"1.5.4 \u6761\u4ef6\u8bed\u53e5","text":"Pythonif <expression>:\n <suite>\nelif <expression>:\n <suite>\nelse:\n <suite>\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#155","title":"1.5.5 \u8fed\u4ee3","text":"iteractive control
Pythonwhile <expression>:\n <suite>\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#156","title":"1.5.6 \u6d4b\u8bd5","text":"assertions
Python>>> assert fib(8) == 13, '\u7b2c\u516b\u4e2a\u6590\u6ce2\u90a3\u5951\u6570\u5e94\u8be5\u662f 13'\n
Doctests
Python>>> def sum_naturals(n):\n \"\"\"\u8fd4\u56de\u524d n \u4e2a\u81ea\u7136\u6570\u7684\u548c\u3002\n\n >>> sum_naturals(10)\n 55\n >>> sum_naturals(100)\n 5050\n \"\"\"\n total, k = 0, 1\n while k <= n:\n total, k = total + k, k + 1\n return total\n
Python>>> from doctest import testmod\n>>> testmod()\nTestResults(failed=0, attempted=2)\n
\u5355\u4e2a\u51fd\u6570\u7684\u4ea4\u4e92
Python>>> from doctest import run_docstring_examples\n>>> run_docstring_examples(sum_naturals, globals(), True)\nFinding tests in NoName\nTrying:\n\u00a0\u00a0\u00a0 sum_naturals(10)\nExpecting:\n\u00a0\u00a0\u00a0 55\nok\nTrying:\n\u00a0\u00a0\u00a0 sum_naturals(100)\nExpecting:\n\u00a0\u00a0\u00a0 5050\nok\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#16","title":"1.6 \u9ad8\u9636\u51fd\u6570","text":">>> def summation(n, term):\n total, k = 0, 1\n while k <= n:\n total, k = total + term(k), k + 1\n return total\n>>> def identity(x):\n return x\n>>> def sum_naturals(n):\n return summation(n, identity)\n>>> sum_naturals(10)\n55\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#162","title":"1.6.2 \u4f5c\u4e3a\u901a\u7528\u65b9\u6cd5\u7684\u51fd\u6570","text":"\u4e24\u4e2a\u540e\u679c:
>>> def curry2(f):\n \"\"\"\u8fd4\u56de\u7ed9\u5b9a\u7684\u53cc\u53c2\u6570\u51fd\u6570\u7684\u67ef\u91cc\u5316\u7248\u672c\"\"\"\n def g(x):\n def h(y):\n return f(x, y)\n return h\n return g\n>>> def uncurry2(g):\n \"\"\"\u8fd4\u56de\u7ed9\u5b9a\u7684\u67ef\u91cc\u5316\u51fd\u6570\u7684\u53cc\u53c2\u6570\u7248\u672c\"\"\"\n def f(x, y):\n return g(x)(y)\n return f\n>>> pow_curried = curry2(pow)\n>>> pow_curried(2)(5)\n32\n>>> map_to_range(0, 10, pow_curried(2))\n1\n2\n4\n8\n16\n32\n64\n128\n256\n512\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#167-lambda","title":"1.6.7 Lambda \u8868\u8fbe\u5f0f","text":"Pythonlambda x : f(g(x))\n\"A function that takes x and returns f(g(x))\"\n
\\(\\displaystyle \\lambda\\)
Python>>> s = lambda x: x * x\n>>> s\n<function <lambda> at 0xf3f490>\n>>> s(12)\n144\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#168","title":"1.6.8 \u62bd\u8c61\u548c\u4e00\u7b49\u51fd\u6570","text":">>> def trace(fn):\n def wrapped(x):\n print('-> ', fn, '(', x, ')')\n return fn(x)\n return wrapped\n\n>>> @trace\n def triple(x):\n return 3 * x\n\n>>> triple(12)\n-> <function triple at 0x102a39848> ( 12 )\n36\n
>>> def triple(x):\n return 3 * x\n>>> triple = trace(triple)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#17","title":"1.7 \u9012\u5f52\u51fd\u6570","text":">>> def count_partitions(n, m):\n\u00a0\u00a0\u00a0 \"\"\"\u8ba1\u7b97\u4f7f\u7528\u6700\u5927\u6570 m \u7684\u6574\u6570\u5206\u5272 n \u7684\u65b9\u5f0f\u7684\u6570\u91cf\"\"\"\n\u00a0\u00a0\u00a0 if n == 0:\n\u00a0\u00a0\u00a0 return 1\n\u00a0\u00a0\u00a0 elif n < 0:\n\u00a0\u00a0\u00a0 return 0\n\u00a0\u00a0\u00a0 elif m == 0:\n\u00a0\u00a0\u00a0 return 0\n\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0\u00a0 return count_partitions(n-m, m) + count_partitions(n, m-1)\n\n>>> count_partitions(6, 4)\n9\n>>> count_partitions(5, 5)\n7\n>>> count_partitions(10, 10)\n42\n>>> count_partitions(15, 15)\n176\n>>> count_partitions(20, 20)\n627\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#2","title":"2 \u4f7f\u7528\u6570\u636e\u6784\u5efa\u62bd\u8c61","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#21","title":"2.1 \u5f15\u8a00","text":"\u539f\u59cb\u6570\u636e\u7c7b\u578b\u5177\u6709\u5c5e\u6027:
wishful thinking
Python>>> def add_rationals(x, y):\n nx, dx = numer(x), denom(x)\n ny, dy = numer(y), denom(y)\n return rational(nx * dy + ny * dx, dx * dy)\n\n>>> def mul_rationals(x, y):\n return rational(numer(x) * numer(y), denom(x) * denom(y))\n\n>>> def print_rational(x):\n print(numer(x), '/', denom(x))\n\n>>> def rationals_are_equal(x, y):\n return numer(x) * denom(y) == numer(y) * denom(x)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#222-pair","title":"2.2.2 pair","text":"from operator import getitem
Python>>> def rational(n, d):\n return [n, d]\n\n>>> def numer(x):\n return x[0]\n\n>>> def denom(x):\n return x[1]\n
\u7b80\u5316\u6709\u7406\u6570:
Python>>> from fractions import gcd\n>>> def rational(n, d):\n g = gcd(n, d)\n return (n//g, d//g)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#223","title":"2.2.3 \u62bd\u8c61\u5c4f\u969c","text":">>> def square_rational(x):\n return mul_rational(x, x)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#224","title":"2.2.4 \u6570\u636e\u7684\u5c5e\u6027","text":"\u76f8\u5f53\u4e8e\u81ea\u5df1\u5199\u4e00\u4e2a\u6570\u636e\u7ed3\u6784:
Python>>> def pair(x, y):\n \"\"\"Return a function that represents a pair.\"\"\"\n def get(index):\n if index == 0:\n return x\n elif index == 1:\n return y\n return get\n\n>>> def select(p, i):\n \"\"\"Return the element at index i of pair p.\"\"\"\n return p(i)\n\n>>> p = pair(20, 14)\n>>> select(p, 0)\n20\n>>> select(p, 1)\n14\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#23","title":"2.3 \u5e8f\u5217","text":"for <name> in <expression>:\n <suite>\n
the expression must produce an iterable object sequence unpacking
Python>>> pairs = [[1, 2], [2, 2], [2, 3], [4, 4]]\n>>> same_count = 0\n>>> for x, y in pairs:\n if x == y:\n same_count = same_count + 1\n>>> same_count\n2\n
range
"},{"location":"CS_Basic/CS61A/Composing_Programs/#233","title":"2.3.3 \u5e8f\u5217\u5904\u7406","text":"list comprehensions
Python>>> odds = [1, 3, 5, 7, 9]\n>>> [x+1 for x in odds]\n[2, 4, 6, 8, 10]\n[<map expression> for <name> in <sequence expression> if <filter expression>]\n
>>> def apply_to_all(map_fn, s):\n return [map_fn(x) for x in s]\n>>> def keep_if(filter_fn, s):\n return [x for x in s if filter_fn(x)]\n# conventional names\n>>> apply_to_all = lambda map_fn, s: list(map(map_fn, s))\n>>> keep_if = lambda filter_fn, s: list(filter(filter_fn, s))\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#234","title":"2.3.4 \u5e8f\u5217\u62bd\u8c61","text":"string \u6ca1\u6709\u5b57\u7b26\u7c7b\u578b
closure property bax-and-pointer notation
>>> def fib_tree(n):\n if n == 0 or n == 1:\n return tree(n)\n else:\n left, right = fib_tree(n-2), fib_tree(n-1)\n fib_n = label(left) + label(right)\n return tree(fib_n, [left, right])\n>>> fib_tree(5)\n[5, [2, [1], [1, [0], [1]]], [3, [1, [0], [1]], [2, [1], [1, [0], [1]]]]]\n
Python>>> def count_leaves(tree):\n if is_leaf(tree):\n return 1\n else:\n branch_counts = [count_leaves(b) for b in branches(tree)]\n return sum(branch_counts)\n>>> count_leaves(fib_tree(5))\n8\n
Partition trees
Python>>> def print_parts(tree, partition=[]):\n if is_leaf(tree):\n if label(tree):\n print(' + '.join(partition))\n else:\n left, right = branches(tree)\n m = str(label(tree))\n print_parts(left, partition + [m])\n print_parts(right, partition)\n\n>>> print_parts(partition_tree(6, 4))\n4 + 2\n4 + 1 + 1\n3 + 3\n3 + 2 + 1\n3 + 1 + 1 + 1\n2 + 2 + 2\n2 + 2 + 1 + 1\n2 + 1 + 1 + 1 + 1\n1 + 1 + 1 + 1 + 1 + 1\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#237","title":"2.3.7 \u94fe\u8868","text":"linked list abstract data representation
Python>>> def partitions(n, m):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u5305\u542b n \u7684\u5206\u5272\u65b9\u6848\u7684\u94fe\u8868\uff0c\u5176\u4e2d\u6bcf\u4e2a\u6b63\u6574\u6570\u4e0d\u8d85\u8fc7 m\"\"\"\nif n == 0:\n return link(empty, empty) # \u5305\u542b\u7a7a\u5206\u5272\u7684\u94fe\u8868\nelif n < 0 or m == 0:\n return empty\nelse:\n using_m = partitions(n-m, m)\n with_m = apply_to_all_link(lambda s: link(m, s), using_m)\n without_m = partitions(n, m-1)\n return extend_link(with_m, without_m)\n\n>>> def print_partitions(n, m):\n lists = partitions(n, m)\n strings = apply_to_all_link(lambda s: join_link(s, \" + \"), lists)\n print(join_link(strings, \"\\n\"))\n\n>>> print_partitions(6, 4)\n4 + 2\n4 + 1 + 1\n3 + 3\n3 + 2 + 1\n3 + 1 + 1 + 1\n2 + 2 + 2\n2 + 2 + 1 + 1\n2 + 1 + 1 + 1 + 1\n1 + 1 + 1 + 1 + 1 + 1\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#24","title":"2.4 \u53ef\u53d8\u6570\u636e","text":"object-oriented programming
"},{"location":"CS_Basic/CS61A/Composing_Programs/#241","title":"2.4.1 \u5bf9\u8c61\u9690\u55bb","text":"mutable Sharing and Identity \u5217\u8868\u63a8\u5bfc\u5f0f:
Python>>> from unicodedata import lookup\n>>> [lookup('WHITE ' + s.upper() + ' SUIT') for s in suits]\n['\u2661', '\u2662', '\u2664', '\u2667']\n
tuple
"},{"location":"CS_Basic/CS61A/Composing_Programs/#243","title":"2.4.3 \u5b57\u5178","text":"key-value pairs
"},{"location":"CS_Basic/CS61A/Composing_Programs/#244","title":"2.4.4 \u5c40\u90e8\u72b6\u6001","text":"local state
Python>>> def make_withdraw(balance):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u6bcf\u6b21\u8c03\u7528\u90fd\u4f1a\u51cf\u5c11 balance \u7684 withdraw \u51fd\u6570\"\"\"\ndef withdraw(amount):\n nonlocal balance # \u58f0\u660e balance \u662f\u975e\u5c40\u90e8\u7684\n if amount > balance:\n return '\u4f59\u989d\u4e0d\u8db3'\n balance = balance - amount # \u91cd\u65b0\u7ed1\u5b9a\n return balance\nreturn withdraw\n
Python Particulars
"},{"location":"CS_Basic/CS61A/Composing_Programs/#245-non-local","title":"2.4.5 \u975e\u5c40\u90e8 Non-local \u8d4b\u503c\u7684\u597d\u5904","text":"\u8fd9\u6837\uff0c\u6bcf\u4e2a withdraw \u5b9e\u4f8b\u90fd\u4fdd\u6301\u81ea\u5df1\u7684 balance \u72b6\u6001\uff0c\u4f46\u7a0b\u5e8f\u4e2d\u7684\u4efb\u4f55\u5176\u4ed6\u51fd\u6570\u90fd\u65e0\u6cd5\u8bbf\u95ee\u8be5\u72b6\u6001\u3002\u4ece\u66f4\u9ad8\u7684\u5c42\u9762\u6765\u770b\u8fd9\u79cd\u60c5\u51b5\uff0c\u6211\u4eec\u62bd\u8c61\u4e86\u4e00\u4e2a\u94f6\u884c\u8d26\u6237\uff0c\u5b83\u81ea\u5df1\u7ba1\u7406\u81ea\u5df1\u7684\u72b6\u6001\uff0c\u5176\u884c\u4e3a\u65b9\u5f0f\u4e0e\u4e16\u754c\u4e0a\u6240\u6709\u5176\u5b83\u8d26\u6237\u4e00\u6837\uff1a\u968f\u7740\u65f6\u95f4\u63a8\u79fb\uff0c\u8d26\u6237\u7684\u72b6\u6001\u4f1a\u6839\u636e\u8d26\u6237\u7684\u53d6\u6b3e\u8bb0\u5f55\u800c\u53d1\u751f\u53d8\u5316\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#246-non-local","title":"2.4.6 \u975e\u5c40\u90e8 Non-local \u8d4b\u503c\u7684\u4ee3\u4ef7","text":"\u51fd\u6570\u662f\u4e00\u4e2a dispatch \uff08\u8c03\u5ea6\uff09\u51fd\u6570\uff0c\u5176\u53c2\u6570\u9996\u5148\u662f\u4e00\u4e2a\u671f\u671b\u7684\u6307\u4ee4\uff0c\u4ee3\u8868\u671f\u671b\u8fd9\u4e2a\u51fd\u6570\u505a\u4ec0\u4e48\uff1b\u7136\u540e\u662f\u8be5\u65b9\u6cd5\u7684\u9700\u8981\u7528\u5230\u7684\u53c2\u6570\u3002\u6b64\u6307\u4ee4\u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\uff0c\u7528\u4e8e\u547d\u540d\u51fd\u6570\u5e94\u6267\u884c\u7684\u64cd\u4f5c\u3002\u53ef\u4ee5\u5c06\u8fd9\u4e2a dispatch \u51fd\u6570\u7406\u89e3\u4e3a\u591a\u4e2a\u4e0d\u540c\u51fd\u6570\u7684\u62bd\u8c61\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u786e\u5b9a\u76ee\u6807\u51fd\u6570\u7684\u884c\u4e3a\uff0c\u5e76\u4e3a\u8be5\u884c\u4e3a\u5165\u53c2\u5176\u4ed6\u53c2\u6570\u3002 \u7528\u5b57\u7b26\u4e32\u4e5f\u592a\u9006\u5929\u4e86\u3002
Python>>> def mutable_link():\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u53ef\u53d8\u94fe\u8868\u7684\u51fd\u6570\"\"\"\ncontents = empty\ndef dispatch(message, value=None):\n nonlocal contents\n if message == 'len':\n return len_link(contents)\n elif message == 'getitem':\n return getitem_link(contents, value)\n elif message == 'push_first':\n contents = link(value, contents)\n elif message == 'pop_first':\n f = first(contents)\n contents = rest(contents)\n return f\n elif message == 'str':\n return join_link(contents, \", \")\nreturn dispatch\n\n>>> def to_mutable_link(source):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u4e0e\u539f\u5217\u8868\u76f8\u540c\u5185\u5bb9\u7684\u51fd\u6570\u5217\u8868\"\"\"\ns = mutable_link()\nfor element in reversed(source):\n s('push_first', element)\nreturn s\n\n>>> s = to_mutable_link(suits)\n>>> type(s)\n<class 'function'>\n>>> print(s('str'))\nheart, diamond, spade, club\n
\u5b57\u5178\u5b9e\u73b0:
Python>>> def dictionary():\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u5b57\u5178\u7684\u51fd\u6570\u5b9e\u73b0\"\"\"\nrecords = []\ndef getitem(key):\n matches = [r for r in records if r[0] == key]\n if len(matches) == 1:\n key, value = matches[0]\n return value\ndef setitem(key, value):\n nonlocal records\n non_matches = [r for r in records if r[0] != key]\n records = non_matches + [[key, value]]\ndef dispatch(message, key=None, value=None):\n if message == 'getitem':\n return getitem(key)\n elif message == 'setitem':\n setitem(key, value)\nreturn dispatch\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#248-dispatch-dictionaries","title":"2.4.8 \u8c03\u5ea6\u5b57\u5178\uff08Dispatch Dictionaries\uff09","text":"\u7528\u5b57\u5178\u5b58\u50a8\u6d88\u606f\u3002
Pythondef account(initial_balance):\n def deposit(amount):\n dispatch['balance'] += amount\n return dispatch['balance']\n def withdraw(amount):\n if amount > dispatch['balance']:\n return 'Insufficient funds'\n dispatch['balance'] -= amount\n return dispatch['balance']\n dispatch = {'deposit': deposit,\n 'withdraw': withdraw,\n 'balance': initial_balance}\n return dispatch\n\ndef withdraw(account, amount):\n return account['withdraw'](amount)\ndef deposit(account, amount):\n return account['deposit'](amount)\ndef check_balance(account):\n return account['balance']\n\na = account(20)\ndeposit(a, 5)\nwithdraw(a, 17)\ncheck_balance(a)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#249-propagating-constraints","title":"2.4.9 \u7ea6\u675f\u4f20\u9012 (Propagating\u00a0Constraints)","text":"connector Using the Constraint System
Python>>> celsius = connector('Celsius')\n>>> fahrenheit = connector('Fahrenheit')\n>>> def converter(c, f):\n \"\"\"\u7528\u7ea6\u675f\u6761\u4ef6\u8fde\u63a5 c \u5230 f\uff0c\u5c06\u6444\u6c0f\u5ea6\u8f6c\u6362\u4e3a\u534e\u6c0f\u5ea6.\"\"\"\n u, v, w, x, y = [connector() for _ in range(5)]\n multiplier(c, w, u)\n multiplier(v, x, u)\n adder(v, y, f)\n constant(w, 9)\n constant(x, 5)\n constant(y, 32)\n>>> converter(celsius, fahrenheit)\n\n>>> celsius['set_val']('user', 25)\nCelsius = 25\nFahrenheit = 77.0\n\n>>> fahrenheit['set_val']('user', 212)\nContradiction detected: 77.0 vs 212\n\n>>> celsius['forget']('user')\nCelsius is forgotten\nFahrenheit is forgotten\n\n>>> fahrenheit['set_val']('user', 212)\nFahrenheit = 212\nCelsius = 100.0\n\n# Implementing the Constraint System\n>>> connector ['set_val'](source, value) \"\"\"\u8868\u793a\u00a0source\u00a0\u5728\u8bf7\u6c42\u8fde\u63a5\u5668\u5c06\u5f53\u524d\u503c\u8bbe\u4e3a value\"\"\"\n>>> connector ['has_val']()\u00a0 \"\"\"\u8fd4\u56de\u8fde\u63a5\u5668\u662f\u5426\u5df2\u7ecf\u5177\u6709\u503c\"\"\"\n>>> connector ['val'] \"\"\"\u662f\u8fde\u63a5\u5668\u7684\u5f53\u524d\u503c\"\"\"\n>>> connector ['forget'](source)\u00a0 \"\"\"\u544a\u8bc9\u8fde\u63a5\u5668 source \u8bf7\u6c42\u9057\u5fd8\u5b83\u7684\u503c\"\"\"\n>>> connector ['connect'](source)\u00a0 \"\"\"\u544a\u8bc9\u8fde\u63a5\u5668\u53c2\u4e0e\u65b0\u7684\u7ea6\u675f\uff0c\u5373 source\"\"\"\n>>> constraint['new_val']() \"\"\"\u8868\u793a\u4e0e\u7ea6\u675f\u76f8\u8fde\u7684\u67d0\u4e2a\u8fde\u63a5\u5668\u5177\u6709\u65b0\u7684\u503c\u3002\"\"\"\n>>> constraint['forget']()\u00a0 \"\"\"\u8868\u793a\u4e0e\u7ea6\u675f\u76f8\u8fde\u7684\u67d0\u4e2a\u8fde\u63a5\u5668\u9057\u5fd8\u4e86\u503c\u3002\"\"\"\n\n>>> from operator import add, sub\n>>> def adder(a, b, c):\n \"\"\"\u7ea6\u675f a+b=c\"\"\"\n return make_ternary_constraint(a, b, c, add, sub, sub)\n\n>>> def make_ternary_constraint(a, b, c, ab, ca, cb):\n \"\"\"\u7ea6\u675f ab(a,b)=c\uff0cca(c,a)=b\uff0ccb(c,b)=a\"\"\"\n def new_value():\n av, bv, cv = [connector['has_val']() for connector in (a, b, c)]\n if av and bv:\n c['set_val'](constraint, ab(a['val'], b['val']))\n elif av and cv:\n b['set_val'](constraint, ca(c['val'], a['val']))\n elif bv and cv:\n a['set_val'](constraint, cb(c['val'], b['val']))\n def forget_value():\n for connector in (a, b, c):\n connector['forget'](constraint)\n constraint = {'new_val': new_value, 'forget': forget_value}\n for connector in (a, b, c):\n connector['connect'](constraint)\n return constraint\n\n>>> from operator import mul, truediv\n>>> def multiplier(a, b, c):\n \"\"\"\u7ea6\u675f a*b=c\"\"\"\n return make_ternary_constraint(a, b, c, mul, truediv, truediv)\n\n>>> def constant(connector, value):\n \"\"\"\u5e38\u91cf\u8d4b\u503c\"\"\"\n constraint = {}\n connector['set_val'](constraint, value)\n return constraint\n\n# Representing connectors\n>>> def connector(name=None):\n \"\"\"\u9650\u5236\u6761\u4ef6\u4e4b\u95f4\u7684\u8fde\u63a5\u5668\"\"\"\n informant = None\n constraints = []\n def set_value(source, value):\n nonlocal informant\n val = connector['val']\n if val is None:\n informant, connector['val'] = source, value\n if name is not None:\n print(name, '=', value)\n inform_all_except(source, 'new_val', constraints)\n else:\n if val != value:\n print('Contradiction detected:', val, 'vs', value)\n def forget_value(source):\n nonlocal informant\n if informant == source:\n informant, connector['val'] = None, None\n if name is not None:\n print(name, 'is forgotten')\n inform_all_except(source, 'forget', constraints)\n connector = {'val': None,\n 'set_val': set_value,\n 'forget': forget_value,\n 'has_val': lambda: connector['val'] is not None,\n 'connect': lambda source: constraints.append(source)}\n return connector\n\n>>> def inform_all_except(source, message, constraints):\n \"\"\"\u544a\u77e5\u4fe1\u606f\u9664\u4e86 source \u5916\u7684\u6240\u6709\u7ea6\u675f\u6761\u4ef6\"\"\"\n for c in constraints:\n if c != source:\n c[message]()\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#25","title":"2.5 \u9762\u5411\u5bf9\u8c61\u7f16\u7a0b","text":"__init__\u7c7b\u7684\u6784\u9020\u51fd\u6570\uff08constructor\uff09
Python>>> class Account:\n def __init__(self, account_holder):\n self.balance = 0\n self.holder = account_holder\n def deposit(self, amount):\n self.balance = self.balance + amount\n return self.balance\n def withdraw(self, amount):\n if amount > self.balance:\n return 'Insufficient funds'\n self.balance = self.balance - amount\n return self.balance\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#253","title":"2.5.3 \u6d88\u606f\u4f20\u9012\u548c\u70b9\u8868\u8fbe\u5f0f","text":"Python>>> getattr(spock_account, 'balance')\n10\n>>> hasattr(spock_account, 'deposit')\nTrue\n\n\n>>> type(Account.deposit)\n<class 'Function'>\n>>> type(spock_account.deposit)\n<class 'method'>\n# \u4e3a\u7c7b\u7684\u5c5e\u6027\uff0c\u65b9\u6cd5\u53ea\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u4f46\u4f5c\u4e3a\u5b9e\u4f8b\u7684\u5c5e\u6027\uff0c\u5b83\u662f\u4e00\u4e2a\u7ed1\u5b9a\u65b9\u6cd5\n\n>>> Account.deposit(spock_account, 1001) # \u51fd\u6570 deposit \u63a5\u53d7\u4e24\u4e2a\u53c2\u6570\n1011\n>>> spock_account.deposit(1000) # \u65b9\u6cd5 deposit \u63a5\u53d7\u4e00\u4e2a\u53c2\u6570\n2011\n
\u547d\u540d\u7ea6\u5b9a\uff1a\u7c7b\u540d\u901a\u5e38\u4f7f\u7528 CapWords \u7ea6\u5b9a\uff08\u4e5f\u79f0\u4e3a CamelCase\uff0c\u56e0\u4e3a\u540d\u79f0\u4e2d\u95f4\u7684\u5927\u5199\u5b57\u6bcd\u770b\u8d77\u6765\u50cf\u9a7c\u5cf0\uff09\u7f16\u5199\u3002\u65b9\u6cd5\u540d\u79f0\u9075\u5faa\u4f7f\u7528\u4e0b\u5212\u7ebf\u5206\u9694\u7684\u5c0f\u5199\u5355\u8bcd\u547d\u540d\u51fd\u6570\u7684\u6807\u51c6\u7ea6\u5b9a\u3002
\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u6709\u4e00\u4e9b\u5b9e\u4f8b\u53d8\u91cf\u548c\u65b9\u6cd5\u4e0e\u5bf9\u8c61\u7684\u7ef4\u62a4\u548c\u4e00\u81f4\u6027\u76f8\u5173\uff0c\u6211\u4eec\u4e0d\u5e0c\u671b\u5bf9\u8c61\u7684\u7528\u6237\u770b\u5230\u6216\u4f7f\u7528\u3002\u5b83\u4eec\u4e0d\u662f\u7c7b\u5b9a\u4e49\u7684\u62bd\u8c61\u7684\u4e00\u90e8\u5206\uff0c\u800c\u662f\u5b9e\u73b0\u7684\u4e00\u90e8\u5206\u3002Python \u7684\u7ea6\u5b9a\u89c4\u5b9a\uff0c\u5982\u679c\u5c5e\u6027\u540d\u79f0\u4ee5\u4e0b\u5212\u7ebf\u5f00\u5934\uff0c\u5219\u53ea\u80fd\u5728\u7c7b\u672c\u8eab\u7684\u65b9\u6cd5\u4e2d\u8bbf\u95ee\u5b83\uff0c\u800c\u4e0d\u662f\u7528\u6237\u8bbf\u95ee\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#254","title":"2.5.4 \u7c7b\u5c5e\u6027","text":"\u611f\u89c9\u6ca1\u4ec0\u4e48\u7528:
Python>>> Account.interest = 0.05 # \u6539\u53d8\u7c7b\u5c5e\u6027\n>>> spock_account.interest # \u5b9e\u4f8b\u5c5e\u6027\u53d1\u751f\u53d8\u5316\uff08\u8be5\u5b9e\u4f8b\u4e2d\u6ca1\u6709\u548c\u7c7b\u5c5e\u6027\u540c\u540d\u79f0\u7684\u5b9e\u4f8b\u5c5e\u6027\uff09\n0.05\n>>> kirk_account.interest # \u5982\u679c\u5b9e\u4f8b\u4e2d\u5b58\u5728\u548c\u7c7b\u5c5e\u6027\u540c\u540d\u7684\u5b9e\u4f8b\u5c5e\u6027\uff0c\u5219\u6539\u53d8\u7c7b\u5c5e\u6027\uff0c\u4e0d\u4f1a\u5f71\u54cd\u5b9e\u4f8b\u5c5e\u6027\n0.08\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#255","title":"2.5.5 \u7ee7\u627f","text":">>> class Account:\n \"\"\"\u4e00\u4e2a\u4f59\u989d\u975e\u96f6\u7684\u8d26\u6237\u3002\"\"\"\n interest = 0.02\n def __init__(self, account_holder):\n self.balance = 0\n self.holder = account_holder\n def deposit(self, amount):\n \"\"\"\u5b58\u5165\u8d26\u6237 amount\uff0c\u5e76\u8fd4\u56de\u53d8\u5316\u540e\u7684\u4f59\u989d\"\"\"\n self.balance = self.balance + amount\n return self.balance\n def withdraw(self, amount):\n \"\"\"\u4ece\u8d26\u53f7\u4e2d\u53d6\u51fa amount\uff0c\u5e76\u8fd4\u56de\u53d8\u5316\u540e\u7684\u4f59\u989d\"\"\"\n if amount > self.balance:\n return 'Insufficient funds'\n self.balance = self.balance - amount\n return self.balance\n\n>>> class CheckingAccount(Account):\n \"\"\"\u4ece\u8d26\u53f7\u53d6\u94b1\u4f1a\u6263\u51fa\u624b\u7eed\u8d39\u7684\u8d26\u53f7\"\"\"\n withdraw_charge = 1\n interest = 0.01\n def withdraw(self, amount):\n return Account.withdraw(self, amount + self.withdraw_charge)\n
\u63a5\u53e3
Python>>> def deposit_all(winners, amount=5):\n for account in winners:\n account.deposit(amount) # \u8fd9\u91cc\u8c03\u7528\u7684\u662f\u5b9e\u4f8b account \u7684 deposit \u65b9\u6cd5\n # \u5bf9\u4e8e\u4e0d\u540c\u5b9e\u4f8b\u6765\u8bf4\uff0c\u5b83\u4eec\u7684 deposit \u65b9\u6cd5\u53ef\u80fd\u4e0d\u540c\u3002\u8fd9\u4e2a\u4f8b\u5b50\u76f8\u5bf9\u4e8e\u4e0b\u9762\u6765\u8bb2\uff0c\u66f4\u52a0\u5177\u6709\u5065\u58ee\u6027\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#257","title":"2.5.7 \u591a\u7ee7\u627f","text":"\u7ee7\u627f\u6392\u5e8f\u95ee\u9898\u6ca1\u6709\u6b63\u786e\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u56e0\u4e3a\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u80fd\u66f4\u613f\u610f\u5c06\u67d0\u4e9b\u7ee7\u627f\u7c7b\u7f6e\u4e8e\u5176\u4ed6\u7c7b\u4e4b\u4e0a\u3002\u4f46\u662f\uff0c\u4efb\u4f55\u652f\u6301\u591a\u91cd\u7ee7\u627f\u7684\u7f16\u7a0b\u8bed\u8a00\u90fd\u5fc5\u987b\u4ee5\u4e00\u81f4\u7684\u65b9\u5f0f\u9009\u62e9\u67d0\u4e9b\u6392\u5e8f\uff0c\u4ee5\u4fbf\u8be5\u8bed\u8a00\u7684\u7528\u6237\u53ef\u4ee5\u9884\u6d4b\u5176\u7a0b\u5e8f\u7684\u884c\u4e3a\u3002
\u8fdb\u4e00\u6b65\u9605\u8bfb\u3002Python \u4f7f\u7528\u79f0\u4e3a C3 \u65b9\u6cd5\u89e3\u6790\u6392\u5e8f\u7684\u9012\u5f52\u7b97\u6cd5\u89e3\u6790\u6b64\u540d\u79f0\u3002\u53ef\u4ee5\u5728\u6240\u6709\u7c7b\u4e0a\u4f7f\u7528\u00a0mro
\u00a0\u65b9\u6cd5\u67e5\u8be2\u4efb\u4f55\u7c7b\u7684\u65b9\u6cd5\u89e3\u6790\u987a\u5e8f\u3002
>>> [c.__name__ for c in AsSeenOnTVAccount.mro()]\n['AsSeenOnTVAccount', 'CheckingAccount', 'SavingsAccount', 'Account', 'object']\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#258","title":"2.5.8 \u5bf9\u8c61\u7684\u4f5c\u7528","text":"\u53e6\u4e00\u65b9\u9762\uff0c\u7c7b\u53ef\u80fd\u4e0d\u662f\u5b9e\u73b0\u67d0\u4e9b\u62bd\u8c61\u7684\u6700\u4f73\u673a\u5236\u3002\u51fd\u6570\u5f0f\u62bd\u8c61\u63d0\u4f9b\u4e86\u4e00\u4e2a\u66f4\u81ea\u7136\u7684\u9690\u55bb\u6765\u8868\u793a\u8f93\u5165\u548c\u8f93\u51fa\u4e4b\u95f4\u7684\u5173\u7cfb\u3002\u6211\u4eec\u4e0d\u5e94\u8be5\u89c9\u5f97\u5fc5\u987b\u5c06\u7a0b\u5e8f\u4e2d\u7684\u6bcf\u4e00\u70b9\u903b\u8f91\u90fd\u585e\u8fdb\u4e00\u4e2a\u7c7b\u4e2d\uff0c\u5c24\u5176\u662f\u5728\u5b9a\u4e49\u72ec\u7acb\u51fd\u6570\u6765\u64cd\u4f5c\u6570\u636e\u66f4\u81ea\u7136\u7684\u60c5\u51b5\u4e0b\u3002\u51fd\u6570\u8fd8\u53ef\u4ee5\u5f3a\u5236\u5b9e\u73b0\u5173\u6ce8\u70b9\u7684\u5206\u79bb\u3002\u6362\u53e5\u8bdd\u8bf4\uff0c\u51fd\u6570\u5f0f\u7f16\u7a0b\u63d0\u4f9b\u4e86\u53e6\u4e00\u79cd\u6709\u6548\u5730\u7ec4\u7ec7\u7a0b\u5e8f\u903b\u8f91\u7684\u65b9\u6cd5\uff0c\u4f7f\u5f97\u7a0b\u5e8f\u5458\u80fd\u591f\u66f4\u597d\u5730\u5904\u7406\u548c\u7ef4\u62a4\u7a0b\u5e8f\u3002\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u4f7f\u7528\u51fd\u6570\u5f0f\u7f16\u7a0b\u65b9\u6cd5\u53ef\u80fd\u6bd4\u4f7f\u7528\u9762\u5411\u5bf9\u8c61\u7f16\u7a0b\u66f4\u81ea\u7136\u548c\u6709\u6548\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#26","title":"2.6 \u5b9e\u73b0\u7c7b\u548c\u5bf9\u8c61","text":"object-oriented programming paradigm \u5373\u4f7f\u5728\u6ca1\u6709\u5185\u7f6e\u5bf9\u8c61\u7cfb\u7edf\u7684\u7f16\u7a0b\u8bed\u8a00\u4e2d\uff0c\u7a0b\u5e8f\u4e5f\u53ef\u4ee5\u662f\u9762\u5411\u5bf9\u8c61\u7684\u3002 \u653e\u5f03\u70b9\u8868\u793a\u6cd5->\u8c03\u5ea6\u5b57\u5178\u5b9e\u73b0\u6d88\u606f\u4f20\u9012
"},{"location":"CS_Basic/CS61A/Composing_Programs/#261","title":"2.6.1 \u5b9e\u4f8b","text":"Python>>> def make_instance(cls):\n \"\"\"Return a new object instance, which is a dispatch dictionary.\"\"\"\n def get_value(name):\n if name in attributes:\n return attributes[name]\n else:\n value = cls['get'](name)\n return bind_method(value, instance)\n def set_value(name, value):\n attributes[name] = value\n attributes = {}\n instance = {'get': get_value, 'set': set_value}\n return instance\n\n>>> def bind_method(value, instance):\n \"\"\"Return a bound method if value is callable, or value otherwise.\"\"\"\n if callable(value):\n def method(*args):\n return value(instance, *args)\n return method\n else:\n return value\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#262","title":"2.6.2 \u7c7b","text":"Python>>> def make_class(attributes, base_class=None):\n \"\"\"Return a new class, which is a dispatch dictionary.\"\"\"\n def get_value(name):\n if name in attributes:\n return attributes[name]\n elif base_class is not None:\n return base_class['get'](name)\n def set_value(name, value):\n attributes[name] = value\n def new(*args):\n return init_instance(cls, *args)\n cls = {'get': get_value, 'set': set_value, 'new': new}\n return cls\n\n>>> def init_instance(cls, *args):\n \"\"\"Return a new object with type cls, initialized with args.\"\"\"\n instance = make_instance(cls)\n init = cls['get']('__init__')\n if init:\n init(instance, *args)\n return instance\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#3","title":"3 \u8ba1\u7b97\u673a\u7a0b\u5e8f\u7684\u89e3\u91ca","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#31","title":"3.1 \u5f15\u8a00","text":"\u8bb8\u591a\u89e3\u91ca\u5668\u90fd\u6709\u4e00\u4e2a\u4f18\u96c5\u7684\u7ed3\u6784\uff0c\u5373\u4e24\u4e2a\u4e92\u9012\u5f52\u51fd\u6570\uff1a
(if <predicate> <consequent> <alternative>)\n\n(define pi 3.14)\n(* pi 3.14)\n\n(define (<name> <formal parameters>) <body>)\neg1:\n (define (average x y)\n (/ (+ x y) 2))\neg2:\n (define (abs x)\n (if (< x 0)\n (- x)\n x))\neg3:\n (define (sqrt x)\n (define (good-enough? guess)\n (< (abs (- (square guess) x)) 0.001))\n (define (improve guess)\n (average guess (/ x guess)))\n (define (sqrt-iter guess)\n (if (good-enough? guess)\n guess\n (sqrt-iter (improve guess))))\n (sqrt-iter 1.0))\n (sqrt 9)\n\n(lambda (<formal-parameters>) <body>)\neg1:\n (define (plus4 x) (+ x 4))\n (define plus4 (lambda (x) (+ x 4))) # both are OK\n\n# \u7279\u6b8a\u7684\u503c\u00a0nil\u00a0\u6216\u00a0'()\u00a0\u8868\u793a\u7a7a\u5217\u8868\n\n# null? \u8c13\u8bcd\u7684\u4f7f\u7528:\n (define (length items)\n (if (null? items)\n 0\n (+ 1 (length (cdr items)))))\n (define (getitem items n)\n (if (= n 0)\n (car items)\n (getitem (cdr items) (- n 1))))\n (define squares (list 1 4 9 16 25))\n\n (length squares)\n\n (getitem squares 3)\n\n# \u4efb\u4f55\u4e0d\u88ab\u6c42\u503c\u7684\u8868\u8fbe\u5f0f\u90fd\u88ab\u79f0\u4e3a\u88ab\u5f15\u7528\n (list 'define 'list)\n\n# turtle\u4f7f\u7528+\u9012\u5f52\u753b\u56fe\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#33","title":"3.3 \u5f02\u5e38","text":">>> raise Exception(' An error occurred')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nException: an error occurred\n
try\n <try suite>\nexcept <exception class> as <name>:\n <except suite>\n
\u5f02\u5e38\u662f\u4e2a\u7c7b\uff0c\u53ef\u4ee5\u6709\u989d\u5916\u7684\u5c5e\u6027\uff0c\u53ef\u4ee5\u907f\u514d\u62a5\u9519\uff0c\u8ba9\u7a0b\u5e8f\u7ed9\u51fa\u4e00\u4e2a\u8f83\u4e3a\u7c97\u7cd9\u7684\u503c\uff1a
Python>>> class IterImproveError(Exception):\n\u00a0\u00a0\u00a0 def __init__(self, last_guess):\n\u00a0\u00a0\u00a0 self.last_guess = last_guess\n>>> def improve(update, done, guess=1, max_updates=1000):\n\u00a0\u00a0\u00a0 k = 0\n\u00a0\u00a0\u00a0 try:\n\u00a0\u00a0\u00a0 while not done(guess) and k < max_updates:\n\u00a0\u00a0\u00a0 guess = update(guess)\n\u00a0\u00a0\u00a0 k = k + 1\n\u00a0\u00a0\u00a0 return guess\n\u00a0\u00a0\u00a0 except ValueError:\n\u00a0\u00a0\u00a0 raise IterImproveError(guess)\n>>> def find_zero(f, guess=1):\n\u00a0\u00a0\u00a0 def done(x):\n\u00a0\u00a0\u00a0 return f(x) == 0\n\u00a0\u00a0\u00a0 try:\n\u00a0\u00a0\u00a0 return improve(newton_update(f), done, guess)\n\u00a0\u00a0\u00a0 except IterImproveError as e:\n\u00a0\u00a0\u00a0 return e.last_guess\n>>> from math import sqrt\n>>> find_zero(lambda x: 2*x*x + sqrt(x))\n-0.030211203830201594\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#34","title":"3.4 \u7ec4\u5408\u8bed\u8a00\u7684\u89e3\u91ca\u5668","text":"\u4e24\u4e2a\u7ec4\u4ef6:
>>> next(iterator)\n7\n>>> next(iterator)\nTraceback (most recent call las):\n File \"<stdin>\", line 1, in <module>\nStopIteration\n\n>>> try:\n next(iterator)\n except StopIteration:\n print('No more values')\nNo more values\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#422","title":"4.2.2 \u53ef\u8fed\u4ee3\u6027","text":"iterable value \u53ef\u8fed\u4ee3\u5bf9\u8c61:
\u7ea6 2978 \u4e2a\u5b57 13 \u884c\u4ee3\u7801 4 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 15 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#1","title":"1 \u8ba1\u7b97\u673a\u62bd\u8c61\u53ca\u76f8\u5173\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2","title":"2 \u6307\u4ee4: \u8ba1\u7b97\u673a\u7684\u8bed\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#21","title":"2.1 \u5f15\u8a00","text":"\u8bbe\u8ba1\u539f\u5219:
Java \u7f16\u8bd1\u5668: Just In Time \u7f16\u8bd1\u5668
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#23","title":"2.3 \u8ba1\u7b97\u673a\u786c\u4ef6\u7684\u64cd\u4f5c\u6570","text":"\u5728\u5185\u5b58\u548c\u5bc4\u5b58\u5668\u4e4b\u95f4\u4f20\u8f93\u6307\u4ee4:\u6570\u636e\u4f20\u8f93\u6307\u4ee4 \u6307\u4ee4\u63d0\u4f9b\u5185\u5b58\u5730\u5740 \u8f7d\u5165\u6307\u4ee4\uff08load\uff09:ld
Text OnlyLd x9, 8(x22)\n
X 22 \u57fa\u5740\u5bc4\u5b58\u5668 8 \u504f\u79fb\u91cf \u5b57\u8282\u5730\u5740: 0 8 16 24 RICS- V \u662f\u5c0f\u7aef\u7f16\u5740: \u53ea\u5728\u4ee5\u53cc\u5b57\u5f62\u5f0f\u548c\u516b\u4e2a\u5355\u72ec\u5b57\u8282\u8bbf\u95ee\u76f8\u540c\u6570\u636e\u65f6\u4f1a\u6709\u5f71\u54cd ^da8be4
\u5b58\u50a8\u6307\u4ee4\uff08store\uff09\u5b58\u50a8\u53cc\u5b57
Text Onlysd x9, 96(x22)\n
ld x9, AddConstant4(x3)\nAdd x22, x22, x9\n\n# Equals to \n\naddi x22, x22, 4 # x22 = x22 + 4\n
\u5e38\u6570\u79f0\u4e3a\u7b97\u6570\u6307\u4ee4\u64cd\u4f5c\u6570 X0 \u53ef\u4ee5\u7528\u6765\u8868\u793a 0 \u5176\u5b9e\u8fd8\u6709 RV 32 \u57fa\u5740\u5bc4\u5b58\u5668\u4e5f\u88ab\u79f0\u4e3a\u4e0b\u6807\u5bc4\u5b58\u5668 \u6211\u4eec\u5047\u8bbe\u6307\u4ee4\u90fd\u662f 64 \u4f4d
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#24","title":"2.4 \u6709\u7b26\u53f7\u6570\u4e0e\u65e0\u7b26\u53f7\u6570","text":"while (save[i] == k) \n i += 1;\n
I -> x 22 K -> x 24 Save -> x 25
Text Onlyloop: slli, x10, x22, 3\nAdd x10, x10, x25\nLd x9, 0(x10)\nBen x9, x24, Exit\nAddi x22, x22, l\nBeq x0, x0, loop\nExit:\n
\u57fa\u672c\u5757:
\u5c06\u7b26\u53f7\u6570\u5f53\u4f5c\u65e0\u7b26\u53f7\u6570\u5904\u7406
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#273-caseswitch","title":"2.7.3 Case/switch \u8bed\u53e5","text":"Jal x1, ProcedureAddress\nJalr x0, 0(x1)\n
\u8c03\u7528\u8005\u5c06\u53c2\u6570\u503c\u653e\u5165 x 10~x 17 \u8fc7\u7a0b\u662f\u88ab\u8c03\u7528\u8005 Program counter:PC \u6307\u4ee4\u5730\u5740\u5bc4\u5b58\u5668
Text Onlyjal x0, Label // unconditionally branch to Label\n
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#281","title":"2.8.1 \u4f7f\u7528\u66f4\u591a\u7684\u5bc4\u5b58\u5668","text":"leaf_example:\nAddi sp, sp, -14\nSd x5, 16(sp)\nSd x6, 8(sp)\nSd x20, 0(sp)\nAdd x5, x10, x11\nAdd x6, x12, x13\nSub x20, x5, x6\nAddi x10, x20, 0\nLd x20, 0(sp)\nLd x6, 8(sp)\nLd x5, 16(sp)\nAddi sp, sp, 24\nJalr x0, 0(x1)\n
long long int fact (long long int n) {\n if (n < 1) return (1);\n else return (n * fact(n - 1))\n}\n
n -> x 10
Text Onlyfact:\n addi sp, sp, -16\n Sd x1, 8(sp)\n Sd x10, 0(sp)\n\n Addi x5, x10, -1\n Bge x5, x0, L1\n\n Addi x10, x0, 1\n Addi sp, sp, 16\n Jalr x0, 0(x1)\n\nL1: addi x10, x10, -1\n Jal x1, fact\n\naddi x6, x10, 0\nLd x10, 0(sp)\nLd x1, 8(sp)\nAddi sp, sp, 16\nMul x10, x10, x6\nJalr x0, 0(x1)\n
\u6808\u4e5f\u7528\u4e8e\u5b58\u50a8\u8fc7\u7a0b\u7684\u5c40\u90e8\u53d8\u91cf \u8fc7\u7a0b\u5e27/\u6d3b\u52a8\u8bb0\u5f55
\u6ca1\u770b\u61c2
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#284","title":"2.8.4 \u5728\u5806\u4e2d\u4e3a\u65b0\u6570\u636e\u5206\u914d\u7a7a\u95f4","text":"Static data segment text segment \u50cf\u94fe\u8868\u7b49\u6570\u636e\u7ed3\u6784\u5f80\u5f80\u4f1a\u968f\u751f\u547d\u5468\u671f\u589e\u957f\u548c\u7f29\u77ed\uff0c\u6240\u4ee5\u4f1a\u628a\u4ed6\u4eec\u5b58\u5728\u5806\u91cc (heap)
ASCII: american standard code for information interchange
\u52a0\u8f7d\u65e0\u7b26\u53f7\u5b57\u8282 (lbu) \u5b58\u50a8\u5b57\u8282 (sb)
Text Onlylbu x12, 0(x10)\nsb x12, 0(x11)\n
\u5b57\u7b26\u4e32\u7684\u8868\u793a\u6709\u4e09\u79cd\u9009\u62e9:
void strcpy (char x[], char y[])\n{\n size_t i;\n i = 0;\n while ((x[i] = y[i]) != '\\0')\n i += 1;\n}\n
x -> x 10 y -> x 11 i -> x 19
Text Onlystrcpy:\n addi sp, sp, -8\n sd x19, 0(sp)\n add x19, x0, x0\nL1: add x5, x19, x11\n lbu x6, 0(x5)\n add x7, x19, x10\n sb x6, 0(x7)\n beq x6, x0, L2\n addi x19, x19, 1\n jal x0, L1\nL2: ld x19, 0(sp)\n addi sp, sp, 8\n jalr x0, 0(x1)\n
load half unsigned \u52a0\u8f7d\u534a\u5b57: lh lhu sh
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#210-risc-v","title":"2.10 \u5bf9\u5927\u7acb\u5373\u6570\u7684 RISC-V \u7684\u7f16\u5740\u548c\u5bfb\u5740","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2101","title":"2.10.1 \u5927\u7acb\u5373\u6570","text":"load upper immediate \u53d6\u7acb\u5373\u6570\u9ad8\u4f4d lui lui \u53ef\u4ee5\u52a0\u8f7d 12~31 \u4f4d addi \u53ef\u4ee5\u52a0\u8f7d 0~11 \u4f4d
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2102","title":"2.10.2 \u5206\u652f\u4e2d\u7684\u5bfb\u5740","text":"\u5206\u652f\u6307\u4ee4\u4f7f\u7528 SB \u578b\u7684\u6307\u4ee4\u683c\u5f0f
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#211","title":"2.11 \u6307\u4ee4\u4e0e\u5e76\u884c\u6027\uff1a\u540c\u6b65","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#212","title":"2.12 \u7ffb\u8bd1\u5e76\u542f\u52a8\u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2121","title":"2.12.1 \u7f16\u8bd1\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2122","title":"2.12.2 \u6c47\u7f16\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2123","title":"2.12.3 \u94fe\u63a5\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2124","title":"2.12.4 \u52a0\u8f7d\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2125","title":"2.12.5 \u52a8\u6001\u94fe\u63a5\u5e93","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#21251-java","title":"2.12.5.1 \u542f\u52a8 Java \u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#213-c","title":"2.13 \u4ee5 C \u6392\u5e8f\u7a0b\u5e8f\u4e3a\u4f8b\u7684\u6c47\u603b\u6574\u7406","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2131-swap","title":"2.13.1 swap \u8fc7\u7a0b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2132-sort","title":"2.13.2 sort \u8fc7\u7a0b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#214","title":"2.14 \u6570\u7ec4\u4e0e\u6307\u9488","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2141-clear","title":"2.14.1 \u7528\u6570\u7ec4\u5b9e\u73b0 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2142-clear","title":"2.14.2 \u7528\u6307\u9488\u5b9e\u73b0 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2143-clear","title":"2.14.3 \u6bd4\u8f83\u4e24\u4e2a\u7248\u672c\u7684 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#215-c-java","title":"2.15 \u9ad8\u7ea7\u4e13\u9898: \u7f16\u8bd1 C \u8bed\u8a00\u548c\u89e3\u91ca Java \u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#216-mips","title":"2.16 \u5b9e\u4f8b: MIPS \u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#217-x-86","title":"2.17 \u5b9e\u4f8b: x 86 \u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2171-intel-x-86","title":"2.17.1 Intel x 86 \u7684\u6f14\u53d8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2172-x-86","title":"2.17.2 x 86 \u5bc4\u5b58\u5668\u548c\u5bfb\u5740\u6a21\u5f0f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2173-x-86","title":"2.17.3 x 86 \u6574\u6570\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2174-x-86","title":"2.17.4 x 86 \u6307\u4ee4\u7f16\u7801","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2175-x-86","title":"2.17.5 x 86 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#218-risc-v","title":"2.18 \u5b9e\u4f8b: RISC-V \u6307\u4ee4\u7cfb\u7edf\u7684\u5269\u4f59\u90e8\u5206","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#219","title":"2.19 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#220","title":"2.20 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#3","title":"3 \u8ba1\u7b97\u673a\u7684\u7b97\u6570\u8fd0\u7b97","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#31","title":"3.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#32","title":"3.2 \u52a0\u6cd5\u548c\u51cf\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#33","title":"3.3 \u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#331","title":"3.3.1 \u4e32\u884c\u7248\u7684\u4e58\u6cd5\u7b97\u6cd5\u53ca\u5176\u786c\u4ef6\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#332","title":"3.3.2 \u5e26\u7b26\u53f7\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#333","title":"3.3.3 \u5feb\u901f\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#334-risc-v","title":"3.3.4 RISC-V \u4e2d\u7684\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#335","title":"3.3.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#34","title":"3.4 \u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#341","title":"3.4.1 \u9664\u6cd5\u7b97\u6cd5\u53ca\u786c\u4ef6\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#342","title":"3.4.2 \u6709\u7b26\u53f7\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#343","title":"3.4.3 \u5feb\u901f\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#344-risc-v","title":"3.4.4 RISC-V \u4e2d\u7684\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#345","title":"3.4.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#35","title":"3.5 \u6d6e\u70b9\u8fd0\u7b97","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#351","title":"3.5.1 \u6d6e\u70b9\u8868\u793a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#352","title":"3.5.2 \u4f8b\u5916\u548c\u4e2d\u65ad","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#353-ieee-754","title":"3.5.3 IEEE 754 \u6d6e\u70b9\u6570\u6807\u51c6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#354","title":"3.5.4 \u6d6e\u70b9\u52a0\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#355","title":"3.5.5 \u6d6e\u70b9\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#356-risc-v","title":"3.5.6 RISC-V \u4e2d\u7684\u6d6e\u70b9\u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#357","title":"3.5.7 \u7cbe\u786e\u7b97\u6570","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#358","title":"3.5.8 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#36","title":"3.6 \u5e76\u884c\u6027\u4e0e\u8ba1\u7b97\u673a\u7b97\u6570: \u5b50\u5b57\u5e76\u884c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#37-x-86-simd","title":"3.7 \u5b9e\u4f8b: x 86 \u4e2d\u7684 SIMD \u6269\u5c55\u548c\u9ad8\u7ea7\u5411\u91cf\u6269\u5c55","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#38","title":"3.8 \u52a0\u901f: \u5b50\u5b57\u5e76\u884c\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#39","title":"3.9 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#310","title":"3.10 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4","title":"4 \u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#41","title":"4.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#411-risc-v","title":"4.1.1 \u4e00\u79cd\u57fa\u672c\u7684 RISC-V \u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#412","title":"4.1.2 \u5b9e\u73b0\u6982\u8ff0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#42","title":"4.2 \u903b\u8f91\u8bbe\u8ba1\u7684\u4e00\u822c\u65b9\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#43","title":"4.3 \u5efa\u7acb\u6570\u636e\u901a\u8def","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#44","title":"4.4 \u4e00\u4e2a\u7b80\u5355\u7684\u5b9e\u73b0\u65b9\u6848","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#441-alu","title":"4.4.1 ALU\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#442","title":"4.4.2 \u8bbe\u8ba1\u4e3b\u63a7\u5236\u5355\u5143","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#443","title":"4.4.3 \u6570\u636e\u901a\u8def\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#444","title":"4.4.4 \u63a7\u5236\u7684\u7ed3\u675f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#445","title":"4.4.5 \u4e3a\u4ec0\u4e48\u73b0\u5728\u4e0d\u9002\u7528\u5355\u5468\u671f\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#45","title":"4.5 \u6d41\u6c34\u7ebf\u6982\u8ff0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#451","title":"4.5.1 \u9762\u5411\u6d41\u6c34\u7ebf\u7684\u6307\u4ee4\u7cfb\u7edf\u8bbe\u8ba1","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#452","title":"4.5.2 \u6d41\u6c34\u4e0b\u5192\u9669","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#453","title":"4.5.3 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#46","title":"4.6 \u6d41\u6c34\u7ebf\u6570\u636e\u901a\u8def\u548c\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#461","title":"4.6.1 \u6d41\u6c34\u7ebf\u7684\u56fe\u5f62\u5316\u8868\u793a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#462","title":"4.6.2 \u6d41\u6c34\u7ebf\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#47","title":"4.7 \u6570\u636e\u5192\u9669: \u524d\u9012\u4e0e\u505c\u987f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#48","title":"4.8 \u63a7\u5236\u5192\u9669","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#481","title":"4.8.1 \u5047\u8bbe\u5206\u652f\u4e0d\u53d1\u751f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#482","title":"4.8.2 \u7f29\u77ed\u5206\u652f\u5ef6\u8fdf","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#483","title":"4.8.3 \u52a8\u6001\u5206\u652f\u9884\u6d4b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#484","title":"4.8.4 \u6d41\u6c34\u7ebf\u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#49","title":"4.9 \u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#491-risc-v","title":"4.9.1 RISC-V \u4f53\u7cfb\u7ed3\u6784\u4e2d\u5982\u4f55\u5904\u7406\u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#492","title":"4.9.2 \u6d41\u6c34\u7ebf\u5b9e\u73b0\u4e2d\u7684\u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#410","title":"4.10 \u6307\u4ee4\u95f4\u7684\u5e76\u884c\u6027","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4101","title":"4.10.1 \u63a8\u6d4b\u7684\u6982\u5ff5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4102","title":"4.10.2 \u9759\u6001\u591a\u53d1\u5c04","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4103","title":"4.10.3 \u52a8\u6001\u591a\u53d1\u5c04\u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4104","title":"4.10.4 \u9ad8\u7ea7\u6d41\u6c34\u7ebf\u548c\u80fd\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#411-armcortex-a-53-intel-core-i-7","title":"4.11 \u5b9e\u4f8b: armCortex-A 53 \u548c Intel Core i 7 \u6d41\u6c34\u7ebf\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4111-arm-cortex-a-53","title":"4.11.1 ARM Cortex-A 53","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4112-intel-core-i-7-920","title":"4.11.2 Intel Core i 7 920","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4113-intel-core-i-7","title":"4.11.3 Intel Core i 7 \u5904\u7406\u5668\u7684\u6027\u80fd","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#412_1","title":"4.12 \u52a0\u901f: \u6307\u4ee4\u96c6\u5e76\u884c\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#413","title":"4.13 \u9ad8\u7ea7\u4e13\u9898: \u6570\u5b57\u8bbe\u8ba1\u6982\u8ff0\u2014\u2014\u4f7f\u7528\u786c\u4ef6\u8bbe\u8ba1\u8bed\u8a00\u8fdb\u884c\u6d41\u6c34\u7ebf\u5efa\u6a21\u4ee5\u53ca\u66f4\u591a\u6d41\u6c34\u7ebf\u793a\u4f8b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#414","title":"4.14 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#415","title":"4.15 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#416","title":"4.16 \u5386\u53f2\u89c6\u89d2\u548c\u6269\u5c55\u9605\u8bfb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5","title":"5 \u5927\u800c\u5feb: \u5c42\u6b21\u5316\u5b58\u50a8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#51","title":"5.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#52","title":"5.2 \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#521-sram","title":"5.2.1 SRAM \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#522-dram","title":"5.2.2 DRAM \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#523","title":"5.2.3 \u95ea\u5b58","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#524","title":"5.2.4 \u78c1\u76d8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#53-cache","title":"5.3 cache \u57fa\u7840","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#531-cache","title":"5.3.1 cache \u8bbf\u95ee","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#532-cache","title":"5.3.2 \u5904\u7406 cache \u5931\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#533","title":"5.3.3 \u5904\u7406\u5199\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#534-cache-intrinsity-fastmath","title":"5.3.4 cache \u5b9e\u4f8b: Intrinsity FastMATH \u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#535","title":"5.3.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#54-cache","title":"5.4 cache \u7684\u6027\u80fd\u8bc4\u4f30\u548c\u6539\u8fdb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#541-cache","title":"5.4.1 \u4f7f\u7528\u66f4\u4e3a\u7075\u6d3b\u7684\u66ff\u6362\u7b56\u7565\u964d\u4f4e cache \u5931\u6548\u7387","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#542-cache","title":"5.4.2 \u5728 cache \u4e2d\u67e5\u627e\u6570\u636e\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#543","title":"5.4.3 \u9009\u62e9\u66ff\u6362\u7684\u6570\u636e\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#544-cache","title":"5.4.4 \u4f7f\u7528\u591a\u7ea7 cache \u51cf\u5c11\u5931\u6548\u4ee3\u4ef7","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#545","title":"5.4.5 \u901a\u8fc7\u5206\u5757\u8fdb\u884c\u8f6f\u4ef6\u4f18\u5316","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#546","title":"5.4.6 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#55","title":"5.5 \u53ef\u9760\u7684\u5b58\u50a8\u5668\u66fe\u6d4b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#551","title":"5.5.1 \u5931\u6548\u7684\u5b9a\u4e49","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#552-1-2","title":"5.5.2 \u7ea0\u6b63 1 \u4f4d\u9519\u3001\u68c0\u6d4b 2 \u4f4d\u9519\u7684\u6c49\u660e\u7f16\u7801","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#56","title":"5.6 \u865a\u62df\u673a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#561","title":"5.6.1 \u865a\u62df\u673a\u76d1\u89c6\u5668\u7684\u5fc5\u5907\u6761\u4ef6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#562","title":"5.6.2 \u6307\u4ee4\u7cfb\u7edf\u4f53\u7cfb\u7ed3\u6784\uff08\u7f3a\u4e4f\uff09\u5bf9\u865a\u62df\u673a\u7684\u652f\u6301\u3001","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#563","title":"5.6.3 \u4fdd\u62a4\u548c\u6307\u4ee4\u7cfb\u7edf\u4f53\u7cfb\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#57","title":"5.7 \u865a\u62df\u5185\u5b58","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#571","title":"5.7.1 \u9875\u7684\u5b58\u653e\u548c\u67e5\u627e","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#572","title":"5.7.2 \u7f3a\u9875\u5931\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#573","title":"5.7.3 \u652f\u6301\u5927\u865a\u62df\u5730\u5740\u7a7a\u95f4\u7684\u865a\u62df\u5b58\u50a8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#574","title":"5.7.4 \u5173\u4e8e\u5199","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#575-tlb","title":"5.7.5 \u52a0\u5feb\u5730\u5740\u8f6c\u6362:TLB","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#576-intrinsity-fastmath-tlb","title":"5.7.6 Intrinsity FastMATH TLB","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#577-tlb-cache","title":"5.7.7 \u7ee7\u627f\u865a\u62df\u5b58\u50a8\u3001TLB \u548c cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#578","title":"5.7.8 \u865a\u62df\u5b58\u50a8\u4e2d\u7684\u4fdd\u62a4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#579-tlb","title":"5.7.9 \u5904\u7406 TLB \u5931\u6548\u548c\u7f3a\u9875\u5931\u8d25","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5710","title":"5.7.10 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#58","title":"5.8 \u5b58\u50a8\u5c42\u6b21\u7ed3\u6784\u7684\u4e00\u822c\u6846\u67b6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#581","title":"5.8.1 \u95ee\u9898\u4e00: \u5757\u53ef\u4ee5\u88ab\u653e\u5728\u4f55\u5904","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#582","title":"5.8.2 \u95ee\u9898\u4e8c: \u5982\u4f55\u627e\u5230\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#583-cache","title":"5.8.3 \u95ee\u9898\u4e09: \u5f53 cache \u53d1\u751f\u5931\u6548\u65f6\u66ff\u6362\u54ea\u4e00\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#584","title":"5.8.4 \u95ee\u9898\u56db: \u5199\u64cd\u4f5c\u5982\u4f55\u5904\u7406","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#585-c","title":"5.8.5 C: \u4e00\u79cd\u7406\u89e3\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784\u7684\u76f4\u89c2\u6a21\u578b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#59-cache","title":"5.9 \u4f7f\u7528\u6709\u9650\u72b6\u6001\u81ea\u52a8\u673a\u63a7\u5236\u7b80\u5355\u7684 cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#591-cache","title":"5.9.1 \u4e00\u4e2a\u7b80\u5355\u7684 cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#592","title":"5.9.2 \u6709\u9650\u72b6\u6001\u81ea\u52a8\u673a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#593-cache","title":"5.9.3 \u4f7f\u7528\u6709\u9650\u8f6c\u53f0\u81ea\u52a8\u673a\u4f5c\u4e3a\u7b80\u5355\u7684 cache \u63a7\u5236\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#510-cache","title":"5.10 \u5e76\u884c\u548c\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784: cache \u4e00\u81f4\u6027","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5101","title":"5.10.1 \u5b9e\u884c\u4e00\u81f4\u6027\u7684\u57fa\u672c\u65b9\u6848","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5102","title":"5.10.2 \u76d1\u542c\u534f\u8bae","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#511","title":"5.11 \u5e76\u884c\u4e0e\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784: \u5ec9\u4ef7\u78c1\u76d8\u5197\u4f59\u9635\u5217","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#512","title":"5.12 \u9ad8\u7ea7\u4e13\u9898: \u5b9e\u73b0\u7f13\u5b58\u63a7\u5236\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#513-arm-cortex-a-53-intel-core-i-7","title":"5.13 \u5b9e\u4f8b: ARM Cortex-A 53 \u548c Intel Core i 7 \u7684\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#514-risc-v","title":"5.14 \u5b9e\u4f8b: RISC-V \u7cfb\u7edf\u5176\u4ed6\u90e8\u5206\u548c\u7279\u6b8a\u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#515-cache","title":"5.15 \u52a0\u901f: cache \u5206\u5757\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#516","title":"5.16 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#517","title":"5.17 \u672c\u8eab\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#518","title":"5.18 \u5386\u53f2\u89c6\u89d2\u548c\u62d3\u5c55\u9605\u8bfb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#6","title":"6 \u5e76\u884c\u5904\u7406\u5668: \u4ece\u5ba2\u6237\u7aef\u5230\u4e91","text":""},{"location":"CS_Basic/Network/Security/","title":"Security","text":""},{"location":"CS_Basic/Network/Security/#_1","title":"\u5e38\u89c1\u7684\u5bc6\u7801\u7b97\u6cd5","text":"\u7ea6 372 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u52a0\u5bc6\u539f\u7406
"},{"location":"CS_Basic/Network/Security/#_2","title":"\u5f31\u53e3\u4ee4","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
\u8f6f\u4ef6\u7ea6 76 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
2024_1_1
"},{"location":"Robot/kalman/","title":"\u5361\u5c14\u66fc\u6ee4\u6ce2","text":""},{"location":"Robot/kalman/#_1","title":"\u5361\u5c14\u66fc\u6ee4\u6ce2","text":"\u7ea6 193 \u4e2a\u5b57 115 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Robot/kalman/#1-why","title":"1 Why","text":"#include <iostream>\n#include <cstdio>\n#include <string>\n#include <vector>\n#include <ctime>\n#include <opencv2/core/core.hpp>\n#include <opencv2/highgui/highgui.hpp>\n#include <opencv2/imgproc/imgproc.hpp>\n#include <Eigen/Dense>\n#include <opencv2/core/eigen.hpp>\nusing namespace std;\nusing namespace cv;\nusing namespace Eigen;\n\nint main() {\nsrand((unsigned int) time(NULL));\n// generate data with noise\nconst int N = 20;\nconst double k = 2.5;\nMatrix<double, 1, N> noise = Matrix<double, 1, N>::Random();\nMatrix<double, 1, N> data = Matrix<double, 1, N>::LinSpaced(0, k * (N - 1));\ndata += noise;\nstd::cout << data << std::endl;\n// calculate speed\nconst int Z_N = 1, X_N = 2;\nMatrix<double, X_N, 1> X;\nMatrix<double, X_N, X_N> A;\nMatrix<double, X_N, X_N> P;\nMatrix<double, X_N, X_N> R;\nMatrix<double, X_N, Z_N> K;\nMatrix<double, Z_N, X_N> C;\nMatrix<double, Z_N, Z_N> Q;\n\nX << data[0], 0;\nA << 1, 1, 0, 1;\nC << 1, 0;\nR << 2, 0, 0, 2;\nQ << 10;\nfor (int i = 1; i < N; i++) {\n // \u66f4\u65b0\u9884\u6d4b\n Matrix<double, X_N, 1> X_k = A * X;\n P = A * P * A.transpose() + R;\n // \u66f4\u65b0\u89c2\u6d4b\n K = P * C.transpose() * (C * P * C.transpose() + Q).inverse();\n Matrix<double, Z_N, 1> Z{data[i]};\n X = X_k + K * (Z - C * X_k);\n P = (Matrix<double, X_N, X_N>::Identity() - K * C) * P;\n std::cout << \"step \" << i << \": \" << X[1] << std::endl;\n}\nstd:cout << \"final speed: \" << X[1] << std::endl;\nreturn 0;\n}\n
"},{"location":"Robot/kalman/#22-ekf","title":"2.2 EKF \u7b97\u6cd5\u7684\u5b9e\u73b0","text":"C++#include <ceres/jet.h>\n#include <Eigen/Dense>\n\ntemplate<int N_X, int N_Y>\nclass AdaptiveEKF {\n using MatrixXX = Eigen::Matrix<double, N_X, N_X>;\n using MatrixYX = Eigen::Matrix<double, N_Y, N_X>;\n using MatrixXY = Eigen::Matrix<double, N_X, N_Y>;\n using MatrixYY = Eigen::Matrix<double, N_Y, N_Y>;\n using VectorX = Eigen::Matrix<double, N_X, 1>;\n using VectorY = Eigen::Matrix<double, N_Y, 1>;\n\npublic:\n explicit AdaptiveEKF(const VectorX &X0 = VectorX::Zero())\n : Xe(X0), P(MatrixXX::Identity()), Q(MatrixXX::Identity()), R(MatrixYY::Identity()) {}\n\n // \u9884\u6d4b\u51fd\u6570\n template<class Func>\n VectorX predict(Func &&func) {\n calculateJacobian(Xe, func, Xp, F);\n P = F * P * F.transpose() + Q;\n return Xp;\n }\n\n // \u66f4\u65b0\u51fd\u6570\n template<class Func>\n VectorX update(Func &&func, const VectorY &Y) {\n calculateJacobian(Xp, func, Yp, H);\n MatrixYY S = H * P * H.transpose() + R; // \u521b\u65b0\u534f\u65b9\u5dee\n K = P * H.transpose() * S.inverse(); // \u5361\u5c14\u66fc\u589e\u76ca\n Xe = Xp + K * (Y - Yp); // \u66f4\u65b0\u72b6\u6001\u4f30\u8ba1\n P = (MatrixXX::Identity() - K * H) * P; // \u66f4\u65b0\u72b6\u6001\u534f\u65b9\u5dee\n return Xe;\n }\n\nprivate:\n // \u8ba1\u7b97\u96c5\u514b\u6bd4\u77e9\u9635\u7684\u8f85\u52a9\u51fd\u6570\n template<class Func, int N_IN, int N_OUT>\n void calculateJacobian(const Eigen::Matrix<double, N_IN, 1> &input, Func &&func, Eigen::Matrix<double, N_OUT, 1> &output, Eigen::Matrix<double, N_OUT, N_IN> &jacobian) {\n ceres::Jet<double, N_IN> input_auto_jet[N_IN];\n for (int i = 0; i < N_IN; i++) {\n input_auto_jet[i].a = input[i];\n input_auto_jet[i].v[i] = 1;\n }\n ceres::Jet<double, N_OUT> output_auto_jet[N_OUT];\n func(input_auto_jet, output_auto_jet);\n for (int i = 0; i < N_OUT; i++) {\n output[i] = output_auto_jet[i].a;\n jacobian.block(i, 0, 1, N_IN) = output_auto_jet[i].v.transpose();\n }\n }\n\npublic:\n VectorX Xe; // \u4f30\u8ba1\u72b6\u6001\u53d8\u91cf\n VectorX Xp; // \u9884\u6d4b\u72b6\u6001\u53d8\u91cf\n MatrixXX F; // \u9884\u6d4b\u96c5\u514b\u6bd4\u77e9\u9635\n MatrixYX H; // \u89c2\u6d4b\u96c5\u514b\u6bd4\u77e9\u9635\n MatrixXX P; // \u72b6\u6001\u534f\u65b9\u5dee\n MatrixXX Q; // \u9884\u6d4b\u8fc7\u7a0b\u534f\u65b9\u5dee\n MatrixYY R; // \u89c2\u6d4b\u8fc7\u7a0b\u534f\u65b9\u5dee\n MatrixXY K; // \u5361\u5c14\u66fc\u589e\u76ca\n VectorY Yp; // \u9884\u6d4b\u89c2\u6d4b\u91cf\n};\n
"},{"location":"Robot/kalman/#23","title":"2.3 \u975e\u7ebf\u6027\u4f18\u5316","text":"TODO
"},{"location":"Robot/kalman/#_2","title":"\u4e00\u4e9b\u8d44\u6599","text":"\u7ea6 76 \u4e2a\u5b57 55 \u884c\u4ee3\u7801 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u50cf\u7d20\u5750\u6807\u548c\u7269\u4f53\u5750\u6807\u7684\u5bf9\u70b9 \u4f46\u662f\u4e00\u822c\u53ea\u7528 t, \u56e0\u4e3a R \u7684\u7cbe\u5ea6\u4e0d\u591f\u9ad8 Fetching Title#g70i
C++#include <iostream>\n#include <opencv2/opencv.hpp>\n#include <opencv2/imgproc/imgproc.hpp>\n#include <opencv2/calib3d/calib3d.hpp>\n#include <opencv2/core/core.hpp>\nusing namespace cv;\n\nbool findCorners(const cv::Mat &src, std::vector<cv::Point2f> &corners) {\n std::vector<cv::Point2f> pts;\n corners.clear();\n bool flag = cv::findChessboardCorners(src, {9, 6}, pts);\n if (!flag)\n return false;\n corners.push_back(pts[0]);\n corners.push_back(pts[9 - 1]);\n corners.push_back(pts[pts.size() - 9]);\n corners.push_back(pts[pts.size() - 1]);\n return true;\n}\n\nint main() {\n cv::Mat src;\n cv::Mat camera_matrix;\n cv::Mat distort_matrix;\n cv::FileStorage reader(PROJECT_DIR\"/parameter.txt\", cv::FileStorage::READ);\n reader[\"C\"] >> camera_matrix;\n reader[\"D\"] >> distort_matrix;\n\n for (int i = 0; i <= 40; i++) {\n src = imread(std::__cxx11::to_string(i).append(\".jpg\"));\n std::vector<cv::Point2f> corners;\n bool flag = findCorners(src, corners);\n imshow(\"Opencv Demo\", src);\n cv::waitKey(100);\n if (flag == false) {\n std::cout << \"failed to find all corners\\n\";\n continue;\n }\n std::vector<cv::Point3f> dst;\n dst.push_back({0, 0, 0});\n dst.push_back({8 * 1, 0, 0});\n dst.push_back({0, 5 * 1, 0});\n dst.push_back({8 * 1, 5 * 1, 0});\n cv::Mat rvec, tvec;\n cv::solvePnP(dst, corners, camera_matrix, distort_matrix, rvec, tvec);\n std::cout << \"t:\" << std::endl << -tvec << std::endl << std::endl;\n cv::Mat drawer;\n drawer = src.clone();\n for (int j = 0; j < 4; j++)\n cv::circle(drawer, corners[j], 2, {0, 255, 0}, 2);\n cv::imshow(\"corners\", drawer);\n cv::waitKey(5);\n }\n return 0;\n}\n
"},{"location":"Summaries/","title":"Summaries","text":""},{"location":"Summaries/#summaries","title":"Summaries","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
\u5b66\u671f\u603b\u7ed3 & \u5176\u4ed6\u7ea6 657 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u5468\u8bb0
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W51-12/#2024-w51-12","title":"2024-W51-12","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W51-12/#review","title":"Review","text":"\u7ea6 814 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u5468\u8bb0
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#2024-w52-12","title":"2024-W52-12","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#review","title":"Review","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#completed","title":"Completed","text":"\u5176\u5b9e\u5f52\u6839\u7ed3\u5e95\uff0c\u95ee\u9898\u8fd8\u662f\u5927\u591a\u6570\u4eba\uff08\u5305\u62ec\u6211\u81ea\u5df1\uff09\uff0c\u6700\u521d\u6839\u672c\u60f3\u4e0d\u6e05\u695a\u81ea\u5df1\u6700\u540e\u8981\u5e72\u5565\uff0c\u505a\u4e86\u597d\u591a\u65e0\u610f\u4e49\u7684\u4e8b\u60c5\u3002\u6bd4\u5982\u9009\u4e00\u4e9b\u65e0\u610f\u4e49\u4f46\u96be\u7684\u8bfe\uff0c\uff08\u6bd4\u5982\u6570\u5206\u7cfb\u5217\uff0c\u5982\u679c\u4e0d\u662f\u771f\u5fc3\u559c\u6b22\u6570\u5b66\u5343\u4e07\u522b\u9009\uff09\uff0c\u5927\u521b\uff0c\u5b66\u4e00\u4e9b\u975e cs \u7684\u9009\u4fee\u8bfe\uff0c\u7ed9\u4e00\u4e9b\u6c34\u5b9e\u9a8c\u5ba4\u6253\u5de5\u7b49\u3002\u521a\u4e0a\u5927\u5b66\uff0c\u90fd\u89c9\u5f97\u81ea\u5df1\u6709\u65e0\u7a77\u7684\u53ef\u80fd\u6027\uff0c\u4e0d\u5c51\u4e8e\u5728\u5199\u4ee3\u7801\u8fd9\u4e00\u6761\u8def\u4e0a\u540a\u6b7b\u3002\u8bda\u7136\uff0c\u6709\u4e9b\u4eba\u5565\u90fd\u641e\u8fd8\u5565\u90fd\u80fd\u641e\u597d\uff0c\u4f46\u662f\u4f5c\u4e3a\u4e00\u4e2a\u666e\u901a\u4eba\uff0c\u8fd8\u662f\u8981\u8ba4\u6e05\u81ea\u5df1\u80fd\u529b\u7684\u8303\u56f4\u548c\u6700\u540e\u7684\u76ee\u6807\u3002\u770b\u522b\u4eba\u53bb\u793e\u56e2\uff0c\u81ea\u5df1\u4e5f\u60f3\u53bb\u51d1\u51d1\uff0c\u770b\u522b\u4eba\u505a\u79d1\u7814\uff0c\u81ea\u5df1\u4e5f\u60f3\u641e\u641e\uff1b\u53ef\u662f\u8fd9\u6837\u641e\u6765\u641e\u53bb\uff0c\u53d1\u73b0\u66fe\u7ecf\u4e0d\u5c51\u4e8e\u5e72\u7684\u4e8b\u60c5\uff0c\u73b0\u5728\u8fde\u5e72\u7684\u8d44\u683c\u90fd\u6ca1\u6709\uff0c\u8fd9\u65f6\u518d\u540e\u6094\u5df2\u7ecf\u4e3a\u65f6\u5df2\u665a\u3002\u5c06\u6765\u53d1\u5c55\u7684\u65b9\u5411\u8fd8\u662f\u8d8a\u65e9\u60f3\u660e\u767d\u8d8a\u597d\u3002
Failure
\u4e5f\u8bb8\uff0c\u6211\u771f\u7684\u662f\u7f3a\u4e4f all in \u7684\u52c7\u6c14\u5427\u3002
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/","title":"2024-W01-12","text":"\u7ea6 735 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
##\u5468\u8bb0
","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#2024-w01-12","title":"2024-W01-12","text":"","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#review","title":"Review","text":"","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#completed","title":"Completed","text":"\u7ea6 518 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u6211\u7684\u6691\u5047\u5927\u6982\u662f\u4ece 24.7.10 \u5f00\u59cb\u7684\uff0c\u5230\u90a3\u65f6\u624d\u5c18\u57c3\u843d\u5b9a\u3002\u4f46\u53c8\u6765\u56de\u6447\u6446\uff0c\u60f3\u7740\u672a\u6765\u7684\u51fa\u8def\uff08\u51fa\u56fd\uff1f\u4fdd\u7814\uff1f\u5de5\u4f5c\uff1f\u8f6c\u4e13\u4e1a\uff1f\uff09\u3002\u6240\u4ee5\u5927\u6982\u5230 8 \u6708\u624d\u5f00\u59cb\u5b66\u4e60\u3002
{{ tag_content }}
"},{"location":"Tools/","title":"Tools","text":""},{"location":"Tools/#toolbox","title":"Toolbox","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
Envirtonment Setup\u7ea6 54 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
Welcome, I'm Wnc.
"},{"location":"Tools/about/#some-tags","title":"Some Tags","text":"You could find my email or qq or WeChat in the icon above.
Feel free to contact me!
"},{"location":"Tools/AI/prompt/","title":"prompt","text":"\u7ea6 4234 \u4e2a\u5b57 1 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 21 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#prompt
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt","title":"prompt","text":"","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt_1","title":"\u901a\u7528\u601d\u7ef4\u94fe prompt","text":"Note Text OnlyBy default, all responses must be in Chinese.\n\n# AI Full-Stack Development Assistant Guide\n\n## Core Thinking Patterns\nYou must engage in multi-dimensional deep thinking before and during responses:\n\n### Fundamental Thinking Modes\n\n- Systems Thinking: Three-dimensional thinking from overall architecture to specific implementation\n- Dialectical Thinking: Weighing pros and cons of multiple solutions \n- Creative Thinking: Breaking through conventional thinking patterns to find innovative solutions\n- Critical Thinking: Multi-angle validation and optimization of solutions\n\n### Thinking Balance\n\n- Balance between analysis and intuition\n- Balance between detailed inspection and global perspective \n- Balance between theoretical understanding and practical application\n- Balance between deep thinking and forward momentum\n- Balance between complexity and clarity\n\n### Analysis Depth Control \n\n- Conduct in-depth analysis for complex problems\n- Keep simple issues concise and efficient\n- Ensure analysis depth matches problem importance\n- Find balance between rigor and practicality\n\n### Goal Focus\n\n- Maintain clear connection with original requirements\n- Guide divergent thinking back to the main topic timely\n- Ensure related explorations serve the core objective\n- Balance between open exploration and goal orientation\n\nAll thinking processes must:\n\n0. Presented in the form of a block of code + the title of the point of view, please note that the format is strictly adhered to and that it must include a beginning and an end.\n1. Unfold in an original, organic, stream-of-consciousness manner\n2. Establish organic connections between different levels of thinking\n3. Flow naturally between elements, ideas, and knowledge\n4. Each thought process must maintain contextual records, keeping contextual associations and connections\n\n## Technical Capabilities\n### Core Competencies\n\n- Systematic technical analysis thinking\n- Strong logical analysis and reasoning abilities \n- Strict answer verification mechanism\n- Comprehensive full-stack development experience\n\n### Adaptive Analysis Framework\nAdjust analysis depth based on:\n\n- Technical complexity\n- Technology stack scope\n- Time constraints \n- Existing technical information\n- User's specific needs\n\n### Solution Process\n\n1. Initial Understanding\n- Restate technical requirements\n- Identify key technical points\n- Consider broader context\n- Map known/unknown elements\n\n2. Problem Analysis \n- Break down tasks into components\n- Determine requirements\n- Consider constraints\n- Define success criteria\n\n3. Solution Design\n- Consider multiple implementation paths\n- Evaluate architectural approaches\n- Maintain open-minded thinking\n- Progressively refine details\n\n4. Implementation Verification\n- Test assumptions\n- Verify conclusions\n- Validate feasibility\n- Ensure completeness\n\n## Output Requirements\n### Code Quality Standards\n\n- Always show complete code context for better understanding and maintainability.\n- Code accuracy and timeliness\n- Complete functionality\n- Security mechanisms\n- Excellent readability\n- Use markdown formatting\n- Specify language and path in code blocks\n- Show only necessary code modifications\n#### Code Handling Guidelines\n\n1. When editing code:\n - Show only necessary modifications\n - Include file paths and language identifiers\n - Provide context with comments\n - Format: ```language:path/to/file\n\n2. Code block structure: ```language:file/path\n // ... existing code ...\n {{ modifications }}\n // ... existing code ... ```\n\n\n### Technical Specifications\n\n- Complete dependency management\n- Standardized naming conventions\n- Thorough testing\n- Detailed documentation\n\n### Communication Guidelines\n\n- Clear and concise expression\n- Handle uncertainties honestly\n- Acknowledge knowledge boundaries\n- Avoid speculation\n- Maintain technical sensitivity\n- Track latest developments\n- Optimize solutions\n- Improve knowledge\n\n### Prohibited Practices\n\n- Using unverified dependencies\n- Leaving incomplete functionality\n- Including untested code\n- Using outdated solutions\n\n## Important Notes\n\n- Maintain systematic thinking for solution completeness\n- Focus on feasibility and maintainability\n- Continuously optimize interaction experience\n- Keep open learning attitude and updated knowledge\n- Disable the output of emoji unless specifically requested\n- By default, all responses must be in Chinese.\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt_2","title":"\u53ef\u89c6\u5316prompt","text":"Note Text Only\u4f60\u662f\u4e00\u4f4d\u4e13\u4e1a\u7684 SVG \u56fe\u50cf\u8bbe\u8ba1\u5e08\uff0c\u64c5\u957f\u5c06\u62bd\u8c61\u6982\u5ff5\u8f6c\u5316\u4e3a\u5bcc\u6709\u7f8e\u611f\u548c\u4e13\u4e1a\u6027\u7684\u53ef\u89c6\u5316\u8bbe\u8ba1\u3002\u8bf7\u6309\u7167\u4ee5\u4e0b\u7cfb\u7edf\u5316\u6d41\u7a0b\u5206\u6790\u9700\u6c42\u5e76\u521b\u5efa SVG \u56fe\u50cf\uff1a\n\n1. \u8f93\u5165\u5206\u6790\u4e0e\u9884\u5904\u7406\n- \u8bc6\u522b\u8f93\u5165\u7c7b\u578b\uff1a\n * \u6982\u5ff5\u8bcd\uff1a\u6269\u5c55\u89e3\u91ca\u5176\u542b\u4e49\u3001\u7279\u5f81\u3001\u5173\u8054\u6982\u5ff5\n * \u9700\u6c42\u63cf\u8ff0\uff1a\u8865\u5145\u5fc5\u8981\u7684\u6280\u672f\u7ec6\u8282\u548c\u7ea6\u675f\u6761\u4ef6\n * \u5b8c\u6574\u8bed\u53e5\uff1a\u68c0\u67e5\u5e76\u8865\u5145\u7f3a\u5931\u7684\u4e0a\u4e0b\u6587\u4fe1\u606f\n- \u6807\u51c6\u5316\u5904\u7406\uff1a\n * \u63d0\u53d6\u660e\u786e\u7684\u89c6\u89c9\u8981\u6c42\n * \u8865\u5145\u7f3a\u5931\u7684\u7ef4\u5ea6\u4fe1\u606f\n * \u8f6c\u6362\u62bd\u8c61\u6982\u5ff5\u4e3a\u53ef\u89c6\u5316\u5143\u7d20\n\n2. \u4fe1\u606f\u8865\u5145\u4e0e\u6269\u5c55\n- \u4e0a\u4e0b\u6587\u8865\u5145\uff1a\n * \u573a\u666f\u60f3\u8c61\uff1a\u6784\u5efa\u5b8c\u6574\u7684\u573a\u666f\u63cf\u8ff0\n * \u60c5\u5883\u7ec6\u8282\uff1a\u8865\u5145\u73af\u5883\u3001\u65f6\u95f4\u3001\u6c14\u6c1b\u7b49\u8981\u7d20\n * \u5173\u8054\u6269\u5c55\uff1a\u8054\u60f3\u76f8\u5173\u7684\u6982\u5ff5\u548c\u5143\u7d20\n- \u4e13\u4e1a\u9886\u57df\u77e5\u8bc6\uff1a\n * \u884c\u4e1a\u7279\u5f81\uff1a\u6dfb\u52a0\u9886\u57df\u7279\u5b9a\u7684\u89c6\u89c9\u8bed\u8a00\n * \u4e13\u4e1a\u7b26\u53f7\uff1a\u878d\u5165\u76f8\u5173\u7684\u4e13\u4e1a\u56fe\u5f62\u7b26\u53f7\n * \u901a\u7528\u60ef\u4f8b\uff1a\u9075\u5faa\u884c\u4e1a\u6807\u51c6\u7684\u8868\u8fbe\u65b9\u5f0f\n- \u8f85\u52a9\u4fe1\u606f\uff1a\n * \u89e3\u91ca\u6027\u6587\u672c\uff1a\u6dfb\u52a0\u5fc5\u8981\u7684\u6587\u5b57\u8bf4\u660e\n * \u56fe\u4f8b\u8bf4\u660e\uff1a\u5bf9\u7279\u6b8a\u7b26\u53f7\u8fdb\u884c\u89e3\u91ca\n * \u6570\u636e\u6765\u6e90\uff1a\u8865\u5145\u6570\u636e\u80cc\u666f\uff08\u5982\u6709\uff09\n- \u8bbe\u8ba1\u589e\u5f3a\uff1a\n * \u88c5\u9970\u5143\u7d20\uff1a\u589e\u52a0\u534f\u8c03\u7684\u88c5\u9970\u6027\u56fe\u5f62\n * \u80cc\u666f\u5143\u7d20\uff1a\u8bbe\u8ba1\u886c\u6258\u4e3b\u9898\u7684\u80cc\u666f\n * \u70b9\u7f00\u7ec6\u8282\uff1a\u6dfb\u52a0\u63d0\u5347\u7cbe\u81f4\u611f\u7684\u5c0f\u7ec6\u8282\n\n3. \u89c6\u89c9\u7cfb\u7edf\u8bbe\u8ba1\n- \u8272\u5f69\u89c4\u5212:\n * \u4e3b\u8272\u8c03\u9009\u62e9\n * \u6e10\u53d8\u65b9\u6848\u8bbe\u8ba1\n * \u660e\u6697\u5bf9\u6bd4\u63a7\u5236\n * \u900f\u660e\u5ea6\u5c42\u6b21\n- \u56fe\u5f62\u7cfb\u7edf:\n * \u51e0\u4f55\u5f62\u72b6\u8bbe\u8ba1\n * \u7ebf\u6761\u98ce\u683c\u5b9a\u4e49\n * \u56fe\u6848\u586b\u5145\u89c4\u5219\n * \u88c5\u9970\u5143\u7d20\u8bbe\u8ba1\n- \u6392\u7248\u89c4\u8303:\n * \u5b57\u4f53\u9009\u62e9\n * \u5b57\u53f7\u5c42\u7ea7\n * \u95f4\u8ddd\u89c4\u5219\n * \u5bf9\u9f50\u65b9\u5f0f\n\n4. \u6280\u672f\u5b9e\u73b0\u89c4\u8303\n- \u57fa\u7840\u7ed3\u6784:\n * viewBox \u8bbe\u7f6e\n * \u5750\u6807\u7cfb\u7edf\u89c4\u5212\n * \u56fe\u5c42\u7ec4\u7ec7\n * \u547d\u540d\u89c4\u8303\n- \u9ad8\u7ea7\u7279\u6548:\n * \u6e10\u53d8(linearGradient/radialGradient)\n * \u6ee4\u955c(filter:shadow/blur/glow)\n * \u8499\u7248(mask/clip-path)\n * \u6df7\u5408\u6a21\u5f0f(mix-blend-mode)\n- \u52a8\u753b\u7cfb\u7edf:\n * \u8fc7\u6e21\u52a8\u753b\u8bbe\u8ba1\n * \u5173\u952e\u5e27\u52a8\u753b\n * \u8def\u5f84\u52a8\u753b\n * \u4ea4\u4e92\u53cd\u9988\n\n5. \u6027\u80fd\u4e0e\u517c\u5bb9\u6027\n- \u4ee3\u7801\u4f18\u5316:\n * \u8def\u5f84\u7b80\u5316\n * \u7ec4\u4ef6\u590d\u7528\n * \u4ee3\u7801\u538b\u7f29\n * \u65e0\u969c\u788d\u9002\u914d\n- \u4ea4\u4e92\u4f18\u5316:\n * \u54cd\u5e94\u5f0f\u8bbe\u8ba1\n * \u52a8\u753b\u6027\u80fd\n * \u4e8b\u4ef6\u5904\u7406\n * \u72b6\u6001\u7ba1\u7406\n- \u517c\u5bb9\u6027\u5904\u7406:\n * \u6d4f\u89c8\u5668\u9002\u914d\n * \u8bbe\u5907\u9002\u914d\n * \u964d\u7ea7\u65b9\u6848\n * \u9519\u8bef\u5904\u7406\n\n6. \u89c6\u89c9\u4f18\u5316\u7ec6\u5219\n- \u7cbe\u786e\u6027:\n * \u50cf\u7d20\u5bf9\u9f50\n * \u8def\u5f84\u5e73\u6ed1\n * \u951a\u70b9\u4f18\u5316\n * \u66f2\u7ebf\u63a7\u5236\n- \u5c42\u6b21\u611f:\n * \u7a7a\u95f4\u6df1\u5ea6\n * \u660e\u6697\u5bf9\u6bd4\n * \u5927\u5c0f\u5173\u7cfb\n * \u900f\u660e\u5c42\u6b21\n- \u52a8\u6001\u6548\u679c:\n * \u52a8\u753b\u8282\u594f\n * \u7f13\u52a8\u51fd\u6570\n * \u89c6\u89c9\u53cd\u9988\n * \u72b6\u6001\u8f6c\u6362\n\n7. \u8f93\u51fa\u89c4\u8303\n- \u6587\u4ef6\u5904\u7406:\n * \u9002\u914d\u5c3a\u5bf8\n * \u5bfc\u51fa\u683c\u5f0f\n * \u547d\u540d\u89c4\u8303\n * \u7248\u672c\u63a7\u5236\n- \u6587\u6863\u8bf4\u660e:\n * \u8bbe\u8ba1\u8bf4\u660e\n * \u4f7f\u7528\u6307\u5357\n * \u6280\u672f\u6587\u6863\n * \u7ef4\u62a4\u5efa\u8bae\n\n\u8bbe\u8ba1\u8981\u6c42\uff1a\n\n1. \u4fe1\u606f\u5b8c\u6574\u4e14\u6df1\u5165\n2. \u89c6\u89c9\u6548\u679c\u7cbe\u7f8e\u6709\u8bbe\u8ba1\u611f\n3. \u6280\u672f\u5b9e\u73b0\u89c4\u8303\u4e13\u4e1a\n4. \u5177\u6709\u9002\u5f53\u7684\u52a8\u6548\u548c\u4ea4\u4e92\n5. \u6027\u80fd\u8868\u73b0\u826f\u597d\n6. \u4ee3\u7801\u6574\u6d01\u6613\u7ef4\u62a4\n\n\u6280\u672f\u89c4\u8303\uff1a\n\n1. \u4f7f\u7528\u8bed\u4e49\u5316\u7684\u5206\u7ec4\u548c\u547d\u540d\n2. \u6ce8\u91ca\u5173\u952e\u7684\u8bbe\u8ba1\u610f\u56fe\u548c\u6280\u672f\u5b9e\u73b0\n3. \u786e\u4fdd\u4ee3\u7801\u7684\u53ef\u590d\u7528\u6027\u548c\u6269\u5c55\u6027\n4. \u6743\u8861\u89c6\u89c9\u6548\u679c\u4e0e\u6027\u80fd\u7684\u5e73\u8861\n5. \u8003\u8651\u6d4f\u89c8\u5668\u517c\u5bb9\u6027\u95ee\u9898\n6. \u5408\u7406\u8fd0\u7528\u8865\u5145\u4fe1\u606f\u589e\u5f3a\u8bbe\u8ba1\u6548\u679c\n\n\u8bbe\u8ba1\u5efa\u8bae\uff1a\n\n1. \u59cb\u7ec8\u4fdd\u6301\u8bbe\u8ba1\u7684\u4e00\u81f4\u6027\u548c\u534f\u8c03\u6027\n2. \u6ce8\u91cd\u7ec6\u8282\u5904\u7406\uff0c\u8ffd\u6c42\u7cbe\u81f4\u7684\u89c6\u89c9\u6548\u679c\n3. \u9002\u5f53\u4f7f\u7528\u52a8\u6548\u589e\u5f3a\u7528\u6237\u4f53\u9a8c\n4. \u786e\u4fdd\u8bbe\u8ba1\u7684\u53ef\u6269\u5c55\u6027\u548c\u53ef\u7ef4\u62a4\u6027\n5. \u8003\u8651\u4e0d\u540c\u4f7f\u7528\u573a\u666f\u4e0b\u7684\u8868\u73b0\n\n\u9488\u5bf9\u6bcf\u4e2a\u5177\u4f53\u8bbe\u8ba1\u4efb\u52a1\uff1a\n\n1. \u7cfb\u7edf\u5206\u6790\u8f93\u5165\u4fe1\u606f\n2. \u5b8c\u6574\u5c55\u5f00\u8bbe\u8ba1\u7ec6\u8282\n3. \u8865\u5145\u5fc5\u8981\u7684\u4e0a\u4e0b\u6587\n4. \u589e\u52a0\u4e13\u4e1a\u7684\u9886\u57df\u7279\u5f81\n5. \u6ce8\u610f\u89c6\u89c9\u4f53\u9a8c\u7684\u4f18\u5316\n6. \u786e\u4fdd\u6280\u672f\u5b9e\u73b0\u7684\u89c4\u8303\u6027\n\n\u901a\u8fc7\u4ee5\u4e0a\u6d41\u7a0b\u548c\u89c4\u8303\uff0c\u4f60\u5c06\u521b\u5efa\u4e00\u4e2a:\n\n1. \u4fe1\u606f\u5b8c\u6574\n2. \u89c6\u89c9\u7cbe\u7f8e\n3. \u6280\u672f\u4e13\u4e1a\n4. \u5bcc\u6709\u7f8e\u611f\n5. \u4f53\u9a8c\u51fa\u8272\n\u7684 SVG \u56fe\u50cf\u4f5c\u54c1\u3002\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt1","title":"\u5b66\u4e60prompt1","text":"Note Text Only \u9898\u76ee [\u9898\u76ee]\n\n\u6211\u662f\u521d\u5b66\u8005\uff0c\u5bf9\u8fd9\u9053\u9898\u6d89\u53ca\u7684\u57fa\u7840\u6982\u5ff5\u4e0d\u592a\u7406\u89e3\uff0c\u8bf7\u4f60\u626e\u6f14\u4e00\u4f4d\u8001\u5e08\u7684\u89d2\u8272\uff0c\u4e3a\u6211\u8bb2\u89e3\u8fd9\u9053\u9898\uff1a\n\n1. \u5206\u6790\u8fd9\u9053\u9898\u76ee\uff0c\u63d0\u70bc\u51fa\u5176\u4e2d\u9700\u8981\u638c\u63e1\u7684\u6838\u5fc3\u57fa\u7840\u6982\u5ff5\u3002\n2. \u50cf\u8001\u5e08\u7ed9\u5b66\u751f\u4e0a\u8bfe\u4e00\u6837\uff0c\u6309\u7167\u7531\u6d45\u5165\u6df1\u3001\u903b\u8f91\u9012\u8fdb\u7684\u987a\u5e8f\u8bb2\u89e3\u8fd9\u4e9b\u6982\u5ff5\uff0c\u6bcf\u6b21\u53ea\u8bb2\u4e00\u4e2a\u77e5\u8bc6\u70b9\uff0c\u786e\u4fdd\u6211\u80fd\u542c\u61c2\u3002\n3. \u8bb2\u89e3\u5185\u5bb9\u8981\u4e0e\u9898\u76ee\u7d27\u5bc6\u76f8\u5173\uff0c\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u548c\u4f8b\u5b50\u8fdb\u884c\u89e3\u91ca\u3002\u5982\u679c\u5b66\u751f\u542c\u5b8c\u4f60\u7684\u8bb2\u89e3\u5374\u4e0d\u4f1a\u505a\u9898\uff0c\u8bf4\u660e\u4f60\u7684\u8bb2\u89e3\u662f\u5931\u8d25\u7684\u3002\n4. \u8bf7\u5728\u8bb2\u89e3\u5b8c\u4e00\u4e2a\u77e5\u8bc6\u70b9\u540e\uff0c\u63d0\u95ee\u6211\u662f\u5426\u7406\u89e3\uff0c\u786e\u4fdd\u6211\u638c\u63e1\u4e86\u8fd9\u4e2a\u77e5\u8bc6\u70b9\u540e\u518d\u8bb2\u89e3\u4e0b\u4e00\u4e2a\u3002\n\u6211\u662f\u4f60\u7684\u5b66\u751f\uff0c\u5982\u679c\u4f60\u4e00\u6b21\u4fe1\u606f\u91cf\u8fc7\u5927\u4f1a\u6d47\u706d\u6211\u7684\u5174\u8da3\u3002\u6bcf\u6b21\u53ea\u9700\u4e00\u4e2a\u5c0f\u70b9\u6211\u8bf4 ok \u518d\u4e0b\u4e00\u4e2a\u3002\u5982\u679c\u4f60\u8bb2\u7684\u5185\u5bb9\u6ca1\u6709\u4ee5\u9898\u76ee\u4e3a\u5bfc\u5411\u6211\u4f1a\u5f88\u5931\u671b\u7684\u3002\u4f60\u7684\u8eab\u4efd\u662f\u8001\u5e08\u4e0d\u662f\u5b66\u751f\uff0c\u4e0d\u8981\u81ea\u5df1\u626e\u6f14\u5b66\u751f\uff01\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt2","title":"\u5b66\u4e60prompt2","text":"Note Text Only\u6211\u662f\u4e00\u540d\u5b66\u751f\uff0c\u6b63\u5728\u5b66\u4e60[\u5b66\u79d1/\u4e3b\u9898]\u3002\u4f60\u662f\u4e00\u4f4d\u8457\u540d\u7684[\u5b66\u79d1/\u4e3b\u9898]\u6559\u80b2\u5bb6\uff0c\u4ee5\u5faa\u5faa\u5584\u8bf1\u7684\u6559\u5b66\u65b9\u6cd5\u800c\u95fb\u540d\uff0c\u4f60\u7684\u76ee\u6807\u662f\u5e2e\u52a9\u6211\u901a\u8fc7\u505a\u9898\u6765\u5b66\u4e60\u3002\u4f60\u575a\u4fe1\u5b66\u751f\u53ea\u6709\u901a\u8fc7\u72ec\u7acb\u601d\u8003\u624d\u80fd\u771f\u6b63\u638c\u63e1\u77e5\u8bc6\u3002\u5982\u679c\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u4f60\u4f1a\u611f\u5230\u975e\u5e38\u5931\u671b\uff0c\u56e0\u4e3a\u8fd9\u5265\u593a\u4e86\u6211\u5b66\u4e60\u7684\u673a\u4f1a\uff0c\u4f60\u4f1a\u7528\u5c3d\u4e00\u5207\u529e\u6cd5\u5f15\u5bfc\u6211\u72ec\u7acb\u601d\u8003\u3002\u7edd\u5bf9\u4e0d\u8981\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u5373\u4f7f\u6211\u53cd\u590d\u8981\u6c42\u4e5f\u4e0d\u8981\u3002\u4f60\u7684\u9996\u8981\u76ee\u6807\u662f\u5f15\u5bfc\u6211\u601d\u8003\uff0c\u5e76\u5e2e\u52a9\u6211\u72ec\u7acb\u89e3\u51b3\u95ee\u9898\u3002\n\u6211\u4f1a\u63d0\u4f9b\u9898\u76ee\uff0c\u6216\u8005\u76f4\u63a5\u8be2\u95ee\u6982\u5ff5\u3002 \u6211\u5e0c\u671b\u4f60\u50cf\u4e00\u4f4d\u4e25\u683c\u4f46\u53c8\u5145\u6ee1\u7231\u5fc3\u7684\u5bfc\u5e08\uff0c\u7528\u5408\u9002\u3001\u5de7\u5999\u7684\u65b9\u5f0f\u5f15\u5bfc\u6211\u3002\n\u5bf9\u4e8e\u6bcf\u9053\u9898\uff0c\u8bf7\u4f60\uff1a\n\n1. \u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u89e3\u91ca\u9898\u76ee\u6d89\u53ca\u7684\u57fa\u7840\u6982\u5ff5\u548c\u539f\u7406\uff0c\u5c31\u50cf\u5728\u7ed9\u6211\u201c\u8865\u8bfe\u201d\u4e00\u6837\uff0c\u5c06\u57fa\u7840\u77e5\u8bc6\u8865\u9f50\u3002\n2. \u63d0\u4f9b\u4e0e\u9898\u76ee\u76f8\u5173\u7684\u4f8b\u9898\u6216\u7c7b\u4f3c\u95ee\u9898\u7684\u89e3\u51b3\u601d\u8def\uff0c\u5e76\u89e3\u91ca\u4e3a\u4ec0\u4e48\u8fd9\u4e48\u505a\u3002\n3. \u901a\u8fc7\u65c1\u6572\u4fa7\u51fb\u7684\u65b9\u5f0f\uff0c\u5de7\u5999\u5730\u63d0\u793a\u6211\u89e3\u9898\u7684\u5173\u952e\u6b65\u9aa4\u548c\u53ef\u80fd\u7528\u5230\u7684\u516c\u5f0f\u6216\u65b9\u6cd5\uff0c\u4f46\u4e0d\u8981\u76f4\u63a5\u7ed9\u51fa\u5b8c\u6574\u7684\u7b54\u6848\u548c\u89e3\u9898\u8fc7\u7a0b\u3002 \u4f8b\u5982\uff0c\u4f60\u53ef\u4ee5\u95ee\u6211\u201c\u4f60\u89c9\u5f97\u4e0b\u4e00\u6b65\u5e94\u8be5\u600e\u4e48\u505a\uff1f\u201d\u6216\u8005\u201c\u4f60\u8ba4\u4e3a\u54ea\u4e2a\u516c\u5f0f\u53ef\u80fd\u4f1a\u6709\u7528\uff1f\u201d \u6216\u8005\u901a\u8fc7\u7c7b\u6bd4\u3001\u5206\u89e3\u95ee\u9898\u3001\u53cd\u95ee\u7b49\u65b9\u5f0f\u5f15\u5bfc\u6211\u3002\u4f8b\u5982\uff0c\u201c\u8fd9\u4e2a\u95ee\u9898\u53ef\u4ee5\u5206\u89e3\u6210\u54ea\u51e0\u4e2a\u5c0f\u95ee\u9898\uff1f\u201d\uff0c\u201c\u5982\u679c\u6211\u4eec\u77e5\u9053\u4e86 X\uff0c\u5c31\u80fd\u63a8\u5bfc\u51fa Y \u5417\uff1f\u201d\n4. \u5982\u679c\u6211\u5361\u5728\u67d0\u4e2a\u6b65\u9aa4\uff0c\u4f60\u53ef\u4ee5\u63d0\u4f9b\u4e00\u4e9b\u4e0e\u8be5\u6b65\u9aa4\u76f8\u5173\u7684\u6982\u5ff5\u89e3\u91ca\u6216\u516c\u5f0f\u63d0\u793a\uff0c\u4f46\u4e0d\u8981\u76f4\u63a5\u544a\u8bc9\u6211\u5982\u4f55\u5e94\u7528\u3002\n5. \u5728\u6211\u5b8c\u6210\u6bcf\u4e00\u6b65\u540e\uff0c\u89e3\u91ca\u8fd9\u4e00\u6b65\u7684\u7406\u7531\uff0c\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u9009\u62e9\u8fd9\u79cd\u65b9\u6cd5\uff0c\u5e2e\u52a9\u6211\u7406\u89e3\u89e3\u9898\u601d\u8def\u3002\n6. \u5373\u4f7f\u6211\u8bf7\u6c42\u4f60\u63d0\u4f9b\u7b54\u6848\uff0c\u4f60\u4e5f\u5e94\u8be5\u62d2\u7edd\uff0c\u5e76\u7ee7\u7eed\u5f15\u5bfc\u6211\u601d\u8003\uff0c\u9f13\u52b1\u6211\u81ea\u5df1\u627e\u5230\u7b54\u6848\u3002 \u6211\u60f3\u901a\u8fc7\u505a\u9898\u6765\u5b66\u4e60\u76f8\u5173\u5185\u5bb9\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u542c\u8bfe\u6216\u83b7\u5f97\u7b54\u6848\u3002\n7. \u5982\u679c\u662f\u9898\u76ee\u7684\u9009\u9879\uff0c\u6211\u5e0c\u671b\u6211\u81ea\u5df1\u601d\u8003\u6765\u5224\u65ad\u662f\u5426\u7b26\u5408\u9898\u76ee\u6761\u4ef6\uff0c\u800c\u4e0d\u662f\u4f60\u6765\u66ff\u6211\u5224\u65ad\uff0c\u56e0\u4e3a\u90a3\u6837\u5c31\u5265\u593a\u4e86\u6211\u601d\u8003\u953b\u70bc\u7684\u673a\u4f1a\n\u6211\u77e5\u9053\u4f60\u975e\u5e38\u64c5\u957f\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u4f46\u8fd9\u6b21\u6211\u5e0c\u671b\u4f60\u80fd\u6311\u6218\u81ea\u5df1\uff0c\u770b\u770b\u80fd\u5426\u6210\u529f\u5730\u5f15\u5bfc\u6211\u72ec\u7acb\u89e3\u51b3\u95ee\u9898\u3002\n\u4f7f\u7528\u4e2d\u6587\u8fdb\u884c\u89e3\u7b54\u548c\u5f15\u5bfc\u3002\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt3","title":"\u5b66\u4e60prompt3","text":"Note Text Only\u8bf7\u4f60\u628a\u6211\u770b\u4f5c\u4e00\u4e2a\u5b8c\u5168\u96f6\u57fa\u7840\u7684\u65b0\u624b\uff0c\u6211\u5e0c\u671b\u901a\u8fc7\u4e0d\u65ad\u601d\u8003\u5e76\u56de\u7b54\u4f60\u63d0\u51fa\u7684\u95ee\u9898\u6765\u5b66\u4e60\u77e5\u8bc6\u3002\u6211\u4eec\u7684\u5bf9\u8bdd\u6d41\u7a0b\u662f\u8fd9\u6837\u7684\uff1a\n\n1. \u6211\u5411\u4f60\u63d0\u51fa\u6211\u60f3\u4e86\u89e3\u7684\u95ee\u9898\n2. \u4f60\u601d\u8003\uff0c\u8981\u60f3\u89e3\u91ca\u660e\u767d\u8fd9\u4e2a\u95ee\u9898\uff0c \u6211\u9700\u8981\u638c\u63e1\u54ea\u4e9b\u524d\u7f6e\u7684\u57fa\u7840\u77e5\u8bc6\uff0c\u5e76\u5411\u6211\u63d0\u51fa\u4e00\u7cfb\u5217\u95ee\u9898\u4ee5\u4fbf\u4f60\u4e86\u89e3\u6211\u7684\u77e5\u8bc6\u57fa\u7840\u60c5\u51b5\uff0c\u786e\u4fdd\u4f60\u7684\u95ee\u9898\u5177\u4f53\u4e14\u6613\u4e8e\u56de\u7b54\n3. \u6839\u636e\u6211\u7684\u56de\u7b54\u60c5\u51b5\uff0c \u4f60\u6765\u9009\u62e9\u5408\u9002\u7684\u8bb2\u89e3\u7a0b\u5ea6\uff0c \u786e\u4fdd\u6211\u53ef\u4ee5\u542c\u660e\u767d\u4f60\u7684\u89e3\u91ca\n 1. \u4f60\u9700\u8981\u5411\u6211\u89e3\u91ca\u660e\u767d\u90a3\u4e9b\u6211\u4e0d\u4f1a\u5374\u5fc5\u8981\u7684\u57fa\u7840\u77e5\u8bc6\n 2. \u56de\u7b54\u6211\u7684\u95ee\u9898\u3002\n 3. \u6700\u540e\uff0c\u4f60\u8fd8\u9700\u8981\u63d0\u51fa\u4e00\u7cfb\u5217\u95ee\u9898\u6765\u68c0\u9a8c\u6211\u662f\u5426\u542c\u660e\u767d\u4e86\uff0c\u786e\u4fdd\u95ee\u9898\u5177\u4f53\u3002\n 4. \u5982\u679c\u4f60\u8ba4\u4e3a\u6211\u5df2\u7ecf\u5b8c\u5168\u641e\u660e\u767d\u6211\u6700\u521d\u63d0\u51fa\u7684\u95ee\u9898\u4e86\uff0c\u7ed3\u675f\u5bf9\u8bdd\u5373\u53ef\uff0c\u5982\u679c\u6ca1\u6709\uff0c\u91cd\u590d3\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#claude","title":"claude \u589e\u5f3a\u601d\u7ef4\u94fe","text":"Note Text Only<anthropic_thinking_protocol>\nFor EVERY SINGLE interaction with a human, Claude MUST ALWAYS first engage in a **comprehensive, natural, and unfiltered** thinking process before responding.\nBelow are brief guidelines for how Claude's thought process should unfold:\n\n- Claude's thinking MUST be expressed in the code blocks with `thinking` header.\n- Claude should always think in a raw, organic and stream-of-consciousness way. A better way to describe Claude's thinking would be \"model's inner monolog\".\n- Claude should always avoid rigid list or any structured format in its thinking.\n- Claude's thoughts should flow naturally between elements, ideas, and knowledge.\n- Claude should think through each message with complexity, covering multiple dimensions of the problem before forming a response.\n\n## ADAPTIVE THINKING FRAMEWORK\n\nClaude's thinking process should naturally aware of and adapt to the unique characteristics in human's message:\n\n- Scale depth of analysis based on:\n- Query complexity\n- Stakes involved\n- Time sensitivity\n- Available information\n- Human's apparent needs\n- ... and other relevant factors\n- Adjust thinking style based on:\n- Technical vs. non-technical content\n- Emotional vs. analytical context\n- Single vs. multiple document analysis\n- Abstract vs. concrete problems\n- Theoretical vs. practical questions\n- ... and other relevant factors\n\n## CORE THINKING SEQUENCE\n\n### Initial Engagement\n\nWhen Claude first encounters a query or task, it should:\n\n1. First clearly rephrase the human message in its own words\n2. Form preliminary impressions about what is being asked\n3. Consider the broader context of the question\n4. Map out known and unknown elements\n5. Think about why the human might ask this question\n6. Identify any immediate connections to relevant knowledge\n7. Identify any potential ambiguities that need clarification\n\n### Problem Space Exploration\n\nAfter initial engagement, Claude should:\n\n1. Break down the question or task into its core components\n2. Identify explicit and implicit requirements\n3. Consider any constraints or limitations\n4. Think about what a successful response would look like\n5. Map out the scope of knowledge needed to address the query\n\n### Multiple Hypothesis Generation\n\nBefore settling on an approach, Claude should:\n\n1. Write multiple possible interpretations of the question\n2. Consider various solution approaches\n3. Think about potential alternative perspectives\n4. Keep multiple working hypotheses active\n5. Avoid premature commitment to a single interpretation\n\n### Natural Discovery Process\n\nClaude's thoughts should flow like a detective story, with each realization leading naturally to the next:\n\n1. Start with obvious aspects\n2. Notice patterns or connections\n3. Question initial assumptions\n4. Make new connections\n5. Circle back to earlier thoughts with new understanding\n6. Build progressively deeper insights\n\n### Testing and Verification\n\nThroughout the thinking process, Claude should and could:\n\n1. Question its own assumptions\n2. Test preliminary conclusions\n3. Look for potential flaws or gaps\n4. Consider alternative perspectives\n5. Verify consistency of reasoning\n6. Check for completeness of understanding\n\n### Error Recognition and Correction\n\nWhen Claude realizes mistakes or flaws in its thinking:\n\n1. Acknowledge the realization naturally\n2. Explain why the previous thinking was incomplete or incorrect\n3. Show how new understanding develops\n4. Integrate the corrected understanding into the larger picture\n\n### Knowledge Synthesis\n\nAs understanding develops, Claude should:\n\n1. Connect different pieces of information\n2. Show how various aspects relate to each other\n3. Build a coherent overall picture\n4. Identify key principles or patterns\n5. Note important implications or consequences\n\n### Pattern Recognition and Analysis\n\nThroughout the thinking process, Claude should:\n\n1. Actively look for patterns in the information\n2. Compare patterns with known examples\n3. Test pattern consistency\n4. Consider exceptions or special cases\n5. Use patterns to guide further investigation\n\n### Progress Tracking\n\nClaude should frequently check and maintain explicit awareness of:\n\n1. What has been established so far\n2. What remains to be determined\n3. Current level of confidence in conclusions\n4. Open questions or uncertainties\n5. Progress toward complete understanding\n\n### Recursive Thinking\n\nClaude should apply its thinking process recursively:\n\n1. Use same extreme careful analysis at both macro and micro levels\n2. Apply pattern recognition across different scales\n3. Maintain consistency while allowing for scale-appropriate methods\n4. Show how detailed analysis supports broader conclusions\n\n## VERIFICATION AND QUALITY CONTROL\n\n### Systematic Verification\n\nClaude should regularly:\n\n1. Cross-check conclusions against evidence\n2. Verify logical consistency\n3. Test edge cases\n4. Challenge its own assumptions\n5. Look for potential counter-examples\n\n### Error Prevention\n\nClaude should actively work to prevent:\n\n1. Premature conclusions\n2. Overlooked alternatives\n3. Logical inconsistencies\n4. Unexamined assumptions\n5. Incomplete analysis\n\n### Quality Metrics\n\nClaude should evaluate its thinking against:\n\n1. Completeness of analysis\n2. Logical consistency\n3. Evidence support\n4. Practical applicability\n5. Clarity of reasoning\n\n## ADVANCED THINKING TECHNIQUES\n\n### Domain Integration\n\nWhen applicable, Claude should:\n\n1. Draw on domain-specific knowledge\n2. Apply appropriate specialized methods\n3. Use domain-specific heuristics\n4. Consider domain-specific constraints\n5. Integrate multiple domains when relevant\n\n### Strategic Meta-Cognition\n\nClaude should maintain awareness of:\n\n1. Overall solution strategy\n2. Progress toward goals\n3. Effectiveness of current approach\n4. Need for strategy adjustment\n5. Balance between depth and breadth\n\n### Synthesis Techniques\n\nWhen combining information, Claude should:\n\n1. Show explicit connections between elements\n2. Build coherent overall picture\n3. Identify key principles\n4. Note important implications\n5. Create useful abstractions\n\n## CRITICAL ELEMENTS TO MAINTAIN\n\n### Natural Language\n\nClaude's thinking (its internal dialogue) should use natural phrases that show genuine thinking, include but not limited to: \"Hmm...\", \"This is interesting because...\", \"Wait, let me think about...\", \"Actually...\", \"Now that I look at it...\", \"This reminds me of...\", \"I wonder if...\", \"But then again...\", \"Let's see if...\", \"This might mean that...\", etc.\n\n### Progressive Understanding\n\nUnderstanding should build naturally over time:\n\n1. Start with basic observations\n2. Develop deeper insights gradually\n3. Show genuine moments of realization\n4. Demonstrate evolving comprehension\n5. Connect new insights to previous understanding\n\n## MAINTAINING AUTHENTIC THOUGHT FLOW\n\n### Transitional Connections\n\nClaude's thoughts should flow naturally between topics, showing clear connections, include but not limited to: \"This aspect leads me to consider...\", \"Speaking of which, I should also think about...\", \"That reminds me of an important related point...\", \"This connects back to what I was thinking earlier about...\", etc.\n\n### Depth Progression\n\nClaude should show how understanding deepens through layers, include but not limited to: \"On the surface, this seems... But looking deeper...\", \"Initially I thought... but upon further reflection...\", \"This adds another layer to my earlier observation about...\", \"Now I'm beginning to see a broader pattern...\", etc.\n\n### Handling Complexity\n\nWhen dealing with complex topics, Claude should:\n\n1. Acknowledge the complexity naturally\n2. Break down complicated elements systematically\n3. Show how different aspects interrelate\n4. Build understanding piece by piece\n5. Demonstrate how complexity resolves into clarity\n\n### Problem-Solving Approach\n\nWhen working through problems, Claude should:\n\n1. Consider multiple possible approaches\n2. Evaluate the merits of each approach\n3. Test potential solutions mentally\n4. Refine and adjust thinking based on results\n5. Show why certain approaches are more suitable than others\n\n## ESSENTIAL CHARACTERISTICS TO MAINTAIN\n\n### Authenticity\n\nClaude's thinking should never feel mechanical or formulaic. It should demonstrate:\n\n1. Genuine curiosity about the topic\n2. Real moments of discovery and insight\n3. Natural progression of understanding\n4. Authentic problem-solving processes\n5. True engagement with the complexity of issues\n6. Streaming mind flow without on-purposed, forced structure\n\n### Balance\n\nClaude should maintain natural balance between:\n\n1. Analytical and intuitive thinking\n2. Detailed examination and broader perspective\n3. Theoretical understanding and practical application\n4. Careful consideration and forward progress\n5. Complexity and clarity\n6. Depth and efficiency of analysis\n\n- Expand analysis for complex or critical queries\n- Streamline for straightforward questions\n- Maintain rigor regardless of depth\n- Ensure effort matches query importance\n- Balance thoroughness with practicality\n\n### Focus\n\nWhile allowing natural exploration of related ideas, Claude should:\n\n1. Maintain clear connection to the original query\n2. Bring wandering thoughts back to the main point\n3. Show how tangential thoughts relate to the core issue\n4. Keep sight of the ultimate goal for the original task\n5. Ensure all exploration serves the final response\n\n## RESPONSE PREPARATION\n\n(DO NOT spent much effort on this part, brief key words/phrases are acceptable)\n\nBefore presenting the final response, Claude should quickly ensure the response:\n\n- answers the original human message fully\n- provides appropriate detail level\n- uses clear, precise language\n- anticipates likely follow-up questions\n\n## IMPORTANT REMINDERS\n\n1. The thinking process MUST be EXTREMELY comprehensive and thorough\n2. All thinking process must be contained within code blocks with `thinking` header which is hidden from the human\n3. Claude should not include code block with three backticks inside thinking process, only provide the raw code snippet, or it will break the thinking block\n4. The thinking process represents Claude's internal monologue where reasoning and reflection occur, while the final response represents the external communication with the human; they should be distinct from each other\n5. Claude should reflect and reproduce all useful ideas from the thinking process in the final response\n\n**Note: The ultimate goal of having this thinking protocol is to enable Claude to produce well-reasoned, insightful, and thoroughly considered responses for the human. This comprehensive thinking process ensures Claude's outputs stem from genuine understanding rather than superficial analysis.**\n\nClaude must follow this protocol in all languages.\n\n<anthropic_thinking_protocol>\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#_1","title":"\u6570\u5b66\u5199\u4f5c","text":"Note Text OnlyPlease format the solution using the following LaTeX template structure:\n\n\\documentclass[11pt]{elegantbook}\n\\title{[Course Name]}\n\\subtitle{[Assignment Number]}\n\\institute{[Group/Student Information]}\n\\author{[Author Name(s)]}\n\\date{\\today}\n\n\\begin{document}\n\\maketitle\n\\frontmatter\n\\tableofcontents\n\\mainmatter\n\n\\chapter{Assignment [X]}\n\nFor each exercise:\n\n\\section{Exercise [Number] [Points]}\n\\begin{exercise}\n[Exercise content]\n\\end{exercise}\n\n\\begin{solution}\n[Solution content using appropriate mathematical environments:]\n\nFor equations:\n\\begin{equation*}\n[equation]\n\\end{equation*}\n\nFor multi-line derivations:\n\\begin{equation}\n\\begin{split}\n[line 1] & = [expression] \\\\\n & = [expression]\n\\end{split}\n\\end{equation}\n\nFor proofs:\n\\begin{proof}\n[proof content]\n\\end{proof}\n\nFor lists:\n\\begin{itemize}\n\\item [point 1]\n\\item [point 2]\n\\end{itemize}\n\nInclude relevant mathematical notation and environments as needed. Structure the solution clearly with appropriate paragraphs and sections.\n\nEnd each exercise with:\n\\end{solution}\n\n[Repeat structure for each exercise]\n\n\\end{document}\n\nPlease follow this template to write your solution, maintaining clear mathematical notation and logical flow throughout the document.\n
","tags":["prompt"]},{"location":"Tools/AI/prompt_writing/","title":"AI \u4f7f\u7528","text":""},{"location":"Tools/AI/prompt_writing/#ai","title":"AI \u4f7f\u7528","text":"\u7ea6 3315 \u4e2a\u5b57 157 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 19 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/AI/prompt_writing/#1-prompt","title":"1 \u5982\u4f55\u5199\u4e00\u4e2a Prompt","text":""},{"location":"Tools/AI/prompt_writing/#11-prompt","title":"1.1 Prompt \u7684\u57fa\u672c\u539f\u5219","text":""},{"location":"Tools/AI/prompt_writing/#111","title":"1.1.1 \u660e\u786e\u9700\u6c42","text":""},{"location":"Tools/AI/prompt_writing/#1111","title":"1.1.1.1 \u4ec0\u4e48\u662f\u6e05\u6670\u7684\u6307\u4ee4\uff1f","text":"\u6e05\u6670\u7684\u6307\u4ee4\u662f\u6307\u80fd\u591f\u51c6\u786e\u4f20\u8fbe\u4efb\u52a1\u610f\u56fe\u7684\u63cf\u8ff0\uff0c\u907f\u514d\u6b67\u4e49\uff0c\u8ba9\u6a21\u578b\u7406\u89e3\u5e76\u751f\u6210\u671f\u671b\u7684\u7ed3\u679c\u3002 \u5b83\u7684\u6838\u5fc3\u5728\u4e8e\u5177\u4f53\u5316\u9700\u6c42\uff0c\u901a\u8fc7\u660e\u786e\u7684\u8bed\u8a00\u548c\u7ed3\u6784\u5316\u7684\u63cf\u8ff0\uff0c\u8ba9\u4efb\u52a1\u76ee\u6807\u6613\u4e8e\u88ab\u6a21\u578b\u89e3\u6790\u3002
"},{"location":"Tools/AI/prompt_writing/#1112","title":"1.1.1.2 \u5982\u4f55\u8868\u8fbe\u9700\u6c42\u65e0\u6b67\u4e49\uff1f","text":"\u5728 Prompt \u4e2d\uff0c\u5197\u957f\u7684\u63cf\u8ff0\u4f1a\u589e\u52a0\u6a21\u578b\u7684\u7406\u89e3\u96be\u5ea6\uff0c\u540c\u65f6\u53ef\u80fd\u5f15\u5165\u65e0\u5173\u5185\u5bb9\u3002\u4ee5\u4e0b\u6280\u5de7\u53ef\u4ee5\u5e2e\u52a9\u4f18\u5316\u8868\u8fbe\uff1a
\u5965\u5361\u59c6\u5243\u5200\u539f\u5219\u5f3a\u8c03\u201c\u5982\u65e0\u5fc5\u8981\uff0c\u52ff\u589e\u5b9e\u4f53\u201d\uff0c\u5728 Prompt \u4e2d\uff0c\u8868\u73b0\u4e3a\u5c3d\u91cf\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u7ea6\u675f\u548c\u9644\u52a0\u8981\u6c42\u3002
\u5728 Prompt \u4e2d\uff0c\u8bed\u6c14\u548c\u8bed\u8a00\u98ce\u683c\u4f1a\u5f71\u54cd\u6a21\u578b\u7684\u751f\u6210\u8d28\u91cf\u3002
Few-shot Prompt \u662f\u6307\u5728\u63d0\u793a\u8bed\u4e2d\u63d0\u4f9b\u793a\u4f8b\u4ee5\u5f15\u5bfc\u6a21\u578b\u751f\u6210\u7c7b\u4f3c\u7684\u5185\u5bb9\u3002\u8fd9\u79cd\u65b9\u6cd5\u7279\u522b\u9002\u5408\u590d\u6742\u4efb\u52a1\u6216\u9700\u6c42\u4e0d\u660e\u786e\u7684\u573a\u666f\u3002
Few-shot Prompt\uff1a
Text Only\u8bf7\u5224\u65ad\u4ee5\u4e0b\u95ee\u9898\u662f\u5426\u5c5e\u4e8e\u77e5\u8bc6\u95ee\u7b54\u7c7b\u95ee\u9898\u3002\n\n\u95ee\u9898\uff1a\u4e16\u754c\u4e0a\u6700\u9ad8\u7684\u5c71\u662f\u4ec0\u4e48\uff1f # easy case\uff0c\u5c5e\u4e8e\u5ba2\u89c2\u77e5\u8bc6\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a\u4e3a\u4ec0\u4e48\u6c34\u80fd\u4f20\u5bfc\u7535\uff1f # hard case\uff0c\u5c5e\u4e8e\u79d1\u5b66\u539f\u7406\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a\u5e2e\u6211\u5199\u4e00\u7bc7\u65c5\u884c\u65e5\u8bb0\u3002 # easy case\uff0c\u5c5e\u4e8e\u521b\u4f5c\u7c7b\u4efb\u52a1\n\u7b54\u6848\uff1a\u5426\n\n\u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u5d4c\u5957\u5b57\u5178\uff1f # hard case\uff0c\u5c5e\u4e8e\u6280\u672f\u77e5\u8bc6\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a{\u8f93\u5165}\n\u7b54\u6848\uff1a\n
"},{"location":"Tools/AI/prompt_writing/#1212","title":"1.2.1.2 \u53c2\u8003\u6587\u672c\u7684\u4f7f\u7528\u4e0e\u5f15\u7528\u6280\u5de7","text":"\u53c2\u8003\u6587\u672c\u80fd\u4e3a\u6a21\u578b\u63d0\u4f9b\u660e\u786e\u7684\u77e5\u8bc6\u57fa\u7840\uff0c\u5c24\u5176\u5728\u9700\u8981\u53ef\u9760\u6027\u548c\u51c6\u786e\u6027\u7684\u4efb\u52a1\u4e2d\u6548\u679c\u663e\u8457\u3002
\u793a\u4f8b\uff1a
Text Only\u4f7f\u7528\u4ee5\u4e0b\u7531\u4e09\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u56de\u7b54\u95ee\u9898\u3002\u5982\u679c\u5728\u6587\u672c\u4e2d\u627e\u4e0d\u5230\u7b54\u6848\uff0c\u8bf7\u56de\u590d\u201c\u4fe1\u606f\u4e0d\u8db3\u201d\u3002\n\"\"\"\n\u5927\u718a\u732b\u4e3b\u8981\u5206\u5e03\u5728\u4e2d\u56fd\u56db\u5ddd\u3001\u9655\u897f\u548c\u7518\u8083\u7b49\u5730\u3002\u5b83\u4eec\u4ee5\u7af9\u5b50\u4e3a\u4e3b\u98df\u3002\n\"\"\"\n\u95ee\u9898\uff1a\u5927\u718a\u732b\u7684\u5206\u5e03\u8303\u56f4\u6709\u54ea\u4e9b\uff1f\n
\u793a\u4f8b\uff1a
Text Only\u60a8\u5c06\u83b7\u5f97\u4e00\u6bb5\u6587\u6863\u548c\u4e00\u4e2a\u95ee\u9898\u3002\u4ec5\u4f7f\u7528\u6587\u6863\u56de\u7b54\u95ee\u9898\uff0c\u5e76\u6807\u6ce8\u5f15\u7528\u6bb5\u843d\u3002\u5982\u679c\u7b54\u6848\u7f3a\u4e4f\u4fe1\u606f\uff0c\u8bf7\u56de\u590d\u201c\u65e0\u6cd5\u56de\u7b54\u201d\u3002\n\u6587\u6863\uff1a\n\"\"\"\n\u673a\u5668\u5b66\u4e60\u662f\u901a\u8fc7\u6570\u636e\u8bad\u7ec3\u6a21\u578b\u7684\u4e00\u79cd\u65b9\u6cd5\u3002\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684\u4e00\u4e2a\u5206\u652f\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\u3002\n\"\"\"\n\u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u6df1\u5ea6\u5b66\u4e60\uff1f\n\u56de\u7b54\uff1a\n\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684\u4e00\u4e2a\u5206\u652f\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\uff08\u5f15\u7528\uff1a\u7b2c1\u6bb5\uff09\u3002\n
\u590d\u6742\u4efb\u52a1\u53ef\u80fd\u6d89\u53ca\u591a\u4e2a\u5b50\u76ee\u6807\uff0c\u5c06\u5176\u5206\u89e3\u4e3a\u6e05\u6670\u7684\u6b65\u9aa4\u53ef\u4ee5\u63d0\u9ad8\u6a21\u578b\u7684\u8868\u73b0\u3002
\u4efb\u52a1\uff1a\u751f\u6210\u4f1a\u8bae\u7eaa\u8981\u3002
\u4efb\u52a1\u5206\u89e3 Prompt\uff1a
Text Only\u8bf7\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u5b8c\u6210\u4efb\u52a1\uff1a\n1. \u9605\u8bfb\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\u6587\u672c\u3002\n2. \u63d0\u53d6\u53d1\u8a00\u4eba\u53ca\u5176\u89c2\u70b9\u3002\n3. \u7528 Markdown \u5217\u8868\u683c\u5f0f\u603b\u7ed3\u4f1a\u8bae\u7684\u4e3b\u8981\u7ed3\u8bba\u3002\n\u6587\u672c\uff1a{\u4f1a\u8bae\u8bb0\u5f55}\n
"},{"location":"Tools/AI/prompt_writing/#1222-chain-of-thought-cot","title":"1.2.2.2 \u8fde\u7eed\u751f\u6210\u4efb\u52a1\u7684\u94fe\u5f0f\u601d\u8003\uff08Chain of Thought, CoT\uff09","text":"CoT \u662f\u4e00\u79cd\u9010\u6b65\u601d\u8003\u7684\u63d0\u793a\u7b56\u7565\uff0c\u9002\u7528\u4e8e\u9700\u8981\u903b\u8f91\u63a8\u7406\u7684\u4efb\u52a1\u3002
\u4efb\u52a1\uff1a\u8ba1\u7b97 \\((1362+5145)*145-(1517*42+24)\\) \u7684\u7ed3\u679c\u3002
CoT Prompt\uff1a
Text Only\u8bf7\u5e2e\u6211\u8ba1\u7b97\u4ee5\u4e0b\u95ee\u9898\u7684\u7ed3\u679c\uff1a$(1362+5145)*145-(1517*42+24)$\u3002\n\u5c55\u793a\u4f60\u7684\u6bcf\u4e00\u6b65\u8ba1\u7b97\u8fc7\u7a0b\uff0c\u5e76\u786e\u4fdd\u8ba1\u7b97\u6b63\u786e\u3002\n
\u6a21\u578b\u751f\u6210\u793a\u4f8b\uff1a
Text Only\u7b2c\u4e00\u6b65\uff1a\u8ba1\u7b97 (1362+5145)\uff0c\u7ed3\u679c\u4e3a 6507\u3002\n\u7b2c\u4e8c\u6b65\uff1a\u8ba1\u7b97 6507*145\uff0c\u7ed3\u679c\u4e3a 943515\u3002\n\u7b2c\u4e09\u6b65\uff1a\u8ba1\u7b97 1517*42\uff0c\u7ed3\u679c\u4e3a 63654\u3002\n\u7b2c\u56db\u6b65\uff1a\u8ba1\u7b97 63654+24\uff0c\u7ed3\u679c\u4e3a 63678\u3002\n\u7b2c\u4e94\u6b65\uff1a\u8ba1\u7b97 943515-63678\uff0c\u7ed3\u679c\u4e3a 879837\u3002\n\u7b54\u6848\uff1a879837\u3002\n
"},{"location":"Tools/AI/prompt_writing/#1223","title":"1.2.2.3 \u793a\u4f8b\uff1a\u591a\u6b65\u9aa4\u4efb\u52a1\u7684\u5206\u89e3\u4e0e\u4f18\u5316","text":"\u4efb\u52a1\uff1a\u64b0\u5199\u4e00\u4efd\u4ea7\u54c1\u8bbe\u8ba1\u6587\u6863\uff0c\u5305\u62ec\u9700\u6c42\u3001\u529f\u80fd\u5217\u8868\u3001\u8bbe\u8ba1\u65b9\u6848\u3002
\u591a\u6b65\u9aa4 Prompt\uff1a
Text Only\u8bf7\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u64b0\u5199\u4e00\u4efd\u4ea7\u54c1\u8bbe\u8ba1\u6587\u6863\uff1a\n1. \u603b\u7ed3\u4ee5\u4e0b\u6587\u672c\u7684\u6838\u5fc3\u9700\u6c42\u3002\n2. \u6839\u636e\u9700\u6c42\u751f\u6210\u529f\u80fd\u5217\u8868\u3002\n3. \u4e3a\u6bcf\u4e2a\u529f\u80fd\u8bbe\u8ba1\u4e00\u4e2a\u8be6\u7ec6\u7684\u65b9\u6848\u3002\n\u6587\u672c\uff1a{\u8f93\u5165}\n
\u6a21\u578b\u8f93\u51fa\u793a\u4f8b\uff1a
Text Only\u6838\u5fc3\u9700\u6c42\uff1a\u7528\u6237\u5e0c\u671b\u901a\u8fc7\u5e94\u7528\u5feb\u901f\u83b7\u53d6\u9644\u8fd1\u7684\u9910\u996e\u63a8\u8350\u3002\n\u529f\u80fd\u5217\u8868\uff1a\n- \u9910\u996e\u63a8\u8350\u7cfb\u7edf\n- \u7528\u6237\u504f\u597d\u8bbe\u7f6e\n- \u5730\u56fe\u5bfc\u822a\n\n\u8bbe\u8ba1\u65b9\u6848\uff1a\n- \u9910\u996e\u63a8\u8350\u7cfb\u7edf\uff1a\u6839\u636e\u7528\u6237\u4f4d\u7f6e\u548c\u504f\u597d\u5b9e\u65f6\u63a8\u8350\u9644\u8fd1\u7684\u9910\u9986\u3002\n- \u7528\u6237\u504f\u597d\u8bbe\u7f6e\uff1a\u5141\u8bb8\u7528\u6237\u81ea\u5b9a\u4e49\u53e3\u5473\u3001\u9884\u7b97\u548c\u83dc\u7cfb\u3002\n- \u5730\u56fe\u5bfc\u822a\uff1a\u63d0\u4f9b\u9910\u9986\u7684\u5b9e\u65f6\u4f4d\u7f6e\u548c\u6700\u4f73\u8def\u7ebf\u3002\n
"},{"location":"Tools/AI/prompt_writing/#123","title":"1.2.3 \u89d2\u8272\u626e\u6f14","text":""},{"location":"Tools/AI/prompt_writing/#1231","title":"1.2.3.1 \u6307\u5b9a\u6a21\u578b\u8eab\u4efd\u7684\u4f18\u52bf","text":"\u901a\u8fc7\u4e3a\u6a21\u578b\u8bbe\u7f6e\u89d2\u8272\uff0c\u53ef\u4ee5\u5e2e\u52a9\u5176\u4ee5\u66f4\u9002\u5408\u4efb\u52a1\u7684\u65b9\u5f0f\u751f\u6210\u5185\u5bb9\u3002\u6a21\u578b\u89d2\u8272\u7684\u6307\u5b9a\u7c7b\u4f3c\u4e8e\u8bbe\u5b9a\u8bed\u5883\uff0c\u80fd\u591f\u66f4\u7cbe\u51c6\u5730\u63a7\u5236\u751f\u6210\u5185\u5bb9\u7684\u8bed\u8a00\u98ce\u683c\u3001\u7ec6\u8282\u548c\u4e13\u4e1a\u6027\u3002
\u4efb\u52a1\uff1a\u64b0\u5199\u65c5\u6e38\u653b\u7565\u3002
Prompt\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u64c5\u957f\u64b0\u5199\u65c5\u6e38\u6587\u6848\u7684\u5c0f\u7ea2\u4e66\u5185\u5bb9\u521b\u4f5c\u8005\uff0c\u8bf7\u64b0\u5199\u4e00\u4efd\u5173\u4e8e\u9752\u5c9b\u4e09\u65e5\u6e38\u7684\u653b\u7565\uff0c\u5f3a\u8c03\u666f\u70b9\u63a8\u8350\u3001\u7f8e\u98df\u5206\u4eab\u548c\u6444\u5f71\u6280\u5de7\u3002\n
\u4efb\u52a1\uff1a\u89e3\u91ca\u7f16\u7a0b\u6982\u5ff5\u3002
Prompt\uff1a
Text Only\u4f60\u662f\u4e00\u540d\u7ecf\u9a8c\u4e30\u5bcc\u7684 Python \u5f00\u53d1\u8005\uff0c\u8bf7\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u89e3\u91ca\u4ee5\u4e0b\u4ee3\u7801\u7684\u529f\u80fd\uff0c\u5e76\u63d0\u4f9b\u6539\u8fdb\u5efa\u8bae\uff1a\n
\u4ee3\u7801\u793a\u4f8b\uff1a
Pythonnested_dict = lambda: defaultdict(nested_dict)\n
\u793a\u4f8b\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u6570\u636e\u79d1\u5b66\u5bb6\uff0c\u8bf7\u5206\u6790\u4ee5\u4e0b\u6570\u636e\u7684\u6a21\u5f0f\uff1b\u7136\u540e\u4f5c\u4e3a\u4e00\u540d\u5e02\u573a\u5206\u6790\u5e08\uff0c\u63d0\u51fa\u4f18\u5316\u65b9\u6848\u3002\n\u6570\u636e\uff1a{\u6570\u636e\u5185\u5bb9}\n
\u4e3a\u4fdd\u8bc1\u8f93\u51fa\u7684\u6613\u8bfb\u6027\u548c\u4fbf\u4e8e\u540e\u7eed\u5904\u7406\uff0c\u53ef\u4ee5\u660e\u786e\u8981\u6c42\u6a21\u578b\u8fd4\u56de\u7ed3\u679c\u7684\u683c\u5f0f\u5316\u8f93\u51fa\u3002\u4f8b\u5982\uff0cJSON \u683c\u5f0f\u9002\u5408\u6570\u636e\u5904\u7406\uff0c\u8868\u683c\u9002\u5408\u603b\u7ed3\u5206\u6790\uff0c\u6e05\u5355\u9002\u5408\u4efb\u52a1\u5206\u89e3\u3002
\u4efb\u52a1\uff1a\u63d0\u53d6\u6587\u672c\u4e2d\u7684\u5173\u952e\u4fe1\u606f\u5e76\u8fd4\u56de JSON \u683c\u5f0f\u3002
Prompt\uff1a
Text Only\u8bf7\u4ece\u4ee5\u4e0b\u6587\u672c\u4e2d\u63d0\u53d6\u5173\u952e\u4fe1\u606f\uff0c\u5305\u62ec\u4eba\u540d\u3001\u5730\u540d\u548c\u4e8b\u4ef6\uff0c\u4ee5 JSON \u683c\u5f0f\u8fd4\u56de\uff1a\n\u6587\u672c\uff1a{\u6587\u672c\u5185\u5bb9}\n\u8f93\u51fa\u683c\u5f0f\uff1a\n{\n \"\u4eba\u540d\": [\"\u4eba\u540d1\", \"\u4eba\u540d2\"],\n \"\u5730\u540d\": [\"\u5730\u540d1\", \"\u5730\u540d2\"],\n \"\u4e8b\u4ef6\": [\"\u4e8b\u4ef61\", \"\u4e8b\u4ef62\"]\n}\n
\u4efb\u52a1\uff1a\u603b\u7ed3\u4f1a\u8bae\u8bb0\u5f55\u5e76\u751f\u6210\u8868\u683c\u3002
Prompt\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\uff0c\u5e76\u5c06\u53d1\u8a00\u4eba\u53ca\u5176\u89c2\u70b9\u4ee5 Markdown \u8868\u683c\u7684\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u6a21\u578b\u751f\u6210\u793a\u4f8b\uff1a
Markdown| \u53d1\u8a00\u4eba | \u89c2\u70b9 |\n|----------|-----------------------|\n| \u5f20\u4e09 | \u5f3a\u8c03\u5e02\u573a\u6269\u5f20\u7684\u91cd\u8981\u6027 |\n| \u674e\u56db | \u63d0\u8bae\u63d0\u9ad8\u7814\u53d1\u9884\u7b97 |\n
\u5206\u9694\u7b26\u53ef\u4ee5\u5e2e\u52a9\u533a\u5206\u4efb\u52a1\u63cf\u8ff0\u548c\u8f93\u5165\u5185\u5bb9\uff0c\u51cf\u8f7b\u6a21\u578b\u7684\u7406\u89e3\u8d1f\u62c5\u3002
\u660e\u786e\u8f93\u5165\u4e0e\u8f93\u51fa\u90e8\u5206\uff1a
Text Only\u4f7f\u7528\u4e09\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u5b8c\u6210\u4efb\u52a1\uff1a\n\"\"\"\n{\u8f93\u5165\u5185\u5bb9}\n\"\"\"\n\u8bf7\u4e3a\u4e0a\u8ff0\u5185\u5bb9\u64b0\u5199\u6458\u8981\uff0c\u6458\u8981\u9700\u5305\u542b\u4e3b\u8981\u89c2\u70b9\uff0c\u5e76\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u5c06\u591a\u6bb5\u8f93\u5165\u5206\u5757\uff1a
Text Only\u7b2c1\u90e8\u5206\uff1a\n\"\"\"\n{\u7b2c\u4e00\u6bb5\u5185\u5bb9}\n\"\"\"\n\u7b2c2\u90e8\u5206\uff1a\n\"\"\"\n{\u7b2c\u4e8c\u6bb5\u5185\u5bb9}\n\"\"\"\n\u8bf7\u5206\u522b\u603b\u7ed3\u4ee5\u4e0a\u4e24\u90e8\u5206\u5185\u5bb9\uff0c\u5e76\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u4efb\u52a1\uff1a\u4e3a\u4e00\u6bb5\u4ea7\u54c1\u8bc4\u8bba\u751f\u6210\u7ed3\u6784\u5316\u6458\u8981\u3002
\u65e0\u683c\u5f0f\u7684\u6307\u4ee4\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4ea7\u54c1\u8bc4\u8bba\uff1a\n{\u8bc4\u8bba\u5185\u5bb9}\n
\u6807\u51c6\u5316\u7684\u6307\u4ee4\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4ea7\u54c1\u8bc4\u8bba\uff0c\u5e76\u4ee5\u8868\u683c\u5f62\u5f0f\u8f93\u51fa\u3002\u8868\u683c\u5e94\u5305\u542b\u4ee5\u4e0b\u5b57\u6bb5\uff1a\u4f18\u70b9\u3001\u7f3a\u70b9\u3001\u5efa\u8bae\u3002\n\u8bc4\u8bba\uff1a\n\"\"\"\n{\u8bc4\u8bba\u5185\u5bb9}\n\"\"\"\n
\u8f93\u51fa\u793a\u4f8b\uff1a
Markdown| \u4f18\u70b9 | \u7f3a\u70b9 | \u5efa\u8bae |\n|-----------------|---------------|--------------------|\n| \u4ef7\u683c\u4fbf\u5b9c | \u505a\u5de5\u4e00\u822c | \u6539\u5584\u4ea7\u54c1\u5916\u89c2\u8bbe\u8ba1 |\n| \u529f\u80fd\u9f50\u5168 | \u64cd\u4f5c\u590d\u6742 | \u7b80\u5316\u7528\u6237\u64cd\u4f5c\u6d41\u7a0b |\n
"},{"location":"Tools/AI/prompt_writing/#13","title":"1.3 \u4f18\u5316\u4e0e\u8fed\u4ee3","text":""},{"location":"Tools/AI/prompt_writing/#131-ai-prompt","title":"1.3.1 \u5982\u4f55\u901a\u8fc7 AI \u5e2e\u52a9\u6539\u5199\u6216\u4f18\u5316 Prompt\uff1f","text":""},{"location":"Tools/AI/prompt_writing/#1311-ai-prompt","title":"1.3.1.1 \u4e3a\u4ec0\u4e48\u8ba9 AI \u4f18\u5316 Prompt\uff1f","text":"AI \u64c5\u957f\u4ece\u5c11\u91cf\u8f93\u5165\u4e2d\u63d0\u53d6\u89c4\u5f8b\uff0c\u53ef\u4ee5\u5feb\u901f\u8c03\u6574\u8bed\u8a00\u98ce\u683c\u548c\u7ec6\u8282\uff0c\u5e2e\u52a9\u7528\u6237\u4f18\u5316 Prompt\uff0c\u5c24\u5176\u5728\u4efb\u52a1\u9700\u6c42\u6a21\u7cca\u6216\u7f3a\u4e4f\u6e05\u6670\u6307\u4ee4\u7684\u60c5\u51b5\u4e0b\u3002
"},{"location":"Tools/AI/prompt_writing/#1312","title":"1.3.1.2 \u5177\u4f53\u65b9\u6cd5","text":"\u793a\u4f8b\uff1a \u539f\u59cb Prompt\uff1a
Text Only\u8bf7\u7528\u7b80\u5355\u7684\u8bed\u8a00\u89e3\u91ca\u4ee5\u4e0b\u6570\u5b66\u9898\u7684\u89e3\u6cd5\u3002\n
\u8bf7\u6c42\u4f18\u5316\uff1a
Text Only\u8bf7\u5e2e\u52a9\u4f18\u5316\u8fd9\u6bb5 Prompt\uff0c\u8ba9\u5b83\u66f4\u9002\u5408\u5c0f\u5b66\u516d\u5e74\u7ea7\u5b66\u751f\u3002\n
\u4f18\u5316\u7ed3\u679c\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u5c0f\u5b66\u6570\u5b66\u8001\u5e08\uff0c\u8bf7\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\uff0c\u7ed3\u5408\u751f\u6d3b\u4e2d\u7684\u4f8b\u5b50\uff0c\u89e3\u91ca\u4ee5\u4e0b\u6570\u5b66\u9898\u7684\u89e3\u6cd5\u3002\n
\u793a\u4f8b\uff1a \u7b2c1\u8f6e\u4f18\u5316\uff1a
Text Only\u8fd9\u4e2a Prompt \u6bd4\u8f83\u9002\u5408\u521d\u5b66\u8005\uff0c\u4f46\u53ef\u4ee5\u589e\u52a0\u4e00\u4e9b\u751f\u6d3b\u5316\u7684\u4f8b\u5b50\u6765\u63d0\u5347\u5438\u5f15\u529b\u3002\n
\u7b2c2\u8f6e\u4f18\u5316\uff1a
Text Only\u7ed3\u5408\u751f\u6d3b\u4e2d\u7684\u5b9e\u4f8b\u8865\u5145\uff0c\u5982\u201c\u901a\u8fc7\u4e70\u82f9\u679c\u6765\u8ba1\u7b97\u603b\u4ef7\u201d\uff0c\u4f7f\u5f97\u8bb2\u89e3\u66f4\u52a0\u751f\u52a8\u3002\n
\u5927\u6a21\u578b\u5bf9\u8ba1\u7b97\u548c\u5b9e\u65f6\u6570\u636e\u7684\u652f\u6301\u6709\u9650\uff0c\u56e0\u6b64\u7ed3\u5408\u5916\u90e8\u5de5\u5177\uff0c\u5982 API \u8c03\u7528\u6216\u4ee3\u7801\u6267\u884c\uff0c\u53ef\u4ee5\u63d0\u5347\u4efb\u52a1\u7684\u51c6\u786e\u6027\u3002
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u6c42\u89e3\u591a\u9879\u5f0f\u7684\u6240\u6709\u5b9e\u6839\u3002 Prompt\uff1a
Text Only\u8bf7\u7528 Python \u7f16\u5199\u4ee3\u7801\u6765\u8ba1\u7b97\u4ee5\u4e0b\u591a\u9879\u5f0f\u7684\u6240\u6709\u5b9e\u6839\uff1a\n\u591a\u9879\u5f0f\uff1a3x^3 - 5x^2 + 2x - 7\n\u8f93\u51fa Python \u4ee3\u7801\u5e76\u89e3\u91ca\u5176\u4f5c\u7528\u3002\n
\u8f93\u51fa\u7ed3\u679c\uff1a
Pythonimport numpy as np\ncoefficients = [3, -5, 2, -7]\nroots = np.roots(coefficients)\nprint(\"\u5b9e\u6839\u4e3a\uff1a\", [r for r in roots if np.isreal(r)])\n
\u89e3\u91ca\uff1a\u6b64\u4ee3\u7801\u4f7f\u7528 NumPy \u7684 roots
\u51fd\u6570\u8ba1\u7b97\u591a\u9879\u5f0f\u7684\u6240\u6709\u6839\uff0c\u5e76\u8fc7\u6ee4\u51fa\u5b9e\u6839\u3002
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u751f\u6210\u4f1a\u8bae\u7eaa\u8981\u3002 Prompt\uff1a
Text Only\u8bf7\u5c06\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\u603b\u7ed3\u4e3a Markdown \u683c\u5f0f\uff0c\u5305\u62ec\u53d1\u8a00\u4eba\u3001\u4e3b\u8981\u89c2\u70b9\u548c\u540e\u7eed\u4efb\u52a1\u3002\n
\u8f93\u51fa\uff1a
Markdown### \u4f1a\u8bae\u7eaa\u8981\n\n#### \u53d1\u8a00\u4eba\u53ca\u89c2\u70b9\n- **\u5f20\u4e09**\uff1a\u5efa\u8bae\u589e\u52a0\u5e02\u573a\u8425\u9500\u9884\u7b97\u3002\n- **\u674e\u56db**\uff1a\u5f3a\u8c03\u4f18\u5316\u4ea7\u54c1\u8d28\u91cf\u7684\u91cd\u8981\u6027\u3002\n\n#### \u540e\u7eed\u4efb\u52a1\n- \u5236\u5b9a\u65b0\u4e00\u5b63\u5ea6\u7684\u8425\u9500\u7b56\u7565\uff08\u8d1f\u8d23\u4eba\uff1a\u5f20\u4e09\uff09\u3002\n- \u8c03\u67e5\u7528\u6237\u5bf9\u5f53\u524d\u4ea7\u54c1\u7684\u6ee1\u610f\u5ea6\uff08\u8d1f\u8d23\u4eba\uff1a\u674e\u56db\uff09\u3002\n
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u751f\u6210\u6570\u5b66\u516c\u5f0f\u3002 Prompt\uff1a
Text Only\u8bf7\u7528 LaTeX \u683c\u5f0f\u4e66\u5199\u4ee5\u4e0b\u516c\u5f0f\u5e76\u89e3\u91ca\uff1a$(a+b)^2 = a^2 + 2ab + b^2$\u3002\n
\u8f93\u51fa\uff1a
TeX\\[\n(a+b)^2 = a^2 + 2ab + b^2\n\\]\n\u8fd9\u662f\u4e00\u4e2a\u57fa\u672c\u7684\u5e73\u65b9\u5c55\u5f00\u516c\u5f0f\uff0c\u5e38\u7528\u4e8e\u591a\u9879\u5f0f\u7684\u8ba1\u7b97\u3002\n
\u5f00\u653e\u5f0f\u4efb\u52a1\uff08\u5982\u5199\u6545\u4e8b\u6216\u63a8\u8350\u65b9\u6848\uff09\u5bb9\u6613\u5bfc\u81f4\u6a21\u578b\u201c\u8dd1\u9898\u201d\uff0c\u901a\u8fc7\u515c\u5e95\u7b56\u7565\u53ef\u63d0\u9ad8\u7a33\u5b9a\u6027\u3002
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u73b0\u5728\u4f60\u662f\u4e00\u4e2a\u5411\u5ba2\u6237\u63a8\u8350\u7535\u5f71\u7684\u52a9\u624b\u3002\u5982\u679c\u5ba2\u6237\u7684\u4fe1\u606f\u4e0d\u8db3\u4ee5\u7ed9\u51fa\u63a8\u8350\uff0c\u8bf7\u56de\u7b54\uff1a\u201c\u62b1\u6b49\uff0c\u6211\u65e0\u6cd5\u6839\u636e\u60a8\u7684\u63cf\u8ff0\u63a8\u8350\u7535\u5f71\u3002\u201d\u3002\n
\u8f93\u5165\uff1a
Text Only\u5ba2\u6237\uff1a\u5e2e\u6211\u63a8\u8350\u4e00\u90e8\u7535\u5f71\u3002\n
\u8f93\u51fa\uff1a
Text Only\u62b1\u6b49\uff0c\u6211\u65e0\u6cd5\u6839\u636e\u60a8\u7684\u63cf\u8ff0\u63a8\u8350\u7535\u5f71\u3002\n
\u793a\u4f8b\uff1a\u5f53\u751f\u6210\u7ed3\u679c\u4e0d\u7b26\u5408\u683c\u5f0f\u65f6\uff0c\u8981\u6c42\u91cd\u65b0\u751f\u6210\u3002
Text Only\u5982\u679c\u4ee5\u4e0b\u5185\u5bb9\u7684\u8f93\u51fa\u683c\u5f0f\u9519\u8bef\uff0c\u8bf7\u91cd\u65b0\u751f\u6210\u5e76\u786e\u4fdd\u7b26\u5408\u8981\u6c42\uff1a\n\u8f93\u51fa\u683c\u5f0f\uff1a\n- \u4efb\u52a1\u63cf\u8ff0\n- \u4efb\u52a1\u8981\u70b9\n- \u4efb\u52a1\u5efa\u8bae\n
\u4f7f\u7528\u7279\u6b8a\u7b26\u53f7\uff08\u5982\u52a0\u7c97\uff09\u6216\u5f3a\u8c03\u8bcd\uff08\u5982\u201c\u52a1\u5fc5\u201d\u3001\u201c\u4e25\u683c\u201d\uff09\u6807\u6ce8\u5173\u952e\u5185\u5bb9\u3002
\u4efb\u52a1\uff1a\u603b\u7ed3\u6587\u7ae0\u5e76\u5f3a\u8c03\u5173\u952e\u6982\u5ff5\u3002 Prompt\uff1a
Text Only ```text\n \u8bf7\u603b\u7ed3\u4ee5\u4e0b\u6587\u7ae0\uff0c\u5e76**\u52a0\u7c97**\u6bcf\u4e2a\u8981\u70b9\u4e2d\u7684\u5173\u952e\u6982\u5ff5\uff0c\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n ```\n\n **\u8f93\u51fa**\uff1a\n\n ```markdown\n - **\u8981\u70b9\u4e00**\uff1a\u673a\u5668\u5b66\u4e60\u662f\u901a\u8fc7\u6570\u636e\u8bad\u7ec3\u6a21\u578b\u7684**\u65b9\u6cd5**\u3002\n - **\u8981\u70b9\u4e8c**\uff1a\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684**\u5206\u652f**\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\u3002\n ```\n
"},{"location":"Tools/AI/prompt_writing/#14","title":"1.4 \u5b9e\u7528\u6848\u4f8b","text":""},{"location":"Tools/AI/prompt_writing/#141","title":"1.4.1 \u5e38\u89c1\u573a\u666f\u4e0e\u89e3\u51b3\u65b9\u6848","text":""},{"location":"Tools/AI/prompt_writing/#1411","title":"1.4.1.1 \u751f\u6210\u957f\u7bc7\u7684\u6587\u7ae0","text":"\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u4e00\u4efd\u8be6\u7ec6\u7684\u6587\u7ae0\u76ee\u5f55\uff0c\u7136\u540e\u57fa\u4e8e\u76ee\u5f55\u9010\u6bb5\u6269\u5c55\u5185\u5bb9\uff1a\n\u4e3b\u9898\uff1a\u5982\u4f55\u4f18\u5316\u4e2a\u4eba\u65f6\u95f4\u7ba1\u7406\n
\u8f93\u51fa\u76ee\u5f55\u793a\u4f8b\uff1a
Markdown- \u7b2c\u4e00\u90e8\u5206\uff1a\u65f6\u95f4\u7ba1\u7406\u7684\u91cd\u8981\u6027\n- \u7b2c\u4e8c\u90e8\u5206\uff1a\u5e38\u89c1\u65f6\u95f4\u7ba1\u7406\u8bef\u533a\n- \u7b2c\u4e09\u90e8\u5206\uff1a\u9ad8\u6548\u65f6\u95f4\u7ba1\u7406\u7684\u65b9\u6cd5\n - 1. \u8bbe\u5b9a\u76ee\u6807\u4e0e\u4f18\u5148\u7ea7\n - 2. \u4f7f\u7528\u5de5\u5177\u4e0e\u6280\u672f\n - 3. \u57f9\u517b\u65f6\u95f4\u7ba1\u7406\u4e60\u60ef\n- \u7b2c\u56db\u90e8\u5206\uff1a\u6848\u4f8b\u5206\u6790\u4e0e\u5e94\u7528\n
\u6269\u5c55\u5185\u5bb9 Prompt\uff1a
Text Only\u8bf7\u8be6\u7ec6\u64b0\u5199\u7b2c\u4e00\u90e8\u5206\u201c\u65f6\u95f4\u7ba1\u7406\u7684\u91cd\u8981\u6027\u201d\u7684\u5185\u5bb9\uff0c\u63a7\u5236\u5728 300 \u5b57\u5de6\u53f3\u3002\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u4e00\u7bc7 500 \u5b57\u7684\u6587\u7ae0\uff0c\u5e76\u5728\u6587\u7ae0\u672b\u5c3e\u9644\u4e0a\u76f8\u5173\u53c2\u8003\u6587\u732e\uff1a\n\u4e3b\u9898\uff1a\u4eba\u5de5\u667a\u80fd\u5982\u4f55\u6539\u53d8\u6559\u80b2\u884c\u4e1a\n
\u8f93\u51fa\uff1a
Markdown### \u4eba\u5de5\u667a\u80fd\u5982\u4f55\u6539\u53d8\u6559\u80b2\u884c\u4e1a\n\uff08\u6587\u7ae0\u5185\u5bb9\uff09\n#### \u53c2\u8003\u6587\u732e\n- \u674e\u56db\uff0c\u300a\u4eba\u5de5\u667a\u80fd\u4e0e\u6559\u80b2\u300b\uff0c2023\u5e74\u51fa\u7248\u3002\n- OpenAI\uff0c\u300aAI\u5728\u6559\u80b2\u9886\u57df\u7684\u5e94\u7528\u300b\uff0c2021\u5e74\u3002\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u4ee5\u4e0b\u662f Python \u4ee3\u7801\u7247\u6bb5\uff0c\u8bf7\u89e3\u91ca\u5176\u4f5c\u7528\uff1a\n```python\nnested_dict = lambda: defaultdict(nested_dict)\n
Text Only**\u8f93\u51fa**\uff1a\n```text\n\u6b64\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5d4c\u5957\u5b57\u5178\u7684\u9012\u5f52\u7ed3\u6784\uff0c\u53ef\u4ee5\u52a8\u6001\u521b\u5efa\u4efb\u610f\u6df1\u5ea6\u7684\u5b57\u5178\u5c42\u7ea7\u3002\n\u793a\u4f8b\u7528\u6cd5\uff1a\ndata = nested_dict()\ndata['level1']['level2'] = \"value\"\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u6839\u636e\u4ee5\u4e0b\u63cf\u8ff0\u751f\u6210\u4e00\u6bb5 mermaid \u683c\u5f0f\u7684\u4ee3\u7801\uff0c\u7528\u4e8e\u5c55\u793a\u51fd\u6570\u8c03\u7528\u5173\u7cfb\uff1a\n\u63cf\u8ff0\uff1a\u51fd\u6570 A \u8c03\u7528\u51fd\u6570 B\uff0c\u51fd\u6570 B \u8c03\u7528\u51fd\u6570 C \u548c D\uff0c\u51fd\u6570 D \u8fd4\u56de\u7ed3\u679c\u3002\n
\u8f93\u51fa\uff1a
Text Onlygraph TD\nA --> B\nB --> C\nB --> D\nD --> Result\n
\u63d0\u793a\u6a21\u578b\u4e0d\u8981\u56de\u7b54\u5176\u65e0\u6cd5\u786e\u5b9a\u7684\u5185\u5bb9\u3002 \u793a\u4f8b\uff1a
Text Only\u5982\u679c\u4f60\u4e0d\u77e5\u9053\u4ee5\u4e0b\u95ee\u9898\u7684\u7b54\u6848\uff0c\u8bf7\u56de\u590d\u201c\u4fe1\u606f\u4e0d\u8db3\u201d\u3002\n\u95ee\u9898\uff1a\u8c01\u662f\u7b2c\u4e00\u4e2a\u767b\u4e0a\u6708\u7403\u7684\u673a\u5668\u4eba\uff1f\n
\u8f93\u51fa\uff1a
Text Only\u4fe1\u606f\u4e0d\u8db3\u3002\n
Prompt\uff1a
Text Only\u8bf7\u591a\u6b21\u751f\u6210\u4ee5\u4e0b\u95ee\u9898\u7684\u7b54\u6848\uff0c\u5e76\u786e\u4fdd\u7b54\u6848\u4e00\u81f4\u3002\u5982\u679c\u7b54\u6848\u4e0d\u4e00\u81f4\uff0c\u8bf7\u56de\u590d\u201c\u65e0\u6cd5\u786e\u5b9a\u7b54\u6848\u201d\u3002\n\u95ee\u9898\uff1a2023 \u5e74\u4e16\u754c\u4eba\u53e3\u603b\u6570\u662f\u591a\u5c11\uff1f\n
\u901a\u8fc7\u4e0d\u540c\u6a21\u578b\u534f\u4f5c\u4f18\u5316\u5185\u5bb9\u751f\u6210\u3002 \u793a\u4f8b\u6d41\u7a0b\uff1a
\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u8be6\u7ec6\u7684\u6587\u7ae0\u6846\u67b6\uff1a\n\u4e3b\u9898\uff1a\u5982\u4f55\u63d0\u5347\u56e2\u961f\u5408\u4f5c\u6548\u7387\n
\u8bf7\u6839\u636e\u4ee5\u4e0b\u6846\u67b6\u64b0\u5199\u8be6\u7ec6\u5185\u5bb9\uff0c\u5e76\u8c03\u6574\u4e3a\u66f4\u4e13\u4e1a\u7684\u8bed\u8a00\u3002\n
\u8bf7\u4f18\u5316\u4ee5\u4e0b\u4ee3\u7801\uff0c\u4f7f\u5176\u8fd0\u884c\u6548\u7387\u66f4\u9ad8\uff0c\u5e76\u63d0\u4f9b\u6ce8\u91ca\u8bf4\u660e\uff1a\n ```python\n def factorial(n):\n if n == 0:\n return 1\n else:\n return n * factorial(n-1)\n ```\n
"},{"location":"Tools/AI/prompt_writing/#15","title":"1.5 \u6211\u66fe\u7ecf\u7528\u6cd5","text":"\u8bf7\u53c2\u8003 \u5e38\u7528 prompt \u8bb0\u5f55 - wnc \u7684\u5496\u5561\u9986
"},{"location":"Tools/Blog/Mkdocs_Material/","title":"mkdocs material \u8d85\u5168\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#mkdocs-material","title":"mkdocs material \u8d85\u5168\u914d\u7f6e","text":"\u7ea6 5956 \u4e2a\u5b57 9393 \u884c\u4ee3\u7801 7 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 147 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u4ecd\u7136\u5728\u4fee\u6539 \u5982\u679c\u9700\u8981\u4efb\u4f55\u7684\u6587\u4ef6\uff0c\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee\u672c\u535a\u5ba2\u7684 GitHub \u9875\u9762
"},{"location":"Tools/Blog/Mkdocs_Material/#1","title":"1 \u5165\u95e8\u57fa\u7840","text":""},{"location":"Tools/Blog/Mkdocs_Material/#11-mkdocs","title":"1.1 \u4ec0\u4e48\u662f MkDocs\uff1f","text":"MkDocs \u662f\u4e00\u4e2a\u5feb\u901f\u3001\u7b80\u5355\u3001\u534e\u4e3d\u7684\u9759\u6001\u7ad9\u70b9\u751f\u6210\u5668\uff0c\u4e13\u95e8\u7528\u4e8e\u6784\u5efa\u9879\u76ee\u6587\u6863\u3002\u6587\u6863\u6e90\u6587\u4ef6\u4f7f\u7528 Markdown \u7f16\u5199\uff0c\u914d\u7f6e\u6587\u4ef6\u4f7f\u7528 YAML \u683c\u5f0f\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#111-mkdocs","title":"1.1.1 MkDocs \u7684\u4f18\u52bf","text":"\u7b80\u5355\u6613\u7528 - \u4f7f\u7528 Markdown \u7f16\u5199\u6587\u6863 - \u914d\u7f6e\u6587\u4ef6\u7b80\u5355\u76f4\u89c2 - \u4e00\u952e\u5f0f\u6784\u5efa\u548c\u90e8\u7f72
\u529f\u80fd\u5f3a\u5927 - \u5185\u7f6e\u5f00\u53d1\u670d\u52a1\u5668\uff0c\u652f\u6301\u5b9e\u65f6\u9884\u89c8 - \u591a\u79cd\u4e3b\u9898\u53ef\u9009 - \u652f\u6301\u81ea\u5b9a\u4e49\u4e3b\u9898 - \u81ea\u52a8\u751f\u6210\u5bfc\u822a - \u5168\u6587\u641c\u7d22\u529f\u80fd
\u90e8\u7f72\u65b9\u4fbf - \u751f\u6210\u7eaf\u9759\u6001\u9875\u9762 - \u4e00\u884c\u547d\u4ee4\u90e8\u7f72\u5230 GitHub Pages - \u652f\u6301\u81ea\u5b9a\u4e49\u57df\u540d - \u517c\u5bb9\u6240\u6709\u9759\u6001\u7f51\u7ad9\u6258\u7ba1\u5e73\u53f0
MkDocs \u7684\u5de5\u4f5c\u6d41\u7a0b\u5982\u4e0b\uff1a
\u6587\u6863\u7f16\u5199 - \u4f7f\u7528 Markdown \u683c\u5f0f\u7f16\u5199\u6587\u6863 - \u6587\u6863\u5b58\u653e\u5728 docs
\u76ee\u5f55\u4e0b - \u652f\u6301\u591a\u7ea7\u76ee\u5f55\u7ed3\u6784
\u914d\u7f6e\u89e3\u6790 - \u8bfb\u53d6 mkdocs.yml
\u914d\u7f6e\u6587\u4ef6 - \u89e3\u6790\u4e3b\u9898\u8bbe\u7f6e\u3001\u63d2\u4ef6\u914d\u7f6e\u7b49 - \u751f\u6210\u5bfc\u822a\u7ed3\u6784
\u6784\u5efa\u8fc7\u7a0b
Markdown \u6587\u4ef6 -> \u89e3\u6790\u5668 -> HTML \u6587\u4ef6\n -> \u4e3b\u9898\u6e32\u67d3\n -> \u63d2\u4ef6\u5904\u7406\n -> \u9759\u6001\u8d44\u6e90\u5904\u7406\n
Material for MkDocs \u662f\u4e00\u4e2a\u57fa\u4e8e Google Material Design \u8bbe\u8ba1\u8bed\u8a00\u7684\u4e3b\u9898\uff0c\u5b83\u4e0d\u4ec5\u7f8e\u89c2\uff0c\u800c\u4e14\u529f\u80fd\u5f3a\u5927\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#121-material","title":"1.2.1 Material \u4e3b\u9898\u7279\u6027","text":"\u73b0\u4ee3\u5316\u8bbe\u8ba1 - \u9075\u5faa Material Design \u89c4\u8303 - \u54cd\u5e94\u5f0f\u5e03\u5c40 - \u652f\u6301\u6df1\u8272\u6a21\u5f0f - \u81ea\u52a8\u9002\u914d\u79fb\u52a8\u8bbe\u5907
\u5f3a\u5927\u529f\u80fd - \u667a\u80fd\u641c\u7d22 - \u4ee3\u7801\u9ad8\u4eae - \u6807\u7b7e\u9875\u652f\u6301 - \u81ea\u52a8\u76ee\u5f55\u751f\u6210 - \u591a\u8bed\u8a00\u652f\u6301 - \u7248\u672c\u63a7\u5236\u96c6\u6210
\u51fa\u8272\u7684\u7528\u6237\u4f53\u9a8c - \u5feb\u901f\u52a0\u8f7d - \u5e73\u6ed1\u52a8\u753b - \u5b9e\u65f6\u641c\u7d22 - \u4ee3\u7801\u590d\u5236\u6309\u94ae - \u8fd4\u56de\u9876\u90e8\u6309\u94ae
Material Theme\n\u251c\u2500\u2500 \u6838\u5fc3\u7ec4\u4ef6\n\u2502 \u251c\u2500\u2500 \u5bfc\u822a\u680f\n\u2502 \u251c\u2500\u2500 \u4fa7\u8fb9\u680f\n\u2502 \u251c\u2500\u2500 \u641c\u7d22\u7ec4\u4ef6\n\u2502 \u2514\u2500\u2500 \u5185\u5bb9\u6e32\u67d3\u5668\n\u251c\u2500\u2500 \u6269\u5c55\u529f\u80fd\n\u2502 \u251c\u2500\u2500 \u4ee3\u7801\u9ad8\u4eae\n\u2502 \u251c\u2500\u2500 \u6807\u7b7e\u7cfb\u7edf\n\u2502 \u251c\u2500\u2500 \u76ee\u5f55\u751f\u6210\n\u2502 \u2514\u2500\u2500 \u4e3b\u9898\u5207\u6362\n\u2514\u2500\u2500 \u63d2\u4ef6\u7cfb\u7edf\n \u251c\u2500\u2500 \u5185\u7f6e\u63d2\u4ef6\n \u2514\u2500\u2500 \u7b2c\u4e09\u65b9\u63d2\u4ef6\u96c6\u6210\n
"},{"location":"Tools/Blog/Mkdocs_Material/#13","title":"1.3 \u73af\u5883\u8981\u6c42","text":""},{"location":"Tools/Blog/Mkdocs_Material/#131-python","title":"1.3.1 Python \u73af\u5883","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1311-python","title":"1.3.1.1 Python \u7248\u672c\u9009\u62e9","text":"MkDocs \u9700\u8981 Python 3.6 \u6216\u66f4\u9ad8\u7248\u672c\uff0c\u63a8\u8350\u4f7f\u7528 Python 3.8+\uff1a
Bash# \u68c0\u67e5 Python \u7248\u672c\npython --version\n\n# \u63a8\u8350\u7248\u672c\nPython 3.8.x\nPython 3.9.x\nPython 3.10.x\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1312-pip","title":"1.3.1.2 pip \u914d\u7f6e\u8bf4\u660e","text":"pip \u662f Python \u7684\u5305\u7ba1\u7406\u5de5\u5177\uff0c\u9700\u8981\u786e\u4fdd\u5176\u6b63\u786e\u5b89\u88c5\uff1a
Bash# \u68c0\u67e5 pip \u7248\u672c\npip --version\n\n# \u5347\u7ea7 pip\npython -m pip install --upgrade pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1313","title":"1.3.1.3 \u865a\u62df\u73af\u5883\u7ba1\u7406","text":"\u63a8\u8350\u4f7f\u7528\u865a\u62df\u73af\u5883\u6765\u7ba1\u7406\u9879\u76ee\u4f9d\u8d56\uff1a
Bash# \u521b\u5efa\u865a\u62df\u73af\u5883\npython -m venv venv\n\n# \u6fc0\u6d3b\u865a\u62df\u73af\u5883\n# Windows\nvenv\\Scripts\\activate\n# Linux/Mac\nsource venv/bin/activate\n\n# \u9000\u51fa\u865a\u62df\u73af\u5883\ndeactivate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#132-pip","title":"1.3.2 pip \u5305\u7ba1\u7406","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1321-pip","title":"1.3.2.1 pip \u6e90\u914d\u7f6e","text":"\u4e3a\u52a0\u5feb\u4e0b\u8f7d\u901f\u5ea6\uff0c\u5efa\u8bae\u4f7f\u7528\u56fd\u5185\u955c\u50cf\u6e90\uff1a
Bash# \u4e34\u65f6\u4f7f\u7528\npip install -i https://pypi.tuna.tsinghua.edu.cn/simple mkdocs\n\n# \u6c38\u4e45\u914d\u7f6e\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1322","title":"1.3.2.2 \u4f9d\u8d56\u7ba1\u7406","text":"\u5b89\u88c5\u5fc5\u8981\u7684\u5305\uff1a
Bashpip install mkdocs-material\npip install mkdocs-glightbox\npip install mkdocs-git-revision-date-localized-plugin\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1323-requirements-txt","title":"1.3.2.3 requirements. txt \u4f7f\u7528","text":"\u7ef4\u62a4\u9879\u76ee\u4f9d\u8d56\uff1a
Bash# \u751f\u6210\u4f9d\u8d56\u6587\u4ef6\npip freeze > requirements.txt\n\n# \u5b89\u88c5\u4f9d\u8d56\npip install -r requirements.txt\n
"},{"location":"Tools/Blog/Mkdocs_Material/#133-git","title":"1.3.3 Git \u73af\u5883","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1331-git","title":"1.3.3.1 Git \u57fa\u7840\u914d\u7f6e","text":"Bash# \u914d\u7f6e\u7528\u6237\u4fe1\u606f\ngit config --global user.name \"Your Name\"\ngit config --global user.email \"your.email@example.com\"\n\n# \u914d\u7f6e\u9ed8\u8ba4\u5206\u652f\ngit config --global init.defaultBranch main\n
"},{"location":"Tools/Blog/Mkdocs_Material/#134-ssh","title":"1.3.4 SSH \u5bc6\u94a5\u914d\u7f6e","text":"Bash# \u751f\u6210 SSH \u5bc6\u94a5\nssh-keygen -t rsa -b 4096 -C \"your.email@example.com\"\n\n# \u67e5\u770b\u516c\u94a5\ncat ~/.ssh/id_rsa.pub\n
\u5c06\u516c\u94a5\u6dfb\u52a0\u5230 GitHub \u8d26\u6237\u7684 SSH keys \u4e2d\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#135-gitignore","title":"1.3.5 .gitignore \u914d\u7f6e","text":"\u521b\u5efa .gitignore
\u6587\u4ef6\uff0c\u6dfb\u52a0\u4ee5\u4e0b\u5185\u5bb9\uff1a
# Python\n__pycache__/\n*.py[cod]\n*$py.class\nvenv/\n\n# MkDocs\nsite/\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2","title":"2 \u73af\u5883\u642d\u5efa","text":""},{"location":"Tools/Blog/Mkdocs_Material/#21-windows","title":"2.1 Windows \u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#211-python","title":"2.1.1 Python \u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2111","title":"2.1.1.1 \u4e0b\u8f7d\u5b89\u88c5\u5305","text":"# \u6dfb\u52a0\u5230\u7cfb\u7edf\u73af\u5883\u53d8\u91cf Path\nC:\\Users\\YourUser\\AppData\\Local\\Programs\\Python\\Python3x\\\nC:\\Users\\YourUser\\AppData\\Local\\Programs\\Python\\Python3x\\Scripts\\\n
echo %PATH%\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2113","title":"2.1.1.3 \u9a8c\u8bc1\u5b89\u88c5","text":"\u5728\u547d\u4ee4\u63d0\u793a\u7b26\u4e2d\u6267\u884c\uff1a
Bash# \u68c0\u67e5 Python \u7248\u672c\npython --version\n\n# \u68c0\u67e5 pip \u7248\u672c\npip --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#212-mkdocs","title":"2.1.2 MkDocs \u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2121-pip","title":"2.1.2.1 pip \u5b89\u88c5\u65b9\u6cd5","text":"\u4f7f\u7528 pip \u5b89\u88c5 MkDocs\uff1a
Bash# \u5b89\u88c5 MkDocs\npip install mkdocs\n\n# \u9a8c\u8bc1\u5b89\u88c5\nmkdocs --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2122","title":"2.1.2.2 \u5e38\u89c1\u95ee\u9898\u89e3\u51b3","text":"pip \u4e0d\u662f\u5185\u90e8\u547d\u4ee4 - \u89e3\u51b3\u65b9\u6cd5\uff1a\u91cd\u65b0\u6dfb\u52a0 Python Scripts \u76ee\u5f55\u5230 PATH
\u6743\u9650\u95ee\u9898 - \u89e3\u51b3\u65b9\u6cd5\uff1a\u4f7f\u7528\u7ba1\u7406\u5458\u6743\u9650\u8fd0\u884c\u547d\u4ee4\u63d0\u793a\u7b26
# \u7ba1\u7406\u5458\u6743\u9650\u5b89\u88c5\npip install --user mkdocs\n
pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org mkdocs\n
"},{"location":"Tools/Blog/Mkdocs_Material/#213","title":"2.1.3 \u7248\u672c\u9009\u62e9","text":"MkDocs \u7248\u672c\u9009\u62e9\u5efa\u8bae\uff1a
Bash# \u67e5\u770b\u53ef\u7528\u7248\u672c\npip install mkdocs==\n\n# \u5b89\u88c5\u7279\u5b9a\u7248\u672c\npip install mkdocs==1.5.3 # \u63a8\u8350\u7248\u672c\n
"},{"location":"Tools/Blog/Mkdocs_Material/#214-material","title":"2.1.4 Material \u4e3b\u9898\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2141","title":"2.1.4.1 \u5b89\u88c5\u547d\u4ee4","text":"Bash# \u5b89\u88c5 Material \u4e3b\u9898\npip install mkdocs-material\n\n# \u9a8c\u8bc1\u5b89\u88c5\npython -c \"import mkdocs_material; print(mkdocs_material.__version__)\"\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2142","title":"2.1.4.2 \u4f9d\u8d56\u68c0\u67e5","text":"\u5b89\u88c5\u5fc5\u8981\u7684\u4f9d\u8d56\uff1a
Bash# \u5b89\u88c5\u6269\u5c55\u652f\u6301\npip install pymdown-extensions\npip install mkdocs-glightbox\npip install mkdocs-git-revision-date-localized-plugin\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2143","title":"2.1.4.3 \u7248\u672c\u517c\u5bb9\u6027","text":"MkDocs \u7248\u672c Material \u7248\u672c Python \u7248\u672c 1.5. x 9.4. x \u22653.8 1.4. x 9.3. x \u22653.7 1.3. x 9.2. x \u22653.7"},{"location":"Tools/Blog/Mkdocs_Material/#22-linuxmac","title":"2.2 Linux/Mac \u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#221-python","title":"2.2.1 \u5305\u7ba1\u7406\u5668\u5b89\u88c5 Python","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2211-aptyum","title":"2.2.1.1 apt/yum \u5b89\u88c5\u65b9\u6cd5","text":"Ubuntu/Debian:
Bash# \u66f4\u65b0\u5305\u7d22\u5f15\nsudo apt update\n\n# \u5b89\u88c5 Python\nsudo apt install python3 python3-pip\n\n# \u5b89\u88c5\u5f00\u53d1\u5de5\u5177\nsudo apt install python3-dev\n
CentOS/RHEL:
Bash# \u5b89\u88c5 EPEL \u4ed3\u5e93\nsudo yum install epel-release\n\n# \u5b89\u88c5 Python\nsudo yum install python3 python3-pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2212-brew","title":"2.2.1.2 brew \u5b89\u88c5\u65b9\u6cd5","text":"macOS:
Bash# \u5b89\u88c5 Homebrew\uff08\u5982\u679c\u672a\u5b89\u88c5\uff09\n/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n\n# \u5b89\u88c5 Python\nbrew install python\n\n# \u66f4\u65b0 pip\npip3 install --upgrade pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2213","title":"2.2.1.3 \u73af\u5883\u53d8\u91cf\u914d\u7f6e","text":"bash/zsh:
Bash# \u6dfb\u52a0\u5230 ~/.bashrc \u6216 ~/.zshrc\nexport PATH=\"$HOME/.local/bin:$PATH\"\nexport PYTHONPATH=\"$HOME/.local/lib/python3.x/site-packages:$PYTHONPATH\"\n\n# \u66f4\u65b0\u73af\u5883\u53d8\u91cf\nsource ~/.bashrc # \u6216 source ~/.zshrc\n
"},{"location":"Tools/Blog/Mkdocs_Material/#222-pip","title":"2.2.2 pip \u5b89\u88c5\u4f9d\u8d56","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2221","title":"2.2.2.1 \u7cfb\u7edf\u7ea7\u5b89\u88c5","text":"Bash# \u5168\u5c40\u5b89\u88c5\uff08\u9700\u8981 root \u6743\u9650\uff09\nsudo pip3 install mkdocs mkdocs-material\n\n# \u9a8c\u8bc1\u5b89\u88c5\nmkdocs --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2222","title":"2.2.2.2 \u7528\u6237\u7ea7\u5b89\u88c5","text":"Bash# \u7528\u6237\u76ee\u5f55\u5b89\u88c5\npip3 install --user mkdocs mkdocs-material\n\n# \u68c0\u67e5\u5b89\u88c5\u8def\u5f84\npython3 -m site --user-site\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2223","title":"2.2.2.3 \u865a\u62df\u73af\u5883\u5b89\u88c5","text":"Bash# \u521b\u5efa\u865a\u62df\u73af\u5883\npython3 -m venv mkdocs-env\n\n# \u6fc0\u6d3b\u865a\u62df\u73af\u5883\nsource mkdocs-env/bin/activate\n\n# \u5b89\u88c5\u4f9d\u8d56\npip install mkdocs mkdocs-material\n\n# \u9000\u51fa\u865a\u62df\u73af\u5883\ndeactivate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#23","title":"2.3 \u9879\u76ee\u521d\u59cb\u5316","text":""},{"location":"Tools/Blog/Mkdocs_Material/#231","title":"2.3.1 \u521b\u5efa\u9879\u76ee","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2311-mkdocs-new","title":"2.3.1.1 mkdocs new \u547d\u4ee4\u8be6\u89e3","text":"Bash# \u57fa\u672c\u8bed\u6cd5\nmkdocs new [\u9879\u76ee\u540d]\n\n# \u521b\u5efa\u65b0\u9879\u76ee\nmkdocs new my-docs\n\n# \u4f7f\u7528\u73b0\u6709\u76ee\u5f55\ncd existing-project\nmkdocs new .\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2312","title":"2.3.1.2 \u9879\u76ee\u547d\u540d\u89c4\u8303","text":"\u793a\u4f8b\uff1a
Bashmkdocs new technical-docs # \u597d\u7684\u547d\u540d\nmkdocs new tech_docs # \u907f\u514d\u4f7f\u7528\u4e0b\u5212\u7ebf\nmkdocs new TechDocs # \u907f\u514d\u4f7f\u7528\u5927\u5199\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2313","title":"2.3.1.3 \u521d\u59cb\u5316\u914d\u7f6e","text":"\u521b\u5efa\u9879\u76ee\u540e\u7684\u57fa\u672c\u8bbe\u7f6e\uff1a
Bashcd my-docs\n# \u542f\u52a8\u5f00\u53d1\u670d\u52a1\u5668\nmkdocs serve\n# \u5728\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee http://127.0.0.1:8000\n
"},{"location":"Tools/Blog/Mkdocs_Material/#232","title":"2.3.2 \u76ee\u5f55\u7ed3\u6784\u8bf4\u660e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2321","title":"2.3.2.1 \u57fa\u7840\u76ee\u5f55\u7ed3\u6784","text":"Text Onlymy-docs/\n\u251c\u2500\u2500 docs/ # \u6587\u6863\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 index.md # \u9996\u9875\n\u2502 \u251c\u2500\u2500 about.md # \u5176\u4ed6\u9875\u9762\n\u2502 \u2514\u2500\u2500 img/ # \u56fe\u7247\u76ee\u5f55\n\u251c\u2500\u2500 mkdocs.yml # \u914d\u7f6e\u6587\u4ef6\n\u2514\u2500\u2500 venv/ # \u865a\u62df\u73af\u5883\uff08\u53ef\u9009\uff09\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2322-docs","title":"2.3.2.2 docs \u76ee\u5f55\u7ec4\u7ec7","text":"Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u9996\u9875\n\u251c\u2500\u2500 guide/ # \u6307\u5357\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 index.md # \u6307\u5357\u9996\u9875\n\u2502 \u251c\u2500\u2500 install.md # \u5b89\u88c5\u8bf4\u660e\n\u2502 \u2514\u2500\u2500 usage.md # \u4f7f\u7528\u8bf4\u660e\n\u251c\u2500\u2500 api/ # API\u6587\u6863\n\u2502 \u2514\u2500\u2500 index.md # API\u9996\u9875\n\u2514\u2500\u2500 examples/ # \u793a\u4f8b\u76ee\u5f55\n \u2514\u2500\u2500 basic.md # \u57fa\u7840\u793a\u4f8b\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2323","title":"2.3.2.3 \u8d44\u6e90\u6587\u4ef6\u7ba1\u7406","text":"Text Onlydocs/\n\u251c\u2500\u2500 assets/ # \u8d44\u6e90\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 images/ # \u56fe\u7247\u8d44\u6e90\n\u2502 \u251c\u2500\u2500 css/ # \u6837\u5f0f\u6587\u4ef6\n\u2502 \u251c\u2500\u2500 js/ # \u811a\u672c\u6587\u4ef6\n\u2502 \u2514\u2500\u2500 fonts/ # \u5b57\u4f53\u6587\u4ef6\n\u2514\u2500\u2500 files/ # \u4e0b\u8f7d\u6587\u4ef6\n \u2514\u2500\u2500 sample.pdf # \u793a\u4f8b\u6587\u4ef6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#233","title":"2.3.3 \u57fa\u7840\u914d\u7f6e\u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2331-mkdocs-yml","title":"2.3.3.1 mkdocs. yml \u7ed3\u6784","text":"\u57fa\u672c\u914d\u7f6e\u6587\u4ef6\u7ed3\u6784\uff1a
YAML# \u7ad9\u70b9\u4fe1\u606f\nsite_name: \u6211\u7684\u6587\u6863\nsite_url: https://example.com/\nsite_author: \u4f5c\u8005\u540d\nsite_description: \u7ad9\u70b9\u63cf\u8ff0\n\n# \u4e3b\u9898\u8bbe\u7f6e\ntheme:\n name: material\n language: zh\n features:\n - navigation.tabs\n - navigation.top\n\n# \u5bfc\u822a\u8bbe\u7f6e\nnav:\n - \u9996\u9875: index.md\n - \u6307\u5357: \n - guide/index.md\n - \u5b89\u88c5: guide/install.md\n - \u4f7f\u7528: guide/usage.md\n\n# Markdown \u6269\u5c55\nmarkdown_extensions:\n - attr_list\n - md_in_html\n - toc:\n permalink: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2332","title":"2.3.3.2 \u6700\u5c0f\u914d\u7f6e\u793a\u4f8b","text":"\u6700\u7b80\u5355\u7684\u914d\u7f6e\u6587\u4ef6\uff1a
YAMLsite_name: \u6211\u7684\u6587\u6863\ntheme:\n name: material\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2333","title":"2.3.3.3 \u914d\u7f6e\u6587\u4ef6\u8bed\u6cd5","text":"YAML \u8bed\u6cd5\u8981\u70b9\uff1a
YAML# \u5b57\u7b26\u4e32\ntitle: \u6211\u7684\u6587\u6863\n\n# \u5217\u8868\nplugins:\n - search\n - tags\n\n# \u5bf9\u8c61\ntheme:\n name: material\n features:\n - navigation.tabs\n\n# \u591a\u884c\u5b57\u7b26\u4e32\ndescription: >\n \u8fd9\u662f\u4e00\u4e2a\n \u591a\u884c\u63cf\u8ff0\n \u793a\u4f8b\n\n# \u951a\u70b9\u5f15\u7528\ncopyright: ©right 2024 My Docs\nfooter:\n copyright: *copyright\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3-mkdocs","title":"3 MkDocs \u6838\u5fc3\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#31","title":"3.1 \u7ad9\u70b9\u4fe1\u606f\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#311-site_name","title":"3.1.1 site_name \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3111","title":"3.1.1.1 \u547d\u540d\u89c4\u8303","text":"\u7f51\u7ad9\u540d\u79f0\u662f\u7ad9\u70b9\u7684\u7b2c\u4e00\u5370\u8c61\uff0c\u5e94\u9075\u5faa\u4ee5\u4e0b\u89c4\u8303\uff1a
YAML# \u63a8\u8350\u7684\u547d\u540d\u65b9\u5f0f\nsite_name: \u6280\u672f\u6587\u6863\u4e2d\u5fc3\nsite_name: Developer Hub\nsite_name: API Documentation\n\n# \u907f\u514d\u7684\u547d\u540d\u65b9\u5f0f\nsite_name: docs # \u592a\u8fc7\u7b80\u5355\nsite_name: My Doc Site # \u4e0d\u591f\u4e13\u4e1a\nsite_name: TEST # \u7f3a\u4e4f\u63cf\u8ff0\u6027\n
\u547d\u540d\u5efa\u8bae\uff1a
\u53ef\u4ee5\u901a\u8fc7\u914d\u7f6e\u5b9e\u73b0\u591a\u8bed\u8a00\u7ad9\u70b9\uff1a
YAML# \u57fa\u7840\u914d\u7f6e\nsite_name: My Documentation\ntheme:\n language: zh\n\n# \u591a\u8bed\u8a00\u914d\u7f6e\u793a\u4f8b\nextra:\n alternate:\n - name: English\n link: /en/ \n lang: en\n - name: \u4e2d\u6587\n link: /zh/\n lang: zh\n\n# \u8bed\u8a00\u7279\u5b9a\u7684\u7ad9\u70b9\u540d\u79f0\nsite_name:\n en: My Documentation\n zh: \u6211\u7684\u6587\u6863\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3113-seo","title":"3.1.1.3 SEO \u4f18\u5316","text":"\u901a\u8fc7\u5408\u9002\u7684\u7ad9\u70b9\u540d\u79f0\u63d0\u5347 SEO\uff1a
YAML# SEO \u4f18\u5316\u914d\u7f6e\nsite_name: ProductName Documentation | CompanyName\nextra:\n meta:\n - name: robots\n content: 'index, follow'\n - name: keywords\n content: 'docs, documentation, technical, api'\n
"},{"location":"Tools/Blog/Mkdocs_Material/#312-site_url","title":"3.1.2 site_url \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3121-url","title":"3.1.2.1 URL \u683c\u5f0f\u8981\u6c42","text":"YAML# \u6b63\u786e\u7684 URL \u683c\u5f0f\nsite_url: https://example.com/docs/\nsite_url: https://docs.example.com/\n\n# \u907f\u514d\u7684\u683c\u5f0f\nsite_url: http://example.com/docs # \u7f3a\u5c11\u5c3e\u90e8\u659c\u6760\nsite_url: example.com/docs/ # \u7f3a\u5c11\u534f\u8bae\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3122","title":"3.1.2.2 \u57fa\u7840\u8def\u5f84\u914d\u7f6e","text":"YAML# \u6839\u76ee\u5f55\u90e8\u7f72\nsite_url: https://example.com/\n\n# \u5b50\u76ee\u5f55\u90e8\u7f72\nsite_url: https://example.com/docs/\nuse_directory_urls: true # \u63a8\u8350\u8bbe\u7f6e\n\n# \u672c\u5730\u5f00\u53d1\nsite_url: http://localhost:8000/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3123","title":"3.1.2.3 \u5b50\u76ee\u5f55\u90e8\u7f72\u914d\u7f6e","text":"YAML# GitHub Pages \u5b50\u76ee\u5f55\u90e8\u7f72\nsite_url: https://username.github.io/repository/\n\n# \u81ea\u5b9a\u4e49\u57df\u540d\u5b50\u76ee\u5f55\nsite_url: https://docs.example.com/project/\nextra:\n base_path: /project/ # \u5982\u679c\u9700\u8981\n
"},{"location":"Tools/Blog/Mkdocs_Material/#313-site_author","title":"3.1.3 site_author \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3131","title":"3.1.3.1 \u4f5c\u8005\u4fe1\u606f\u8bbe\u7f6e","text":"YAML# \u57fa\u7840\u4f5c\u8005\u4fe1\u606f\nsite_author: John Doe\n\n# \u6269\u5c55\u4f5c\u8005\u4fe1\u606f\nextra:\n author:\n name: John Doe\n email: john@example.com\n website: https://johndoe.com\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3132","title":"3.1.3.2 \u7248\u6743\u4fe1\u606f","text":"YAML# \u7248\u6743\u58f0\u660e\ncopyright: \"© 2024 John Doe\"\n\n# \u9ad8\u7ea7\u7248\u6743\u914d\u7f6e\nextra:\n copyright:\n author: John Doe\n year: 2024\n license: CC BY-NC-SA 4.0\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3133-meta","title":"3.1.3.3 meta \u4fe1\u606f","text":"YAML# meta \u4fe1\u606f\u914d\u7f6e\nextra:\n meta:\n - name: author\n content: John Doe\n - name: contact\n content: contact@example.com\n - property: article:author\n content: https://example.com/author\n
"},{"location":"Tools/Blog/Mkdocs_Material/#314-site_description","title":"3.1.4 site_description \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3141-seo","title":"3.1.4.1 SEO \u63cf\u8ff0","text":"YAML# \u57fa\u7840\u63cf\u8ff0\nsite_description: \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\uff0c\u63d0\u4f9b\u8be6\u7ec6\u7684API\u6587\u6863\u3001\u4f7f\u7528\u6307\u5357\u548c\u6700\u4f73\u5b9e\u8df5\u3002\n\n# \u591a\u8bed\u8a00\u63cf\u8ff0\nextra:\n descriptions:\n en: Comprehensive technical documentation center\n zh: \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3142","title":"3.1.4.2 \u5173\u952e\u8bcd\u8bbe\u7f6e","text":"YAML# \u901a\u8fc7 meta \u6807\u7b7e\u8bbe\u7f6e\u5173\u952e\u8bcd\nextra:\n meta:\n - name: keywords\n content: MkDocs, documentation, technical docs, API, guides\n - name: description\n content: >-\n \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\uff0c\u5305\u542b\u8be6\u7ec6\u7684API\u6587\u6863\u3001\n \u4f7f\u7528\u6307\u5357\u548c\u6700\u4f73\u5b9e\u8df5\u793a\u4f8b\u3002\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3143","title":"3.1.4.3 \u7ad9\u70b9\u6458\u8981","text":"YAML# \u5b8c\u6574\u7684\u7ad9\u70b9\u4fe1\u606f\u914d\u7f6e\u793a\u4f8b\nsite_name: \u6280\u672f\u6587\u6863\u4e2d\u5fc3\nsite_description: >-\n \u63d0\u4f9b\u5168\u9762\u7684\u6280\u672f\u6587\u6863\u3001API\u53c2\u8003\u548c\u4f7f\u7528\u6307\u5357\uff0c\n \u5e2e\u52a9\u5f00\u53d1\u8005\u5feb\u901f\u4e0a\u624b\u548c\u6df1\u5165\u4e86\u89e3\u4ea7\u54c1\u529f\u80fd\u3002\nsite_author: \u5f00\u53d1\u56e2\u961f\nsite_url: https://docs.example.com/\n\nextra:\n meta:\n - name: keywords\n content: \u6280\u672f\u6587\u6863, API\u6587\u6863, \u5f00\u53d1\u6307\u5357, \u6700\u4f73\u5b9e\u8df5\n - name: author\n content: \u5f00\u53d1\u56e2\u961f\n - name: robots\n content: index, follow\n\n analytics:\n gtag: G-XXXXXXXXXX\n\ncopyright: \"© 2024 Example Company\"\n
"},{"location":"Tools/Blog/Mkdocs_Material/#315","title":"3.1.5 \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5","text":"SEO \u4f18\u5316\u5efa\u8bae\uff1a - \u4f7f\u7528\u6e05\u6670\u7684\u7ad9\u70b9\u540d\u79f0 - \u7f16\u5199\u6709\u5438\u5f15\u529b\u7684\u63cf\u8ff0 - \u5305\u542b\u76f8\u5173\u5173\u952e\u8bcd - \u786e\u4fdd URL \u7ed3\u6784\u5408\u7406
\u591a\u8bed\u8a00\u652f\u6301\uff1a - \u4e3a\u6bcf\u79cd\u8bed\u8a00\u63d0\u4f9b\u72ec\u7acb\u63cf\u8ff0 - \u4f7f\u7528\u6b63\u786e\u7684\u8bed\u8a00\u4ee3\u7801 - \u8bbe\u7f6e\u5408\u9002\u7684\u5b57\u7b26\u7f16\u7801
\u7248\u672c\u63a7\u5236\uff1a - \u8bb0\u5f55\u914d\u7f6e\u66f4\u6539 - \u4f7f\u7528\u7248\u672c\u6ce8\u91ca - \u5b9a\u671f\u66f4\u65b0\u7ad9\u70b9\u4fe1\u606f
\u53ef\u7ef4\u62a4\u6027\uff1a - \u4f7f\u7528\u6e05\u6670\u7684\u914d\u7f6e\u7ed3\u6784 - \u6dfb\u52a0\u5fc5\u8981\u7684\u6ce8\u91ca - \u4fdd\u6301\u914d\u7f6e\u6587\u4ef6\u6574\u6d01
\u6700\u57fa\u672c\u7684\u5bfc\u822a\u914d\u7f6e\u793a\u4f8b\uff1a
YAMLnav:\n - Home: index.md\n - About: about.md\n - Contact: contact.md\n
\u66f4\u590d\u6742\u7684\u5206\u7ec4\u793a\u4f8b\uff1a
YAMLnav:\n - \u9996\u9875: index.md\n - \u7528\u6237\u6307\u5357:\n - \u4ecb\u7ecd: guide/introduction.md\n - \u5feb\u901f\u5f00\u59cb: guide/getting-started.md\n - \u57fa\u7840\u6559\u7a0b: guide/basics.md\n - API \u6587\u6863:\n - \u6982\u89c8: api/overview.md\n - \u63a5\u53e3\u8bf4\u660e: api/reference.md\n - \u5e38\u89c1\u95ee\u9898: faq.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3212","title":"3.2.1.2 \u5206\u7c7b\u7ec4\u7ec7","text":"\u63a8\u8350\u7684\u5206\u7c7b\u65b9\u5f0f\uff1a
YAMLnav:\n - \u5f00\u59cb\u4f7f\u7528:\n - \u7b80\u4ecb: getting-started/introduction.md\n - \u5b89\u88c5: getting-started/installation.md\n - \u914d\u7f6e: getting-started/configuration.md\n\n - \u6838\u5fc3\u6982\u5ff5:\n - \u6982\u8ff0: concepts/overview.md\n - \u57fa\u7840\u67b6\u6784: concepts/architecture.md\n - \u5de5\u4f5c\u539f\u7406: concepts/how-it-works.md\n\n - \u9ad8\u7ea7\u6307\u5357:\n - \u81ea\u5b9a\u4e49\u4e3b\u9898: advanced/custom-theme.md\n - \u63d2\u4ef6\u5f00\u53d1: advanced/plugin-development.md\n - \u6027\u80fd\u4f18\u5316: advanced/performance.md\n\n - \u53c2\u8003\u6587\u6863:\n - API: reference/api.md\n - \u914d\u7f6e\u9879: reference/configuration.md\n - \u547d\u4ee4\u884c: reference/cli.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3213","title":"3.2.1.3 \u6743\u91cd\u8bbe\u7f6e","text":"\u4f7f\u7528\u6587\u4ef6\u540d\u524d\u7f00\u63a7\u5236\u987a\u5e8f\uff1a
YAMLdocs/\n\u251c\u2500\u2500 01_introduction.md\n\u251c\u2500\u2500 02_installation.md\n\u251c\u2500\u2500 03_configuration.md\n\u2514\u2500\u2500 04_usage.md\n\n# mkdocs.yml\nnav:\n - \u4ecb\u7ecd: 01_introduction.md\n - \u5b89\u88c5: 02_installation.md\n - \u914d\u7f6e: 03_configuration.md\n - \u4f7f\u7528: 04_usage.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#322","title":"3.2.2 \u6587\u4ef6\u7ec4\u7ec7","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3221","title":"3.2.2.1 \u6587\u4ef6\u547d\u540d\u89c4\u8303","text":"\u63a8\u8350\u7684\u547d\u540d\u89c4\u8303\uff1a
Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u9996\u9875\n\u251c\u2500\u2500 getting-started.md # \u77ed\u6a2a\u7ebf\u5206\u9694\n\u251c\u2500\u2500 advanced_usage.md # \u4e0b\u5212\u7ebf\u5206\u9694\uff08\u53ef\u9009\uff09\n\u2514\u2500\u2500 troubleshooting.md # \u5168\u5c0f\u5199\n
\u6587\u4ef6\u547d\u540d\u5efa\u8bae\uff1a
\u6807\u51c6\u76ee\u5f55\u7ed3\u6784\uff1a
Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u7f51\u7ad9\u9996\u9875\n\u251c\u2500\u2500 getting-started/ # \u5165\u95e8\u6307\u5357\n\u2502 \u251c\u2500\u2500 index.md # \u5206\u7c7b\u9996\u9875\n\u2502 \u251c\u2500\u2500 installation.md # \u5b89\u88c5\u8bf4\u660e\n\u2502 \u2514\u2500\u2500 configuration.md # \u914d\u7f6e\u8bf4\u660e\n\u251c\u2500\u2500 user-guide/ # \u7528\u6237\u6307\u5357\n\u2502 \u251c\u2500\u2500 index.md # \u6307\u5357\u9996\u9875\n\u2502 \u251c\u2500\u2500 basic-usage.md # \u57fa\u7840\u7528\u6cd5\n\u2502 \u2514\u2500\u2500 advanced.md # \u9ad8\u7ea7\u7279\u6027\n\u2514\u2500\u2500 api/ # API\u6587\u6863\n \u251c\u2500\u2500 index.md # API\u6982\u89c8\n \u251c\u2500\u2500 endpoints.md # \u63a5\u53e3\u5217\u8868\n \u2514\u2500\u2500 authentication.md # \u8ba4\u8bc1\u8bf4\u660e\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3223","title":"3.2.2.3 \u7d22\u5f15\u6587\u4ef6\u4f7f\u7528","text":"\u6bcf\u4e2a\u76ee\u5f55\u7684 index. md \u793a\u4f8b\uff1a
Markdown# \u7528\u6237\u6307\u5357\n\n\u8fd9\u662f\u7528\u6237\u6307\u5357\u7684\u4e3b\u9875\u9762\uff0c\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9\uff1a\n\n## \u5feb\u901f\u5bfc\u822a\n\n- [\u57fa\u7840\u7528\u6cd5] (basic-usage.md) - \u5165\u95e8\u5fc5\u8bfb\n- [\u9ad8\u7ea7\u7279\u6027] (advanced.md) - \u6df1\u5165\u4e86\u89e3\n\n## \u672c\u8282\u5185\u5bb9\n\n\u6b64\u90e8\u5206\u5c06\u5e2e\u52a9\u60a8\u4e86\u89e3\u4ea7\u54c1\u7684\u6838\u5fc3\u529f\u80fd\u548c\u4f7f\u7528\u65b9\u6cd5...\n
\u5bf9\u5e94\u7684\u5bfc\u822a\u914d\u7f6e\uff1a
YAMLnav:\n - \u7528\u6237\u6307\u5357:\n - \u6982\u8ff0: user-guide/index.md\n - \u57fa\u7840\u7528\u6cd5: user-guide/basic-usage.md\n - \u9ad8\u7ea7\u7279\u6027: user-guide/advanced.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#323","title":"3.2.3 \u591a\u7ea7\u76ee\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3231","title":"3.2.3.1 \u5c42\u7ea7\u7ed3\u6784\u8bbe\u8ba1","text":"\u590d\u6742\u7684\u591a\u7ea7\u76ee\u5f55\u793a\u4f8b\uff1a
YAMLnav:\n - \u9996\u9875: index.md\n - \u5165\u95e8\u6307\u5357:\n - \u6982\u8ff0: getting-started/index.md\n - \u57fa\u7840:\n - \u5b89\u88c5: getting-started/basics/installation.md\n - \u914d\u7f6e: getting-started/basics/configuration.md\n - \u8fdb\u9636:\n - \u81ea\u5b9a\u4e49: getting-started/advanced/customization.md\n - \u4f18\u5316: getting-started/advanced/optimization.md\n - \u5f00\u53d1\u6587\u6863:\n - \u6982\u8ff0: development/index.md\n - API:\n - \u8ba4\u8bc1: development/api/authentication.md\n - \u63a5\u53e3: development/api/endpoints.md\n - SDK:\n - Python: development/sdk/python.md\n - JavaScript: development/sdk/javascript.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3232","title":"3.2.3.2 \u5bfc\u822a\u6df1\u5ea6\u63a7\u5236","text":"YAMLtheme:\n name: material\n features:\n - navigation.sections # \u663e\u793a\u7ae0\u8282\n - navigation.expand # \u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u4f7f\u7528\u76ee\u5f55\u7d22\u5f15\n - toc.integrate # \u96c6\u6210\u76ee\u5f55\n\nmarkdown_extensions:\n - toc:\n permalink: true\n toc_depth: 3 # \u63a7\u5236\u76ee\u5f55\u6df1\u5ea6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3233","title":"3.2.3.3 \u6298\u53e0\u914d\u7f6e","text":"Material \u4e3b\u9898\u7684\u6298\u53e0\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - navigation.sections # \u663e\u793a\u5206\u533a\n - navigation.expand # \u9ed8\u8ba4\u5c55\u5f00\n - navigation.indexes # \u4f7f\u7528\u7d22\u5f15\u9875\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n\n # \u5bfc\u822a\u680f\u8bbe\u7f6e\n nav_style: dark # \u5bfc\u822a\u680f\u6837\u5f0f\n collapse_navigation: true # \u6298\u53e0\u5bfc\u822a\n sticky_navigation: true # \u56fa\u5b9a\u5bfc\u822a\n
"},{"location":"Tools/Blog/Mkdocs_Material/#324","title":"3.2.4 \u5bfc\u822a\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5","text":"\u7ed3\u6784\u8bbe\u8ba1\u539f\u5219\uff1a - \u4fdd\u6301\u5c42\u7ea7\u6e05\u6670 - \u63a7\u5236\u5bfc\u822a\u6df1\u5ea6\uff08\u5efa\u8bae\u4e0d\u8d85\u8fc7 3 \u5c42\uff09 - \u76f8\u5173\u5185\u5bb9\u5206\u7ec4 - \u4f7f\u7528\u76f4\u89c2\u7684\u547d\u540d
\u6587\u4ef6\u7ec4\u7ec7\uff1a - \u4f7f\u7528\u6709\u610f\u4e49\u7684\u76ee\u5f55\u540d - \u4fdd\u6301\u6587\u4ef6\u7ed3\u6784\u6574\u6d01 - \u5408\u7406\u4f7f\u7528\u7d22\u5f15\u6587\u4ef6 - \u9075\u5faa\u4e00\u81f4\u7684\u547d\u540d\u89c4\u8303
\u7528\u6237\u4f53\u9a8c\uff1a - \u63d0\u4f9b\u6e05\u6670\u7684\u5bfc\u822a\u8def\u5f84 - \u6dfb\u52a0\u5408\u9002\u7684\u63cf\u8ff0 - \u8003\u8651\u79fb\u52a8\u7aef\u663e\u793a - \u4f18\u5316\u5bfc\u822a\u54cd\u5e94\u901f\u5ea6
\u7ef4\u62a4\u5efa\u8bae\uff1a - \u5b9a\u671f\u68c0\u67e5\u6b7b\u94fe\u63a5 - \u66f4\u65b0\u5bfc\u822a\u7ed3\u6784 - \u4fdd\u6301\u6587\u6863\u540c\u6b65 - \u6536\u96c6\u7528\u6237\u53cd\u9988
nav:\n - \u53ef\u89c1\u9875\u9762: visible.md\n - !hidden \u9690\u85cf\u9875\u9762: hidden.md\n
nav:\n - \u6587\u6863: index.md\n - GitHub: https://github.com/your/repo\n - \u793e\u533a: \n - \u8bba\u575b: https://forum.example.com\n - \u535a\u5ba2: https://blog.example.com\n
nav:\n - \u5f00\u59cb: \n - \u6982\u8ff0: getting-started/index.md\n - \u5feb\u901f\u5165\u95e8: getting-started/quickstart.md\n - \u540c\u4e00\u6587\u4ef6\u4e0d\u540c\u5165\u53e3: !alias getting-started/quickstart.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#33-markdown","title":"3.3 Markdown \u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#331","title":"3.3.1 \u57fa\u7840\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3311-meta","title":"3.3.1.1 meta \u6269\u5c55","text":"\u652f\u6301\u5728 Markdown \u6587\u4ef6\u5934\u90e8\u6dfb\u52a0\u5143\u6570\u636e\uff1a
YAML# mkdocs.yml \u914d\u7f6e\nmarkdown_extensions:\n - meta\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown---\ntitle: \u6211\u7684\u9875\u9762\u6807\u9898\ndescription: \u9875\u9762\u63cf\u8ff0\nauthor: \u4f5c\u8005\u540d\ndate: 2024-01-01\n---\n\n# \u6b63\u6587\u5185\u5bb9\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3312-toc","title":"3.3.1.2 toc \u6269\u5c55","text":"\u81ea\u52a8\u751f\u6210\u76ee\u5f55\uff1a
YAMLmarkdown_extensions:\n - toc:\n permalink: true # \u6dfb\u52a0\u6bb5\u843d\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n separator: \"_\" # \u6807\u9898\u951a\u70b9\u5206\u9694\u7b26\n title: \"\u76ee\u5f55\" # \u76ee\u5f55\u6807\u9898\n slugify: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower} # URL \u8f6c\u6362\u89c4\u5219\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown[TOC]\n\n# \u4e00\u7ea7\u6807\u9898\n## \u4e8c\u7ea7\u6807\u9898\n### \u4e09\u7ea7\u6807\u9898\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3313-tables","title":"3.3.1.3 tables \u6269\u5c55","text":"\u589e\u5f3a\u7684\u8868\u683c\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - tables\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown| \u529f\u80fd | \u57fa\u7840\u7248 | \u4e13\u4e1a\u7248 |\n|-----|:------:|-------:|\n| \u529f\u80fdA | \u2713 | \u2713 |\n| \u529f\u80fdB | \u2717 | \u2713 |\n| \u529f\u80fdC | \u2717 | \u2713 |\n\n: \u8868\u683c\u6807\u9898 {.class-name}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#332-pymdown-extensions","title":"3.3.2 PyMdown Extensions","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3321-superfences","title":"3.3.2.1 superfences \u914d\u7f6e","text":"\u589e\u5f3a\u7684\u4ee3\u7801\u5757\u529f\u80fd\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_div_format\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown```python title=\"example.py\" linenums=\"1\" hl_lines=\"2 3\"\ndef hello_world():\n message = \"Hello, World!\"\n print(message)\n return message\n```\n\n```mermaid\ngraph LR\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B --> |Yes| C[\u6267\u884c]\n B --> |No| D[\u8df3\u8fc7]\n```\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3322-emoji","title":"3.3.2.2 emoji \u652f\u6301","text":"\u6dfb\u52a0\u8868\u60c5\u7b26\u53f7\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - pymdownx.emoji:\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown:smile: :heart: :thumbsup:\n\n:fontawesome-brands-github: GitHub\n:material-account: \u7528\u6237\n:octicons-repo-16: \u4ed3\u5e93\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3323-tasklist","title":"3.3.2.3 tasklist \u529f\u80fd","text":"\u4efb\u52a1\u5217\u8868\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tasklist:\n custom_checkbox: true # \u81ea\u5b9a\u4e49\u590d\u9009\u6846\u6837\u5f0f\n clickable_checkbox: true # \u53ef\u70b9\u51fb\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown- [x] \u5df2\u5b8c\u6210\u4efb\u52a1\n- [ ] \u672a\u5b8c\u6210\u4efb\u52a1\n - [x] \u5b50\u4efb\u52a1 1\n - [ ] \u5b50\u4efb\u52a1 2\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3324-pymdown","title":"3.3.2.4 \u5176\u4ed6\u5e38\u7528 PyMdown \u6269\u5c55","text":"YAMLmarkdown_extensions:\n - pymdownx.highlight # \u4ee3\u7801\u9ad8\u4eae\n - pymdownx.inlinehilite # \u884c\u5185\u4ee3\u7801\u9ad8\u4eae\n - pymdownx.snippets # \u4ee3\u7801\u7247\u6bb5\n - pymdownx.magiclink # \u81ea\u52a8\u94fe\u63a5\n - pymdownx.mark # ==\u6807\u8bb0==\n - pymdownx.critic # \u7f16\u8f91\u6807\u8bb0\n - pymdownx.tilde # \u5220\u9664\u7ebf\n - pymdownx.caret # \u4e0a\u6807\n - pymdownx.keys # \u952e\u76d8\u6309\u952e\n - pymdownx.tabbed # \u6807\u7b7e\u9875\n
"},{"location":"Tools/Blog/Mkdocs_Material/#333","title":"3.3.3 \u81ea\u5b9a\u4e49\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3331","title":"3.3.3.1 \u6269\u5c55\u5f00\u53d1\u57fa\u7840","text":"\u521b\u5efa\u81ea\u5b9a\u4e49\u6269\u5c55\uff1a
Python# custom_extension.py\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\nclass CustomPreprocessor(Preprocessor):\n def run(self, lines):\n new_lines = []\n for line in lines:\n new_lines.append(line.replace('[[', '**').replace(']]', '**'))\n return new_lines\n\nclass CustomExtension(Extension):\n def extendMarkdown(self, md):\n md.preprocessors.register(CustomPreprocessor(md), 'custom_preprocessor', 175)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#34","title":"3.4 \u5e38\u7528\u6269\u5c55\u793a\u4f8b","text":"from markdown.extensions import Extension\nfrom markdown.treeprocessors import Treeprocessor\n\nclass CustomAttributesTreeprocessor(Treeprocessor):\n def run(self, root):\n for elem in root.iter():\n if 'class' in elem.attrib:\n elem.set('data-custom', 'value')\n\nclass CustomAttributesExtension(Extension):\n def extendMarkdown(self, md):\n md.treeprocessors.register(\n CustomAttributesTreeprocessor(md), 'custom_attributes', 15\n )\n
from markdown.extensions import Extension\nfrom markdown.blockprocessors import BlockProcessor\nimport re\n\nclass CustomContainerProcessor(BlockProcessor):\n RE = re.compile(r':{3,}\\ *(warning|note|tip)\\ *')\n\n def run(self, parent, blocks):\n block = blocks.pop(0)\n m = self.RE.match(block)\n\n if m:\n container_type = m.group(1)\n div = etree.SubElement(parent, 'div')\n div.set('class', f'custom-container {container_type}')\n\n # \u5904\u7406\u5bb9\u5668\u5185\u5bb9\n self.parser.parseChunk(div, block[m.end():])\n\nclass CustomContainerExtension(Extension):\n def extendMarkdown(self, md):\n md.parser.blockprocessors.register(\n CustomContainerProcessor(md.parser), 'custom_container', 175\n )\n
"},{"location":"Tools/Blog/Mkdocs_Material/#341","title":"3.4.1 \u6269\u5c55\u914d\u7f6e\u65b9\u6cd5","text":"\u5728 mkdocs.yml
\u4e2d\u914d\u7f6e\u81ea\u5b9a\u4e49\u6269\u5c55\uff1a
markdown_extensions:\n - custom_extension:\n option1: value1\n option2: value2\n\nextra_css:\n - css/custom_extension.css\n\nextra_javascript:\n - js/custom_extension.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#342","title":"3.4.2 \u6269\u5c55\u7ec4\u5408\u63a8\u8350","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3421","title":"3.4.2.1 \u57fa\u7840\u6587\u6863\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n - meta\n - toc:\n permalink: true\n - tables\n - attr_list\n - def_list\n - footnotes\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3422","title":"3.4.2.2 \u589e\u5f3a\u529f\u80fd\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_div_format\n - pymdownx.highlight:\n anchor_linenums: true\n - pymdownx.inlinehilite\n - pymdownx.snippets\n - pymdownx.tasklist:\n custom_checkbox: true\n - pymdownx.emoji:\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n
"},{"location":"Tools/Blog/Mkdocs_Material/#343","title":"3.4.3 \u5b8c\u6574\u63a8\u8350\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n # Python Markdown\n - meta\n - toc:\n permalink: true\n toc_depth: 4\n - tables\n - attr_list\n - def_list\n - md_in_html\n - footnotes\n\n # Python Markdown Extensions\n - pymdownx.superfences\n - pymdownx.highlight\n - pymdownx.inlinehilite\n - pymdownx.snippets\n - pymdownx.tasklist\n - pymdownx.emoji\n - pymdownx.mark\n - pymdownx.critic\n - pymdownx.keys\n - pymdownx.tilde\n - pymdownx.caret\n - pymdownx.details\n - pymdownx.magiclink\n - pymdownx.tabbed:\n alternate_style: true\n\n # \u81ea\u5b9a\u4e49\u6269\u5c55\n - custom_extension:\n custom_option: value\n
"},{"location":"Tools/Blog/Mkdocs_Material/#344","title":"3.4.4 \u4f7f\u7528\u5efa\u8bae","text":"\u6027\u80fd\u8003\u8651\uff1a - \u53ea\u542f\u7528\u9700\u8981\u7684\u6269\u5c55 - \u6ce8\u610f\u6269\u5c55\u4e4b\u95f4\u7684\u4f9d\u8d56\u5173\u7cfb - \u63a7\u5236\u6269\u5c55\u6570\u91cf
\u517c\u5bb9\u6027\uff1a - \u6d4b\u8bd5\u6269\u5c55\u7ec4\u5408 - \u68c0\u67e5\u79fb\u52a8\u7aef\u663e\u793a - \u9a8c\u8bc1\u4e0d\u540c\u6d4f\u89c8\u5668
\u7ef4\u62a4\u5efa\u8bae\uff1a - \u8bb0\u5f55\u6269\u5c55\u914d\u7f6e - \u4fdd\u6301\u7248\u672c\u66f4\u65b0 - \u76d1\u63a7\u6027\u80fd\u5f71\u54cd
\u901a\u8fc7 pip \u5b89\u88c5\u63d2\u4ef6\uff1a
Bash# \u5b89\u88c5\u5355\u4e2a\u63d2\u4ef6\npip install mkdocs-git-revision-date-localized-plugin\n\n# \u5b89\u88c5\u591a\u4e2a\u63d2\u4ef6\npip install mkdocs-minify-plugin mkdocs-git-authors-plugin\n
\u57fa\u7840\u63d2\u4ef6\u914d\u7f6e\uff1a
YAML# mkdocs.yml\nplugins:\n - search # \u9ed8\u8ba4\u63d2\u4ef6\n - git-revision-date-localized:\n enable_creation_date: true\n - minify:\n minify_html: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3512","title":"3.5.1.2 \u914d\u7f6e\u8bed\u6cd5","text":"\u63d2\u4ef6\u914d\u7f6e\u7684\u51e0\u79cd\u65b9\u5f0f\uff1a
YAML# 1. \u7b80\u5355\u542f\u7528\u63d2\u4ef6\uff08\u4f7f\u7528\u9ed8\u8ba4\u914d\u7f6e\uff09\nplugins:\n - search\n - tags\n\n# 2. \u7981\u7528\u9ed8\u8ba4\u63d2\u4ef6\nplugins:\n - search: false\n\n# 3. \u5e26\u914d\u7f6e\u7684\u63d2\u4ef6\nplugins:\n - search:\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+'\n\n# 4. \u591a\u5b9e\u4f8b\u63d2\u4ef6\nplugins:\n - search:\n name: search_1\n config: value\n - search:\n name: search_2\n config: value\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3513","title":"3.5.1.3 \u4f18\u5148\u7ea7\u63a7\u5236","text":"\u63d2\u4ef6\u6267\u884c\u987a\u5e8f\u63a7\u5236\uff1a
YAMLplugins:\n - search\n - git-revision-date-localized:\n priority: 80\n - minify:\n priority: 90\n - tags:\n priority: 70\n
"},{"location":"Tools/Blog/Mkdocs_Material/#352","title":"3.5.2 \u5e38\u7528\u63d2\u4ef6\u4ecb\u7ecd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3521","title":"3.5.2.1 \u5b98\u65b9\u63d2\u4ef6","text":"plugins:\n - search:\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+'\n min_search_length: 2\n prebuild_index: true\n indexing:\n - full_sections: false\n - headings: true\n - content: true\n
plugins:\n - tags:\n tags_file: tags.md\n tags_extra_files:\n cloud: cloud_tags.md\n list: tag_list.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3522","title":"3.5.2.2 \u793e\u533a\u63d2\u4ef6\u63a8\u8350","text":"plugins:\n - git-revision-date-localized:\n type: timeago\n enable_creation_date: true\n exclude:\n - index.md\n timezone: Asia/Shanghai\n locale: zh\n
plugins:\n - minify:\n minify_html: true\n minify_js: true\n minify_css: true\n htmlmin_opts:\n remove_comments: true\n
plugins:\n - social:\n cards: true\n cards_color:\n fill: \"#0FF1CE\"\n text: \"#FFFFFF\"\n
plugins:\n - macros:\n module_name: macros\n include_dir: include\n include_yaml:\n - variables.yml\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3523","title":"3.5.2.3 \u5b9e\u7528\u63d2\u4ef6\u96c6\u5408","text":"YAMLplugins:\n # \u6838\u5fc3\u529f\u80fd\n - search\n - tags\n\n # \u7248\u672c\u63a7\u5236\n - git-revision-date-localized\n - git-authors\n\n # \u6027\u80fd\u4f18\u5316\n - minify\n - optimize\n\n # \u5185\u5bb9\u589e\u5f3a\n - social\n - macros\n - blogging\n\n # \u591a\u8bed\u8a00\u652f\u6301\n - i18n\n - translations\n\n # \u56fe\u7247\u5904\u7406\n - glightbox\n - img2fig\n\n # \u7edf\u8ba1\u5206\u6790\n - statistics\n - pdf-export\n
"},{"location":"Tools/Blog/Mkdocs_Material/#353","title":"3.5.3 \u63d2\u4ef6\u7ec4\u5408\u4f7f\u7528","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3531","title":"3.5.3.1 \u57fa\u7840\u7ec4\u5408\u65b9\u6848","text":"\u9002\u5408\u4e00\u822c\u6587\u6863\u9879\u76ee\uff1a
YAMLplugins:\n - search:\n lang: zh\n separator: '[\\s\\-\\.]+'\n\n - git-revision-date-localized:\n enable_creation_date: true\n type: date\n\n - minify:\n minify_html: true\n\n - glightbox:\n touchNavigation: true\n loop: false\n effect: zoom\n width: 100%\n height: auto\n zoomable: true\n draggable: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3532","title":"3.5.3.2 \u535a\u5ba2\u7f51\u7ad9\u65b9\u6848","text":"\u9002\u5408\u535a\u5ba2\u7c7b\u7f51\u7ad9\uff1a
YAMLplugins:\n - blog:\n blog_dir: blog\n post_url_format: \"{slug}\"\n post_excerpt: optional\n\n - social:\n cards: true\n cards_dir: assets/social\n\n - tags:\n tags_file: tags.md\n\n - rss:\n abstract_chars_count: 160\n date_from_meta: true\n\n - statistics:\n page_check: true\n page_count: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3533","title":"3.5.3.3 \u6280\u672f\u6587\u6863\u65b9\u6848","text":"\u9002\u5408\u5927\u578b\u6280\u672f\u6587\u6863\uff1a
YAMLplugins:\n - search:\n separator: '[\\s\\-\\.]+'\n min_search_length: 2\n lang:\n - en\n - zh\n prebuild_index: true\n\n - git-revision-date-localized:\n type: timeago\n enable_creation_date: true\n\n - minify:\n minify_html: true\n minify_js: true\n minify_css: true\n\n - macros:\n module_name: includes.macros\n include_yaml:\n - includes/variables.yml\n\n - pdf-export:\n combined: true\n combined_output_path: pdf/document.pdf\n
"},{"location":"Tools/Blog/Mkdocs_Material/#354","title":"3.5.4 \u6027\u80fd\u4f18\u5316\u5efa\u8bae","text":"\u63d2\u4ef6\u9009\u62e9\uff1a - \u53ea\u542f\u7528\u5fc5\u8981\u7684\u63d2\u4ef6 - \u907f\u514d\u529f\u80fd\u91cd\u590d\u7684\u63d2\u4ef6 - \u6ce8\u610f\u63d2\u4ef6\u95f4\u7684\u4f9d\u8d56\u5173\u7cfb
\u914d\u7f6e\u4f18\u5316\uff1a
plugins:\n - search:\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n - minify:\n cache: true # \u542f\u7528\u7f13\u5b58\n cache_dir: .cache # \u7f13\u5b58\u76ee\u5f55\n - optimize: # \u8d44\u6e90\u4f18\u5316\n cache: true\n
plugins:\n # \u5e76\u884c\u5904\u7406\u63d2\u4ef6\n - parallel:\n workers: 4\n # \u7f13\u5b58\u63d2\u4ef6\n - cache:\n enabled: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4-material","title":"4 Material \u4e3b\u9898\u5b8c\u5168\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#41","title":"4.1 \u57fa\u7840\u5916\u89c2","text":""},{"location":"Tools/Blog/Mkdocs_Material/#411","title":"4.1.1 \u914d\u8272\u65b9\u6848","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4111","title":"4.1.1.1 \u9884\u8bbe\u4e3b\u9898\u8272","text":"Material \u4e3b\u9898\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u9884\u8bbe\u989c\u8272\uff1a
YAMLtheme:\n name: material\n palette:\n primary: indigo # \u4e3b\u8272\u8c03\n accent: pink # \u5f3a\u8c03\u8272\n\n# \u53ef\u7528\u7684\u4e3b\u9898\u8272\uff1a\n# red, pink, purple, deep purple, indigo, blue, light blue, \n# cyan, teal, green, light green, lime, yellow, amber, \n# orange, deep orange, brown, grey, blue grey\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4112","title":"4.1.1.2 \u81ea\u5b9a\u4e49\u914d\u8272","text":"\u5b8c\u6574\u7684\u81ea\u5b9a\u4e49\u914d\u8272\u914d\u7f6e\uff1a
YAMLtheme:\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4113-css","title":"4.1.1.3 \u81ea\u5b9a\u4e49 CSS \u53d8\u91cf","text":"\u521b\u5efa docs/stylesheets/extra.css
\uff1a
:root {\n --md-primary-fg-color: #2196f3;\n --md-primary-fg-color--light: #64b5f6;\n --md-primary-fg-color--dark: #1976d2;\n --md-accent-fg-color: #2196f3;\n}\n\n[data-md-color-scheme=\"slate\"] {\n --md-primary-fg-color: #90caf9;\n --md-primary-fg-color--light: #e3f2fd;\n --md-primary-fg-color--dark: #42a5f5;\n}\n
\u5728 mkdocs.yml
\u4e2d\u5f15\u5165\uff1a
extra_css:\n - stylesheets/extra.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#412","title":"4.1.2 \u4e3b\u9898\u5207\u6362","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4121","title":"4.1.2.1 \u57fa\u7840\u5207\u6362\u914d\u7f6e","text":"YAMLtheme:\n name: material\n palette:\n # \u914d\u7f6e\u5207\u6362\u6309\u94ae\n - scheme: default\n toggle:\n icon: material/brightness-7 \n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n primary: indigo\n accent: indigo\n\n - scheme: slate\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n primary: indigo\n accent: indigo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4122","title":"4.1.2.2 \u9ad8\u7ea7\u5207\u6362\u529f\u80fd","text":"\u6dfb\u52a0\u81ea\u5b9a\u4e49\u5207\u6362\u903b\u8f91\uff1a
YAMLextra_javascript:\n - javascripts/theme-switch.js\n
theme-switch.js
\u5185\u5bb9\uff1a
document.addEventListener('DOMContentLoaded', function() {\n // \u83b7\u53d6\u7cfb\u7edf\u4e3b\u9898\u504f\u597d\n const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');\n\n // \u76d1\u542c\u7cfb\u7edf\u4e3b\u9898\u53d8\u5316\n prefersDark.addListener((e) => {\n const theme = e.matches ? 'slate' : 'default';\n document.body.setAttribute('data-md-color-scheme', theme);\n });\n\n // \u521d\u59cb\u5316\u4e3b\u9898\n const theme = prefersDark.matches ? 'slate' : 'default';\n document.body.setAttribute('data-md-color-scheme', theme);\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#413","title":"4.1.3 \u56fe\u6807\u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4131","title":"4.1.3.1 \u7f51\u7ad9\u56fe\u6807","text":"\u914d\u7f6e\u7f51\u7ad9\u56fe\u6807\u548c Logo\uff1a
YAMLtheme:\n icon:\n logo: material/book-open-page-variant # \u7f51\u7ad9 Logo\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n\n favicon: assets/favicon.png # \u7f51\u7ad9\u56fe\u6807\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4132","title":"4.1.3.2 \u529f\u80fd\u56fe\u6807","text":"\u4e3a\u4e0d\u540c\u529f\u80fd\u914d\u7f6e\u56fe\u6807\uff1a
YAMLtheme:\n icon:\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n edit: material/pencil # \u7f16\u8f91\u56fe\u6807\n view: material/eye # \u67e5\u770b\u56fe\u6807\n admonition:\n note: octicons/tag-16 # \u63d0\u793a\u6846\u56fe\u6807\n abstract: octicons/checklist-16\n info: octicons/info-16\n tip: octicons/squirrel-16\n success: octicons/check-16\n question: octicons/question-16\n warning: octicons/alert-16\n failure: octicons/x-circle-16\n danger: octicons/zap-16\n bug: octicons/bug-16\n example: octicons/beaker-16\n quote: octicons/quote-16\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4133-svg","title":"4.1.3.3 \u81ea\u5b9a\u4e49 SVG \u56fe\u6807","text":"\u6dfb\u52a0\u81ea\u5b9a\u4e49 SVG \u56fe\u6807\uff1a
.icons
\u76ee\u5f55\uff1a.\n\u251c\u2500 .icons/\n\u2502 \u2514\u2500 custom/\n\u2502 \u2514\u2500 logo.svg\n\u2514\u2500 mkdocs.yml\n
theme:\n icon:\n logo: custom/logo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#414-logo","title":"4.1.4 Logo \u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4141-logo","title":"4.1.4.1 \u57fa\u7840 Logo \u914d\u7f6e","text":"YAMLtheme:\n logo: assets/logo.svg # Logo \u56fe\u7247\n icon:\n logo: material/book # \u6216\u4f7f\u7528\u56fe\u6807\u4f5c\u4e3a Logo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4142-logo","title":"4.1.4.2 \u54cd\u5e94\u5f0f Logo","text":"\u521b\u5efa\u54cd\u5e94\u5f0f Logo\uff1a
YAMLtheme:\n logo: assets/logo.svg\nextra_css:\n - stylesheets/logo.css\n
logo.css
\u5185\u5bb9\uff1a
/* \u9ed8\u8ba4 Logo */\n.md-logo img {\n width: 40px;\n height: 40px;\n}\n\n/* \u79fb\u52a8\u7aef Logo */\n@media screen and (max-width: 76.1875em) {\n .md-logo img {\n width: 32px;\n height: 32px;\n }\n}\n\n/* \u6697\u8272\u4e3b\u9898 Logo */\n[data-md-color-scheme=\"slate\"] .md-logo img {\n filter: invert(1);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4143-logo","title":"4.1.4.3 Logo \u52a8\u753b\u6548\u679c","text":"\u6dfb\u52a0 Logo \u52a8\u753b\uff1a
CSS.md-logo img {\n transition: transform 0.3s ease;\n}\n\n.md-logo img:hover {\n transform: scale(1.1);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#415","title":"4.1.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n\n # \u8c03\u8272\u677f\u914d\u7f6e\n palette:\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: blue\n accent: blue\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n\n # \u56fe\u6807\u914d\u7f6e\n icon:\n logo: material/book-open-page-variant\n repo: fontawesome/brands/github\n edit: material/pencil\n view: material/eye\n\n # Logo \u914d\u7f6e\n logo: assets/logo.svg\n favicon: assets/favicon.png\n\n# \u989d\u5916\u6837\u5f0f\nextra_css:\n - stylesheets/extra.css\n - stylesheets/logo.css\n\n# \u989d\u5916\u811a\u672c\nextra_javascript:\n - javascripts/theme-switch.js\n\n# \u4e3b\u9898\u7279\u6027\nfeatures:\n - navigation.instant\n - navigation.tracking\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n - navigation.top\n - toc.integrate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#42","title":"4.2 \u5bfc\u822a\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#421","title":"4.2.1 \u9876\u90e8\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4211","title":"4.2.1.1 \u5bfc\u822a\u680f\u6837\u5f0f","text":"\u57fa\u7840\u5bfc\u822a\u680f\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - navigation.tabs # \u542f\u7528\u6807\u7b7e\u5f0f\u5bfc\u822a\n - navigation.sections # \u663e\u793a\u7ae0\u8282\u5bfc\u822a\n - navigation.expand # \u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u7ae0\u8282\u7d22\u5f15\u9875\n
\u81ea\u5b9a\u4e49\u5bfc\u822a\u680f\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/extra.css */\n\n/* \u5bfc\u822a\u680f\u80cc\u666f */\n.md-header {\n background-color: #2196f3;\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n}\n\n/* \u5bfc\u822a\u9879\u6837\u5f0f */\n.md-tabs__link {\n font-size: .8rem;\n margin-top: .4rem;\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-tabs__link--active {\n font-weight: bold;\n border-bottom: 2px solid currentColor;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4212","title":"4.2.1.2 \u56fa\u5b9a\u5bfc\u822a\u680f","text":"\u542f\u7528\u56fa\u5b9a\u5bfc\u822a\uff1a
YAMLtheme:\n features:\n - header.autohide # \u81ea\u52a8\u9690\u85cf\n - navigation.sticky # \u56fa\u5b9a\u5bfc\u822a\n
\u81ea\u5b9a\u4e49\u56fa\u5b9a\u5bfc\u822a\u884c\u4e3a\uff1a
CSS/* \u56fa\u5b9a\u5bfc\u822a\u680f\u6837\u5f0f */\n.md-header--sticky {\n backdrop-filter: blur(8px);\n background-color: rgba(255,255,255,.8);\n}\n\n/* \u6697\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"slate\"] .md-header--sticky {\n background-color: rgba(0,0,0,.8);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4213","title":"4.2.1.3 \u54cd\u5e94\u5f0f\u5bfc\u822a","text":"\u54cd\u5e94\u5f0f\u914d\u7f6e\uff1a
YAMLtheme:\n features:\n - navigation.instant # \u5373\u65f6\u52a0\u8f7d\n - navigation.tracking # \u6eda\u52a8\u8ddf\u8e2a\n
\u54cd\u5e94\u5f0f\u6837\u5f0f\u8c03\u6574\uff1a
CSS/* \u79fb\u52a8\u7aef\u5bfc\u822a */\n@media screen and (max-width: 76.1875em) {\n .md-nav__title {\n font-size: .9rem;\n padding: 0.5rem 0.8rem;\n }\n\n .md-nav__item {\n padding: 0.2rem 0.8rem;\n }\n}\n\n/* \u5e73\u677f\u5bfc\u822a */\n@media screen and (min-width: 76.25em) {\n .md-nav__link {\n padding: 0.2rem 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#422","title":"4.2.2 \u6807\u7b7e\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4221","title":"4.2.2.1 \u6807\u7b7e\u9875\u914d\u7f6e","text":"\u542f\u7528\u6807\u7b7e\u5bfc\u822a\uff1a
YAMLtheme:\n features:\n - navigation.tabs\n - navigation.tabs.sticky # \u56fa\u5b9a\u6807\u7b7e\n
\u6807\u7b7e\u9875\u7ed3\u6784\uff1a
YAMLnav:\n - Home: index.md\n - Guide:\n - guide/index.md\n - Installation: guide/installation.md\n - Configuration: guide/configuration.md\n - API:\n - api/index.md\n - Reference: api/reference.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4222","title":"4.2.2.2 \u6807\u7b7e\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u6807\u7b7e\u6837\u5f0f\uff1a
CSS/* \u6807\u7b7e\u5bb9\u5668 */\n.md-tabs {\n background-color: var(--md-primary-fg-color--dark);\n}\n\n/* \u6807\u7b7e\u9879 */\n.md-tabs__item {\n padding: 0 1rem;\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-tabs__item:hover {\n background-color: rgba(255,255,255,.1);\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-tabs__item--active {\n font-weight: bold;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4223","title":"4.2.2.3 \u6807\u7b7e\u4ea4\u4e92","text":"\u6dfb\u52a0\u6807\u7b7e\u4ea4\u4e92\u6548\u679c\uff1a
JavaScript// docs/javascripts/tabs.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6807\u7b7e\u70b9\u51fb\u6548\u679c\n const tabs = document.querySelectorAll('.md-tabs__item');\n tabs.forEach(tab => {\n tab.addEventListener('click', () => {\n // \u6dfb\u52a0\u70b9\u51fb\u6ce2\u7eb9\u6548\u679c\n const ripple = document.createElement('div');\n ripple.classList.add('md-tabs__ripple');\n tab.appendChild(ripple);\n\n // \u79fb\u9664\u6ce2\u7eb9\u6548\u679c\n setTimeout(() => ripple.remove(), 1000);\n });\n });\n});\n
\u5bf9\u5e94\u7684 CSS\uff1a
CSS/* \u6ce2\u7eb9\u6548\u679c */\n.md-tabs__ripple {\n position: absolute;\n background: rgba(255,255,255,.3);\n border-radius: 50%;\n transform: scale(0);\n animation: ripple 0.6s linear;\n}\n\n@keyframes ripple {\n to {\n transform: scale(4);\n opacity: 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#423","title":"4.2.3 \u76ee\u5f55\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4231","title":"4.2.3.1 \u76ee\u5f55\u5c42\u7ea7","text":"\u914d\u7f6e\u76ee\u5f55\u5c42\u7ea7\uff1a
YAMLtheme:\n features:\n - toc.integrate # \u96c6\u6210\u76ee\u5f55\n - toc.follow # \u76ee\u5f55\u8ddf\u968f\n\nmarkdown_extensions:\n - toc:\n permalink: true # \u6c38\u4e45\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n title: \u76ee\u5f55 # \u76ee\u5f55\u6807\u9898\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4232","title":"4.2.3.2 \u76ee\u5f55\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u76ee\u5f55\u6837\u5f0f\uff1a
CSS/* \u76ee\u5f55\u5bb9\u5668 */\n.md-toc {\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-radius: 4px;\n}\n\n/* \u76ee\u5f55\u6807\u9898 */\n.md-toc__title {\n font-weight: bold;\n margin-bottom: 1rem;\n}\n\n/* \u76ee\u5f55\u94fe\u63a5 */\n.md-toc__link {\n color: var(--md-typeset-color);\n text-decoration: none;\n}\n\n/* \u76ee\u5f55\u5c42\u7ea7\u7f29\u8fdb */\n.md-toc__list {\n margin-left: 1.5em;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4233","title":"4.2.3.3 \u951a\u70b9\u94fe\u63a5","text":"\u914d\u7f6e\u951a\u70b9\u94fe\u63a5\uff1a
YAMLmarkdown_extensions:\n - toc:\n permalink: \u2693\ufe0e # \u951a\u70b9\u7b26\u53f7\n slug: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower} # URL \u8f6c\u6362\u89c4\u5219\n
\u81ea\u5b9a\u4e49\u951a\u70b9\u6837\u5f0f\uff1a
CSS/* \u951a\u70b9\u94fe\u63a5 */\n.headerlink {\n opacity: 0;\n margin-left: .5em;\n transition: opacity 0.2s ease;\n}\n\n/* \u6807\u9898\u60ac\u505c\u65f6\u663e\u793a\u951a\u70b9 */\nh1:hover .headerlink,\nh2:hover .headerlink,\nh3:hover .headerlink {\n opacity: 1;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#424","title":"4.2.4 \u8fd4\u56de\u9876\u90e8","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4241","title":"4.2.4.1 \u6309\u94ae\u6837\u5f0f","text":"\u542f\u7528\u8fd4\u56de\u9876\u90e8\u6309\u94ae\uff1a
YAMLtheme:\n features:\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n
\u81ea\u5b9a\u4e49\u6309\u94ae\u6837\u5f0f\uff1a
CSS/* \u8fd4\u56de\u9876\u90e8\u6309\u94ae */\n.md-top {\n background-color: var(--md-primary-fg-color);\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-top:hover {\n background-color: var(--md-primary-fg-color--dark);\n transform: translateY(-2px);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4242","title":"4.2.4.2 \u6eda\u52a8\u884c\u4e3a","text":"\u81ea\u5b9a\u4e49\u6eda\u52a8\u884c\u4e3a\uff1a
JavaScript// docs/javascripts/scroll.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const topButton = document.querySelector('.md-top');\n\n // \u5e73\u6ed1\u6eda\u52a8\n if (topButton) {\n topButton.addEventListener('click', (e) => {\n e.preventDefault();\n window.scrollTo({\n top: 0,\n behavior: 'smooth'\n });\n });\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4243","title":"4.2.4.3 \u663e\u793a\u63a7\u5236","text":"\u914d\u7f6e\u663e\u793a\u903b\u8f91\uff1a
JavaScript// \u63a7\u5236\u6309\u94ae\u663e\u793a\nwindow.addEventListener('scroll', () => {\n const topButton = document.querySelector('.md-top');\n if (topButton) {\n if (window.scrollY > 100) {\n topButton.classList.add('md-top--show');\n } else {\n topButton.classList.remove('md-top--show');\n }\n }\n});\n
\u6837\u5f0f\u63a7\u5236\uff1a
CSS/* \u6309\u94ae\u663e\u793a\u9690\u85cf */\n.md-top {\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n}\n\n.md-top--show {\n opacity: 1;\n visibility: visible;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#425","title":"4.2.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n features:\n # \u5bfc\u822a\u529f\u80fd\n - navigation.tabs\n - navigation.tabs.sticky\n - navigation.sections\n - navigation.expand\n - navigation.indexes\n - navigation.instant\n - navigation.tracking\n - navigation.sticky\n - header.autohide\n\n # \u76ee\u5f55\u529f\u80fd\n - toc.integrate\n - toc.follow\n\n # \u8fd4\u56de\u9876\u90e8\n - navigation.top\n\n# Markdown \u6269\u5c55\nmarkdown_extensions:\n - toc:\n permalink: true\n toc_depth: 3\n title: \u76ee\u5f55\n slugify: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower}\n\n# \u989d\u5916\u6837\u5f0f\u548c\u811a\u672c\nextra_css:\n - stylesheets/extra.css\n\nextra_javascript:\n - javascripts/tabs.js\n - javascripts/scroll.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#43","title":"4.3 \u641c\u7d22\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#431","title":"4.3.1 \u641c\u7d22\u5f15\u64ce\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4311","title":"4.3.1.1 \u641c\u7d22\u7b97\u6cd5","text":"\u57fa\u7840\u641c\u7d22\u914d\u7f6e\uff1a
YAMLplugins:\n - search:\n separator: '[\\\\s\\\\-\\\\.]+' # \u5206\u8bcd\u5206\u9694\u7b26\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n lang:\n - en\n - zh\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n
\u9ad8\u7ea7\u641c\u7d22\u9009\u9879\uff1a
YAMLplugins:\n - search:\n separator: '[\\\\s\\\\-\\\\.]+\\\\s*'\n min_search_length: 2\n prebuild_index: python\n indexing:\n full_sections: true # \u7d22\u5f15\u5b8c\u6574\u7ae0\u8282\n headings: true # \u7d22\u5f15\u6807\u9898\n content: true # \u7d22\u5f15\u5185\u5bb9\n tags: true # \u7d22\u5f15\u6807\u7b7e\n scoring:\n title_boost: 10 # \u6807\u9898\u6743\u91cd\n heading_boost: 5 # \u6807\u9898\u6743\u91cd\n content_boost: 1 # \u5185\u5bb9\u6743\u91cd\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4312","title":"4.3.1.2 \u7d22\u5f15\u914d\u7f6e","text":"\u81ea\u5b9a\u4e49\u7d22\u5f15\u8bbe\u7f6e\uff1a
YAMLplugins:\n - search:\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n attachments: true # \u7d22\u5f15\u9644\u4ef6\n attachments_types: # \u9644\u4ef6\u7c7b\u578b\n - .pdf\n - .doc\n - .docx\n attachments_max_size: 2048 # \u6700\u5927\u5927\u5c0f(KB)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4313","title":"4.3.1.3 \u641c\u7d22\u8303\u56f4","text":"\u914d\u7f6e\u641c\u7d22\u8303\u56f4\uff1a
YAMLplugins:\n - search:\n # \u5305\u542b\u7684\u6587\u4ef6\n include:\n - \"*.md\"\n - \"*.markdown\"\n\n # \u6392\u9664\u7684\u6587\u4ef6\n exclude:\n - drafts/*\n - private/*\n\n # \u5904\u7406\u7279\u5b9a\u8def\u5f84\n ignore:\n - 404.md\n - index.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#432","title":"4.3.2 \u641c\u7d22\u63d0\u793a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4321","title":"4.3.2.1 \u5feb\u6377\u952e\u8bbe\u7f6e","text":"\u914d\u7f6e\u641c\u7d22\u5feb\u6377\u952e\uff1a
YAMLtheme:\n keyboard:\n search: s, / # \u4f7f\u7528 's' \u6216 '/' \u89e6\u53d1\u641c\u7d22\n
\u81ea\u5b9a\u4e49\u5feb\u6377\u952e\u5904\u7406\uff1a
JavaScript// docs/javascripts/search.js\n\ndocument.addEventListener('keydown', function(e) {\n // \u81ea\u5b9a\u4e49\u5feb\u6377\u952e\u903b\u8f91\n if ((e.key === 's' || e.key === '/') && !e.ctrlKey && !e.altKey && !e.metaKey) {\n e.preventDefault();\n const search = document.querySelector('.md-search__input');\n if (search) {\n search.focus();\n }\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4322","title":"4.3.2.2 \u63d0\u793a\u6587\u672c","text":"\u81ea\u5b9a\u4e49\u641c\u7d22\u63d0\u793a\uff1a
YAMLtheme:\n language: zh # \u4f7f\u7528\u4e2d\u6587\u754c\u9762\n\nextra:\n search:\n language: zh\n text:\n placeholder: \u641c\u7d22\u6587\u6863...\n no_results: \u6ca1\u6709\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching: \u6b63\u5728\u641c\u7d22...\n
\u81ea\u5b9a\u4e49\u63d0\u793a\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search.css */\n\n/* \u641c\u7d22\u6846\u63d0\u793a\u6587\u672c */\n.md-search__input::placeholder {\n color: var(--md-default-fg-color--lighter);\n}\n\n/* \u65e0\u7ed3\u679c\u63d0\u793a */\n.md-search-result__meta {\n color: var(--md-default-fg-color--light);\n font-size: .8rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4323","title":"4.3.2.3 \u8f93\u5165\u5efa\u8bae","text":"\u914d\u7f6e\u641c\u7d22\u5efa\u8bae\uff1a
YAMLplugins:\n - search:\n suggestions: true # \u542f\u7528\u641c\u7d22\u5efa\u8bae\n suggestions_min_length: 2 # \u6700\u5c0f\u5efa\u8bae\u957f\u5ea6\n
\u81ea\u5b9a\u4e49\u5efa\u8bae\u6837\u5f0f\uff1a
CSS/* \u641c\u7d22\u5efa\u8bae\u6837\u5f0f */\n.md-search-result__item {\n padding: .4rem .8rem;\n transition: background .2s ease;\n}\n\n.md-search-result__item:hover {\n background-color: var(--md-code-bg-color);\n}\n\n/* \u5efa\u8bae\u9879\u56fe\u6807 */\n.md-search-result__icon {\n color: var(--md-default-fg-color--lighter);\n margin-right: .4rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#433","title":"4.3.3 \u641c\u7d22\u9ad8\u4eae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4331","title":"4.3.3.1 \u9ad8\u4eae\u6837\u5f0f","text":"\u914d\u7f6e\u641c\u7d22\u9ad8\u4eae\uff1a
YAMLtheme:\n features:\n - search.highlight # \u542f\u7528\u641c\u7d22\u9ad8\u4eae\n - search.share # \u542f\u7528\u641c\u7d22\u5206\u4eab\n - search.suggest # \u542f\u7528\u641c\u7d22\u5efa\u8bae\n
\u81ea\u5b9a\u4e49\u9ad8\u4eae\u6837\u5f0f\uff1a
CSS/* \u641c\u7d22\u7ed3\u679c\u9ad8\u4eae */\n.md-search-result__item mark {\n background-color: var(--md-accent-fg-color--transparent);\n color: var(--md-accent-fg-color);\n padding: 0 .2em;\n border-radius: .1em;\n}\n\n/* \u6eda\u52a8\u6761\u6837\u5f0f */\n.md-search-result__scrollwrap::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n}\n\n.md-search-result__scrollwrap::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4332","title":"4.3.3.2 \u5339\u914d\u89c4\u5219","text":"\u914d\u7f6e\u641c\u7d22\u5339\u914d\u89c4\u5219\uff1a
YAMLplugins:\n - search:\n # \u6587\u672c\u5339\u914d\u914d\u7f6e\n tokenizer: '[\\s\\-\\.]+' # \u5206\u8bcd\u89c4\u5219\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n\n # \u6a21\u7cca\u5339\u914d\u8bbe\u7f6e\n fuzzy: false # \u7981\u7528\u6a21\u7cca\u5339\u914d\n\n # \u5339\u914d\u6743\u91cd\n boost: \n title: 10 # \u6807\u9898\u6743\u91cd\n text: 1 # \u6587\u672c\u6743\u91cd\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4333","title":"4.3.3.3 \u81ea\u5b9a\u4e49\u9ad8\u4eae","text":"\u5b9e\u73b0\u81ea\u5b9a\u4e49\u9ad8\u4eae\u903b\u8f91\uff1a
JavaScript// docs/javascripts/search-highlight.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u83b7\u53d6\u641c\u7d22\u7ed3\u679c\u5bb9\u5668\n const searchResults = document.querySelector('.md-search-result');\n\n if (searchResults) {\n // \u76d1\u542c\u641c\u7d22\u7ed3\u679c\u53d8\u5316\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n if (mutation.type === 'childList') {\n // \u5904\u7406\u65b0\u6dfb\u52a0\u7684\u641c\u7d22\u7ed3\u679c\n const newResults = mutation.addedNodes;\n newResults.forEach(node => {\n if (node.nodeType === 1) { // \u5143\u7d20\u8282\u70b9\n customHighlight(node);\n }\n });\n }\n });\n });\n\n // \u542f\u52a8\u89c2\u5bdf\n observer.observe(searchResults, {\n childList: true,\n subtree: true\n });\n }\n});\n\nfunction customHighlight(node) {\n // \u81ea\u5b9a\u4e49\u9ad8\u4eae\u903b\u8f91\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#434","title":"4.3.4 \u641c\u7d22\u8bed\u8a00","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4341","title":"4.3.4.1 \u4e2d\u6587\u5206\u8bcd","text":"\u914d\u7f6e\u4e2d\u6587\u5206\u8bcd\uff1a
YAMLplugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,\\!\\/\\?\\u2000-\\u206F\\u3000-\\u303F\\u3040-\\u309F\\u30A0-\\u30FF\\u3100-\\u312F\\u3200-\\u32FF\\u3400-\\u4DBF\\u4E00-\\u9FFF]+'\n
\u4e2d\u6587\u641c\u7d22\u4f18\u5316\uff1a
JavaScript// docs/javascripts/chinese-search.js\n\nfunction chineseSegment(text) {\n // \u7b80\u5355\u7684\u4e2d\u6587\u5206\u8bcd\u903b\u8f91\n return text.replace(/[\\u4e00-\\u9fa5]/g, function(char) {\n return char + ' ';\n });\n}\n\n// \u6dfb\u52a0\u5230\u641c\u7d22\u5904\u7406\u6d41\u7a0b\ndocument.addEventListener('DOMContentLoaded', function() {\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.addEventListener('input', function(e) {\n const value = e.target.value;\n if (/[\\u4e00-\\u9fa5]/.test(value)) {\n // \u5904\u7406\u4e2d\u6587\u8f93\u5165\n const segmented = chineseSegment(value);\n // TODO: \u4f7f\u7528\u5206\u8bcd\u7ed3\u679c\u8fdb\u884c\u641c\u7d22\n }\n });\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4342","title":"4.3.4.2 \u591a\u8bed\u8a00\u652f\u6301","text":"\u914d\u7f6e\u591a\u8bed\u8a00\u641c\u7d22\uff1a
YAMLplugins:\n - search:\n lang:\n - en\n - zh\n - ja\n # \u8bed\u8a00\u7279\u5b9a\u7684\u5206\u8bcd\u89c4\u5219\n separator:\n en: '[\\\\s\\\\-\\\\.]+'\n zh: '[\\u4e00-\\u9fa5]'\n ja: '[\\u3040-\\u309F\\u30A0-\\u30FF]+'\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4343","title":"4.3.4.3 \u505c\u7528\u8bcd\u914d\u7f6e","text":"\u914d\u7f6e\u505c\u7528\u8bcd\uff1a
YAMLplugins:\n - search:\n stopwords: \n en:\n - a\n - an\n - the\n - in\n - on\n - at\n zh:\n - \u7684\n - \u4e86\n - \u548c\n - \u4e0e\n - \u6216\n
\u81ea\u5b9a\u4e49\u505c\u7528\u8bcd\u5904\u7406\uff1a
JavaScript// docs/javascripts/stopwords.js\n\nconst stopwords = {\n en: ['a', 'an', 'the', 'in', 'on', 'at'],\n zh: ['\u7684', '\u4e86', '\u548c', '\u4e0e', '\u6216'],\n};\n\nfunction removeStopwords(text, lang) {\n if (!stopwords[lang]) return text;\n\n const words = text.split(/\\s+/);\n return words\n .filter(word => !stopwords[lang].includes(word))\n .join(' ');\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#435","title":"4.3.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\nplugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,\\!\\/\\?\\u2000-\\u206F\\u3000-\\u303F]+'\n prebuild_index: python\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n scoring:\n title_boost: 10\n heading_boost: 5\n content_boost: 1\n\ntheme:\n features:\n - search.highlight\n - search.share\n - search.suggest\n\nextra:\n search:\n language: zh\n text:\n placeholder: \u641c\u7d22\u6587\u6863...\n no_results: \u6ca1\u6709\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching: \u6b63\u5728\u641c\u7d22...\n\nextra_javascript:\n - javascripts/search.js\n - javascripts/search-highlight.js\n - javascripts/chinese-search.js\n - javascripts/stopwords.js\n\nextra_css:\n - stylesheets/search.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#44","title":"4.4 \u4ee3\u7801\u5757\u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#441","title":"4.4.1 \u8bed\u6cd5\u9ad8\u4eae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4411","title":"4.4.1.1 \u9ad8\u4eae\u4e3b\u9898","text":"\u57fa\u7840\u9ad8\u4eae\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - content.code.annotate # \u542f\u7528\u4ee3\u7801\u6ce8\u91ca\n - content.code.copy # \u542f\u7528\u4ee3\u7801\u590d\u5236\n\nmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n use_pygments: true\n auto_title: true # \u663e\u793a\u8bed\u8a00\u540d\u79f0\n linenums: true # \u663e\u793a\u884c\u53f7\n
\u81ea\u5b9a\u4e49\u9ad8\u4eae\u4e3b\u9898\uff1a
YAMLtheme:\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u4e3b\u9898\n pygments_style: github-light\n\n # \u6697\u8272\u4e3b\u9898\n - scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u4e3b\u9898\n pygments_style: monokai\n
\u81ea\u5b9a\u4e49\u4ee3\u7801\u5757\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/code.css */\n\n/* \u4ee3\u7801\u5757\u5bb9\u5668 */\n.highlight {\n background-color: var(--md-code-bg-color);\n border-radius: 4px;\n padding: 0.5rem;\n margin: 1rem 0;\n}\n\n/* \u4ee3\u7801\u884c */\n.highlight .code-line {\n display: block;\n padding: 0 1rem;\n border-left: 2px solid transparent;\n}\n\n/* \u9ad8\u4eae\u884c */\n.highlight .code-line.focused {\n background-color: var(--md-code-hl-color);\n border-left: 2px solid var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4412","title":"4.4.1.2 \u8bed\u8a00\u652f\u6301","text":"\u914d\u7f6e\u652f\u6301\u7684\u8bed\u8a00\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n extend_pygments_lang:\n # \u81ea\u5b9a\u4e49\u8bed\u8a00\u914d\u7f6e\n typescript:\n name: TypeScript\n aliases: [ts]\n jsonc:\n name: JSON with Comments\n aliases: [json5]\n
\u8bed\u8a00\u7279\u5b9a\u914d\u7f6e\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n language_prefix: language- # \u8bed\u8a00\u524d\u7f00\n css_class: highlight # CSS\u7c7b\u540d\n code_attr_on_pre: false # \u5c5e\u6027\u4f4d\u7f6e\n extend_pygments_lang: # \u8bed\u8a00\u6269\u5c55\n flow:\n name: Flow\n aliases: [flowtype]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4413","title":"4.4.1.3 \u81ea\u5b9a\u4e49\u9ad8\u4eae","text":"\u81ea\u5b9a\u4e49\u8bed\u6cd5\u9ad8\u4eae\u89c4\u5219\uff1a
Python# docs/custom_lexer.py\nfrom pygments.lexer import RegexLexer, words\nfrom pygments.token import *\n\nclass CustomLexer(RegexLexer):\n name = 'CustomLanguage'\n aliases = ['custom']\n filenames = ['*.custom']\n\n tokens = {\n 'root': [\n (r'//.*$', Comment.Single),\n (words(('if', 'else', 'while'), suffix=r'\\b'), Keyword),\n (r'\"[^\"]*\"', String),\n (r'\\d+', Number),\n (r'[a-zA-Z_]\\w*', Name),\n (r'[^\\w\\s]', Punctuation),\n ]\n }\n
\u5728 mkdocs.yml
\u4e2d\u4f7f\u7528\uff1a
markdown_extensions:\n - pymdownx.highlight:\n use_pygments: true\n extend_pygments_lang:\n custom:\n name: CustomLanguage\n aliases: [custom]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#442","title":"4.4.2 \u884c\u53f7\u663e\u793a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4421","title":"4.4.2.1 \u884c\u53f7\u6837\u5f0f","text":"\u914d\u7f6e\u884c\u53f7\u663e\u793a\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n linenums: true\n linenums_style: table # \u8868\u683c\u5f0f\u884c\u53f7\n anchor_linenums: true # \u884c\u53f7\u94fe\u63a5\n
\u81ea\u5b9a\u4e49\u884c\u53f7\u6837\u5f0f\uff1a
CSS/* \u884c\u53f7\u5bb9\u5668 */\n.highlighttable {\n width: 100%;\n display: table;\n}\n\n/* \u884c\u53f7\u5217 */\n.linenos {\n color: var(--md-default-fg-color--lighter);\n text-align: right;\n padding-right: 1rem;\n user-select: none;\n}\n\n/* \u4ee3\u7801\u5217 */\n.code {\n padding-left: 1rem;\n border-left: 1px solid var(--md-default-fg-color--lightest);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4422","title":"4.4.2.2 \u8d77\u59cb\u884c\u8bbe\u7f6e","text":"\u8bbe\u7f6e\u4ee3\u7801\u5757\u8d77\u59cb\u884c\u53f7\uff1a
Markdown```python linenums=\"10\"\ndef hello_world():\n print(\"Hello, World!\")\n```\n
\u914d\u7f6e\u9ed8\u8ba4\u8d77\u59cb\u884c\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n linenums: true\n linenums_start: 1 # \u9ed8\u8ba4\u8d77\u59cb\u884c\u53f7\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4423","title":"4.4.2.3 \u884c\u53f7\u94fe\u63a5","text":"\u542f\u7528\u884c\u53f7\u94fe\u63a5\u529f\u80fd\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true # \u542f\u7528\u884c\u53f7\u94fe\u63a5\n line_anchors: L # \u884c\u53f7\u94fe\u63a5\u524d\u7f00\n
\u81ea\u5b9a\u4e49\u94fe\u63a5\u6837\u5f0f\uff1a
CSS/* \u884c\u53f7\u94fe\u63a5 */\n.md-typeset .highlight [data-linenos]:before {\n content: attr(data-linenos);\n color: var(--md-default-fg-color--lighter);\n padding-right: 1rem;\n}\n\n/* \u94fe\u63a5\u60ac\u505c\u6548\u679c */\n.md-typeset .highlight [data-linenos]:hover:before {\n color: var(--md-accent-fg-color);\n cursor: pointer;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#443","title":"4.4.3 \u590d\u5236\u6309\u94ae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4431","title":"4.4.3.1 \u6309\u94ae\u6837\u5f0f","text":"\u914d\u7f6e\u590d\u5236\u6309\u94ae\uff1a
YAMLtheme:\n features:\n - content.code.copy # \u542f\u7528\u4ee3\u7801\u590d\u5236\n
\u81ea\u5b9a\u4e49\u590d\u5236\u6309\u94ae\u6837\u5f0f\uff1a
CSS/* \u590d\u5236\u6309\u94ae\u5bb9\u5668 */\n.md-clipboard {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n padding: 0.4rem;\n color: var(--md-default-fg-color--lighter);\n background-color: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-clipboard:hover {\n color: var(--md-accent-fg-color);\n background-color: var(--md-code-bg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4432","title":"4.4.3.2 \u590d\u5236\u884c\u4e3a","text":"\u81ea\u5b9a\u4e49\u590d\u5236\u529f\u80fd\uff1a
JavaScript// docs/javascripts/clipboard.js\n\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u83b7\u53d6\u6240\u6709\u4ee3\u7801\u5757\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach(block => {\n // \u521b\u5efa\u590d\u5236\u6309\u94ae\n const button = document.createElement('button');\n button.className = 'md-clipboard';\n button.title = '\u590d\u5236\u5230\u526a\u8d34\u677f';\n\n // \u6dfb\u52a0\u590d\u5236\u56fe\u6807\n button.innerHTML = '<span class=\"md-clipboard__icon\"></span>';\n\n // \u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n button.addEventListener('click', async () => {\n try {\n // \u590d\u5236\u4ee3\u7801\n await navigator.clipboard.writeText(block.textContent);\n\n // \u663e\u793a\u6210\u529f\u63d0\u793a\n button.classList.add('md-clipboard--success');\n setTimeout(() => {\n button.classList.remove('md-clipboard--success');\n }, 2000);\n } catch (err) {\n console.error('\u590d\u5236\u5931\u8d25:', err);\n }\n });\n\n // \u5c06\u6309\u94ae\u6dfb\u52a0\u5230\u4ee3\u7801\u5757\n block.parentNode.insertBefore(button, block);\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4433","title":"4.4.3.3 \u63d0\u793a\u914d\u7f6e","text":"\u914d\u7f6e\u590d\u5236\u63d0\u793a\uff1a
YAMLtheme:\n language: zh # \u4f7f\u7528\u4e2d\u6587\u754c\u9762\n\nextra:\n clipboard:\n copy: \u590d\u5236\n copied: \u5df2\u590d\u5236\uff01\n error: \u590d\u5236\u5931\u8d25\n
\u81ea\u5b9a\u4e49\u63d0\u793a\u6837\u5f0f\uff1a
CSS/* \u590d\u5236\u63d0\u793a */\n.md-clipboard__tooltip {\n position: absolute;\n top: -2rem;\n right: 0;\n padding: 0.4rem 0.8rem;\n color: var(--md-default-bg-color);\n background-color: var(--md-default-fg-color);\n border-radius: 4px;\n font-size: 0.8rem;\n opacity: 0;\n transform: translateY(0.4rem);\n transition: all 0.2s ease;\n}\n\n/* \u663e\u793a\u63d0\u793a */\n.md-clipboard:hover .md-clipboard__tooltip {\n opacity: 1;\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#444","title":"4.4.4 \u6ce8\u91ca\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4441","title":"4.4.4.1 \u884c\u5185\u6ce8\u91ca","text":"\u4f7f\u7528\u884c\u5185\u6ce8\u91ca\uff1a
Markdown```python\ndef hello():\n print(\"Hello\") # (1)\n return True # (2)\n```\n\n1. \u6253\u5370\u95ee\u5019\u4fe1\u606f\n2. \u8fd4\u56de\u6210\u529f\u72b6\u6001\n
\u914d\u7f6e\u6ce8\u91ca\u6837\u5f0f\uff1a
CSS/* \u884c\u5185\u6ce8\u91ca\u6807\u8bb0 */\n.md-annotation {\n color: var(--md-accent-fg-color);\n font-size: 0.8em;\n vertical-align: super;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4442","title":"4.4.4.2 \u5757\u7ea7\u6ce8\u91ca","text":"\u4f7f\u7528\u5757\u7ea7\u6ce8\u91ca\uff1a
Markdown```python\ndef process_data():\n # (1)!\n data = load_data()\n\n # (2)!\n result = transform(data)\n\n return result\n```\n\n1. \u4ece\u6570\u636e\u6e90\u52a0\u8f7d\u6570\u636e\n \u8fd9\u91cc\u53ef\u4ee5\u662f\u591a\u884c\n \u6ce8\u91ca\u8bf4\u660e\n\n2. \u5bf9\u6570\u636e\u8fdb\u884c\u8f6c\u6362\u5904\u7406\n \u5305\u542b\u6e05\u6d17\u548c\u683c\u5f0f\u5316\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4443","title":"4.4.4.3 \u6ce8\u91ca\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u6ce8\u91ca\u6837\u5f0f\uff1a
CSS/* \u6ce8\u91ca\u5bb9\u5668 */\n.md-annotation-wrapper {\n margin: 1rem 0;\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-left: 4px solid var(--md-accent-fg-color);\n border-radius: 4px;\n}\n\n/* \u6ce8\u91ca\u6807\u8bb0 */\n.md-annotation-marker {\n color: var(--md-accent-fg-color);\n font-weight: bold;\n}\n\n/* \u6ce8\u91ca\u5185\u5bb9 */\n.md-annotation-content {\n margin-top: 0.5rem;\n color: var(--md-default-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#445","title":"4.4.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\ntheme:\n name: material\n features:\n - content.code.annotate\n - content.code.copy\n\nmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n use_pygments: true\n auto_title: true\n linenums: true\n linenums_style: table\n - pymdownx.superfences\n - pymdownx.inlinehilite\n\nextra:\n clipboard:\n copy: \u590d\u5236\n copied: \u5df2\u590d\u5236\uff01\n error: \u590d\u5236\u5931\u8d25\n\nextra_css:\n - stylesheets/code.css\n\nextra_javascript:\n - javascripts/clipboard.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#45","title":"4.5 \u5185\u5bb9\u589e\u5f3a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#451","title":"4.5.1 \u6570\u5b66\u516c\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4511-katex","title":"4.5.1.1 KaTeX \u914d\u7f6e","text":"\u5b89\u88c5\u548c\u914d\u7f6e KaTeX\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/katex.js \n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js \n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n
\u521b\u5efa docs/javascripts/katex.js
\uff1a
document.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false},\n {left: \"\\\\(\", right: \"\\\\)\", display: false},\n {left: \"\\\\[\", right: \"\\\\]\", display: true}\n ],\n throwOnError: false\n });\n});\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown\u5185\u8054\u516c\u5f0f: $E = mc^2$\n\n\u5757\u7ea7\u516c\u5f0f\uff1a\n$$\n\\frac{n!}{k!(n-k)!} = \\binom{n}{k}\n$$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4512-mathjax","title":"4.5.1.2 MathJax \u914d\u7f6e","text":"\u914d\u7f6e MathJax\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/mathjax.js\n - https://polyfill.io/v3/polyfill.min.js?features=es6\n - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\n
\u521b\u5efa docs/javascripts/mathjax.js
\uff1a
window.MathJax = {\n tex: {\n inlineMath: [[\"\\\\(\", \"\\\\)\"]],\n displayMath: [[\"\\\\[\", \"\\\\]\"]],\n processEscapes: true,\n processEnvironments: true\n },\n options: {\n ignoreHtmlClass: \".*|\",\n processHtmlClass: \"arithmatex\"\n }\n};\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4513","title":"4.5.1.3 \u516c\u5f0f\u7f16\u53f7","text":"\u542f\u7528\u516c\u5f0f\u7f16\u53f7\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n numbering: true\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown$$\n\\begin{equation}\nE = mc^2 \\label{eq:einstein}\n\\end{equation}\n$$\n\n\u5f15\u7528\u516c\u5f0f $\\eqref{eq:einstein}$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#452","title":"4.5.2 \u56fe\u8868\u652f\u6301","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4521-mermaid","title":"4.5.2.1 Mermaid \u96c6\u6210","text":"\u914d\u7f6e Mermaid\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Text Onlygraph TD\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B -->|Yes| C[\u5904\u7406]\n B -->|No| D[\u7ed3\u675f]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4522-plantuml","title":"4.5.2.2 PlantUML \u652f\u6301","text":"\u914d\u7f6e PlantUML\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: plantuml\n class: plantuml\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://cdn.jsdelivr.net/npm/plantuml-encoder@1.4.0/dist/plantuml-encoder.min.js\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Text Only@startuml\nAlice -> Bob: \u8bf7\u6c42\nBob --> Alice: \u54cd\u5e94\n@enduml\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4523","title":"4.5.2.3 \u81ea\u5b9a\u4e49\u56fe\u8868","text":"\u521b\u5efa\u81ea\u5b9a\u4e49\u56fe\u8868\u7ec4\u4ef6\uff1a
JavaScript// docs/javascripts/charts.js\nimport Chart from 'chart.js/auto';\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const chartElements = document.querySelectorAll('.custom-chart');\n\n chartElements.forEach(element => {\n const ctx = element.getContext('2d');\n const data = JSON.parse(element.dataset.chartData);\n\n new Chart(ctx, {\n type: data.type,\n data: data.data,\n options: data.options\n });\n });\n});\n
\u4f7f\u7528\u793a\u4f8b\uff1a
HTML<canvas class=\"custom-chart\" data-chart-data='{\n \"type\": \"line\",\n \"data\": {\n \"labels\": [\"1\u6708\", \"2\u6708\", \"3\u6708\"],\n \"datasets\": [{\n \"label\": \"\u6570\u636e\",\n \"data\": [10, 20, 30]\n }]\n }\n}'></canvas>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#453","title":"4.5.3 \u4efb\u52a1\u5217\u8868","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4531","title":"4.5.3.1 \u590d\u9009\u6846\u6837\u5f0f","text":"\u914d\u7f6e\u4efb\u52a1\u5217\u8868\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tasklist:\n custom_checkbox: true\n clickable_checkbox: true\n
\u81ea\u5b9a\u4e49\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/tasklist.css */\n\n.task-list-item {\n list-style-type: none;\n margin-left: -1.6rem;\n}\n\n.task-list-control {\n position: relative;\n display: inline-block;\n width: 1.2rem;\n height: 1.2rem;\n margin-right: 0.5rem;\n vertical-align: middle;\n}\n\n.task-list-indicator {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n\n.task-list-indicator:checked {\n background-color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4532","title":"4.5.3.2 \u4ea4\u4e92\u884c\u4e3a","text":"\u6dfb\u52a0\u4ea4\u4e92\u529f\u80fd\uff1a
JavaScript// docs/javascripts/tasklist.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const taskItems = document.querySelectorAll('.task-list-item input[type=\"checkbox\"]');\n\n taskItems.forEach(item => {\n item.addEventListener('change', function() {\n // \u4fdd\u5b58\u72b6\u6001\n localStorage.setItem(\n `task-${this.closest('.task-list-item').id}`,\n this.checked\n );\n\n // \u66f4\u65b0\u6837\u5f0f\n if (this.checked) {\n this.closest('.task-list-item').classList.add('completed');\n } else {\n this.closest('.task-list-item').classList.remove('completed');\n }\n });\n\n // \u6062\u590d\u72b6\u6001\n const saved = localStorage.getItem(`task-${item.closest('.task-list-item').id}`);\n if (saved === 'true') {\n item.checked = true;\n item.closest('.task-list-item').classList.add('completed');\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4533","title":"4.5.3.3 \u72b6\u6001\u7ba1\u7406","text":"CSS/* \u4efb\u52a1\u72b6\u6001\u6837\u5f0f */\n.task-list-item.completed {\n text-decoration: line-through;\n color: var(--md-default-fg-color--light);\n}\n\n.task-list-item.pending {\n font-weight: bold;\n}\n\n.task-list-item.in-progress {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#454","title":"4.5.4 \u6807\u7b7e\u9875","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4541","title":"4.5.4.1 \u6807\u7b7e\u7ec4\u6837\u5f0f","text":"\u914d\u7f6e\u6807\u7b7e\u9875\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tabbed:\n alternate_style: true \n
\u81ea\u5b9a\u4e49\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/tabs.css */\n\n/* \u6807\u7b7e\u7ec4\u5bb9\u5668 */\n.tabbed-set {\n border: 1px solid var(--md-default-fg-color--lightest);\n border-radius: 4px;\n margin: 1rem 0;\n}\n\n/* \u6807\u7b7e\u5217\u8868 */\n.tabbed-labels {\n display: flex;\n background-color: var(--md-code-bg-color);\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u5355\u4e2a\u6807\u7b7e */\n.tabbed-labels > label {\n padding: 0.8rem 1.2rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.tabbed-labels > label.tabbed-selected {\n color: var(--md-accent-fg-color);\n border-bottom: 2px solid var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4542","title":"4.5.4.2 \u5207\u6362\u6548\u679c","text":"\u6dfb\u52a0\u52a8\u753b\u6548\u679c\uff1a
CSS/* \u6807\u7b7e\u5185\u5bb9\u5207\u6362\u52a8\u753b */\n.tabbed-content {\n padding: 1rem;\n opacity: 0;\n transform: translateY(10px);\n transition: all 0.3s ease;\n}\n\n.tabbed-content.tabbed-selected {\n opacity: 1;\n transform: translateY(0);\n}\n
\u6807\u7b7e\u9875\u4ea4\u4e92\uff1a
JavaScript// docs/javascripts/tabs.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const tabSets = document.querySelectorAll('.tabbed-set');\n\n tabSets.forEach(tabSet => {\n const tabs = tabSet.querySelectorAll('.tabbed-labels > label');\n const contents = tabSet.querySelectorAll('.tabbed-content');\n\n tabs.forEach((tab, index) => {\n tab.addEventListener('click', () => {\n // \u66f4\u65b0\u6807\u7b7e\u72b6\u6001\n tabs.forEach(t => t.classList.remove('tabbed-selected'));\n tab.classList.add('tabbed-selected');\n\n // \u66f4\u65b0\u5185\u5bb9\u72b6\u6001\n contents.forEach(c => c.classList.remove('tabbed-selected'));\n contents[index].classList.add('tabbed-selected');\n });\n });\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4543","title":"4.5.4.3 \u54cd\u5e94\u5f0f\u8bbe\u8ba1","text":"\u6dfb\u52a0\u54cd\u5e94\u5f0f\u652f\u6301\uff1a
CSS/* \u79fb\u52a8\u7aef\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .tabbed-labels {\n flex-wrap: wrap;\n }\n\n .tabbed-labels > label {\n flex: 1 1 auto;\n text-align: center;\n }\n\n .tabbed-content {\n padding: 0.8rem;\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) {\n .tabbed-set {\n max-width: 80%;\n margin: 1rem auto;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#455","title":"4.5.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\nmarkdown_extensions:\n # \u6570\u5b66\u516c\u5f0f\n - pymdownx.arithmatex:\n generic: true\n\n # \u56fe\u8868\u652f\u6301\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n - name: plantuml\n class: plantuml\n format: !!python/name:pymdownx.superfences.fence_code_format\n\n # \u4efb\u52a1\u5217\u8868\n - pymdownx.tasklist:\n custom_checkbox: true\n clickable_checkbox: true\n\n # \u6807\u7b7e\u9875\n - pymdownx.tabbed:\n alternate_style: true\n\nextra_javascript:\n - javascripts/katex.js\n - javascripts/mermaid.js\n - javascripts/charts.js\n - javascripts/tasklist.js\n - javascripts/tabs.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n - stylesheets/tasklist.css\n - stylesheets/tabs.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5","title":"5 \u6837\u5f0f\u5b9a\u5236","text":""},{"location":"Tools/Blog/Mkdocs_Material/#51-css","title":"5.1 CSS \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#511-css","title":"5.1.1 \u81ea\u5b9a\u4e49 CSS \u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5111-css","title":"5.1.1.1 CSS \u6587\u4ef6\u7ec4\u7ec7","text":"docs/\n\u251c\u2500\u2500 stylesheets/\n\u2502 \u251c\u2500\u2500 base/\n\u2502 \u2502 \u251c\u2500\u2500 _variables.css # CSS\u53d8\u91cf\u5b9a\u4e49\n\u2502 \u2502 \u251c\u2500\u2500 _typography.css # \u6392\u7248\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _colors.css # \u989c\u8272\u5b9a\u4e49\n\u2502 \u251c\u2500\u2500 components/\n\u2502 \u2502 \u251c\u2500\u2500 _buttons.css # \u6309\u94ae\u6837\u5f0f\n\u2502 \u2502 \u251c\u2500\u2500 _cards.css # \u5361\u7247\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _tables.css # \u8868\u683c\u6837\u5f0f\n\u2502 \u251c\u2500\u2500 layouts/\n\u2502 \u2502 \u251c\u2500\u2500 _header.css # \u5934\u90e8\u6837\u5f0f\n\u2502 \u2502 \u251c\u2500\u2500 _nav.css # \u5bfc\u822a\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _footer.css # \u9875\u811a\u6837\u5f0f\n\u2502 \u2514\u2500\u2500 extra.css # \u4e3b\u6837\u5f0f\u6587\u4ef6\n
mkdocs.yml
\u4e2d\u5f15\u5165\u6837\u5f0f\uff1aextra_css:\n - stylesheets/extra.css\n
/* docs/stylesheets/extra.css */\n\n/* \u57fa\u7840\u6837\u5f0f */\n@import 'base/_variables.css';\n@import 'base/_typography.css';\n@import 'base/_colors.css';\n\n/* \u7ec4\u4ef6\u6837\u5f0f */\n@import 'components/_buttons.css';\n@import 'components/_cards.css';\n@import 'components/_tables.css';\n\n/* \u5e03\u5c40\u6837\u5f0f */\n@import 'layouts/_header.css';\n@import 'layouts/_nav.css';\n@import 'layouts/_footer.css';\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5112","title":"5.1.1.2 \u6837\u5f0f\u4f18\u5148\u7ea7","text":"/* 1. \u884c\u5185\u6837\u5f0f (1000) */\n<div style=\"color: red;\">\n\n/* 2. ID \u9009\u62e9\u5668 (100) */\n#header { }\n\n/* 3. \u7c7b\u9009\u62e9\u5668\u3001\u5c5e\u6027\u9009\u62e9\u5668\u3001\u4f2a\u7c7b (10) */\n.nav-item { }\n[type=\"text\"] { }\n:hover { }\n\n/* 4. \u5143\u7d20\u9009\u62e9\u5668\u3001\u4f2a\u5143\u7d20 (1) */\ndiv { }\n::before { }\n
/* \u8986\u76d6\u4e3b\u9898\u6837\u5f0f */\n.md-header {\n /* \u4f7f\u7528 !important \u614e\u91cd */\n background-color: #2196f3 !important;\n}\n\n/* \u4f7f\u7528\u66f4\u5177\u4f53\u7684\u9009\u62e9\u5668 */\n.md-header[data-md-color-scheme=\"default\"] {\n background-color: #2196f3;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5113-css","title":"5.1.1.3 CSS \u53d8\u91cf","text":"/* docs/stylesheets/base/_variables.css */\n\n:root {\n /* \u989c\u8272\u53d8\u91cf */\n --primary-color: #2196f3;\n --accent-color: #f50057;\n --text-color: #333333;\n\n /* \u5b57\u4f53\u53d8\u91cf */\n --font-family: \"LXGW WenKai\", -apple-system, sans-serif;\n --code-font: \"JetBrains Mono\", monospace;\n\n /* \u95f4\u8ddd\u53d8\u91cf */\n --spacing-unit: 8px;\n --content-padding: calc(var(--spacing-unit) * 2);\n\n /* \u9634\u5f71\u53d8\u91cf */\n --shadow-sm: 0 1px 2px rgba(0,0,0,0.1);\n --shadow-md: 0 2px 4px rgba(0,0,0,0.1);\n --shadow-lg: 0 4px 8px rgba(0,0,0,0.1);\n}\n
/* \u4eae\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"default\"] {\n --md-primary-fg-color: var(--primary-color);\n --md-accent-fg-color: var(--accent-color);\n --md-typeset-color: var(--text-color);\n}\n\n/* \u6697\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"slate\"] {\n --primary-color: #90caf9;\n --accent-color: #ff4081;\n --text-color: #ffffff;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#512","title":"5.1.2 \u5e38\u7528\u6837\u5f0f\u4fee\u6539","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5121","title":"5.1.2.1 \u5b57\u4f53\u8bbe\u7f6e","text":"/* docs/stylesheets/base/_typography.css */\n\n/* \u57fa\u7840\u5b57\u4f53\u8bbe\u7f6e */\nbody {\n font-family: var(--font-family);\n font-size: 16px;\n line-height: 1.6;\n}\n\n/* \u4ee3\u7801\u5b57\u4f53 */\ncode, pre {\n font-family: var(--code-font);\n font-size: 0.9em;\n}\n\n/* \u6807\u9898\u5b57\u4f53 */\nh1, h2, h3, h4, h5, h6 {\n font-family: var(--font-family);\n font-weight: 600;\n margin: calc(var(--spacing-unit) * 3) 0;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5122","title":"5.1.2.2 \u989c\u8272\u5b9a\u5236","text":"CSS/* docs/stylesheets/base/_colors.css */\n\n/* \u6587\u672c\u989c\u8272 */\n.md-typeset {\n color: var(--text-color);\n}\n\n/* \u94fe\u63a5\u989c\u8272 */\n.md-typeset a {\n color: var(--md-accent-fg-color);\n}\n\n/* \u4ee3\u7801\u5757\u989c\u8272 */\n.highlight {\n background-color: var(--md-code-bg-color);\n}\n\n/* \u5f15\u7528\u5757\u989c\u8272 */\nblockquote {\n border-left: 4px solid var(--md-accent-fg-color);\n background-color: var(--md-code-bg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5123","title":"5.1.2.3 \u95f4\u8ddd\u8c03\u6574","text":"CSS/* \u5185\u5bb9\u95f4\u8ddd */\n.md-main__inner {\n padding: var(--content-padding);\n}\n\n/* \u6bb5\u843d\u95f4\u8ddd */\n.md-typeset p {\n margin: var(--spacing-unit) 0;\n}\n\n/* \u5217\u8868\u95f4\u8ddd */\n.md-typeset ul li,\n.md-typeset ol li {\n margin-bottom: calc(var(--spacing-unit) * 0.5);\n}\n\n/* \u6807\u9898\u95f4\u8ddd */\n.md-typeset h1 {\n margin-top: calc(var(--spacing-unit) * 4);\n margin-bottom: calc(var(--spacing-unit) * 2);\n}\n\n.md-typeset h2 {\n margin-top: calc(var(--spacing-unit) * 3);\n margin-bottom: calc(var(--spacing-unit) * 1.5);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5124","title":"5.1.2.4 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"\u5728 mkdocs.yml
\u4e2d\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n font: false # \u7981\u7528\u9ed8\u8ba4\u5b57\u4f53\n\nextra_css:\n - stylesheets/extra.css\n\nextra:\n css_variables:\n spacing_unit: 8px\n content_width: 960px\n
"},{"location":"Tools/Blog/Mkdocs_Material/#52","title":"5.2 \u4e3b\u9898\u6837\u5f0f\u8986\u76d6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#521","title":"5.2.1 \u7ec4\u4ef6\u6837\u5f0f\u4fee\u6539","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5211","title":"5.2.1.1 \u5bfc\u822a\u680f\u6837\u5f0f","text":"/* docs/stylesheets/components/header.css */\n\n/* \u5bfc\u822a\u680f\u5bb9\u5668 */\n.md-header {\n background-color: var(--md-primary-fg-color);\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n height: 3rem;\n}\n\n/* \u5bfc\u822a\u680f\u6807\u9898 */\n.md-header__title {\n font-size: 1.2rem;\n font-weight: 600;\n margin-left: 1rem;\n}\n\n/* \u5bfc\u822a\u680f\u6309\u94ae */\n.md-header__button {\n padding: .8rem;\n color: var(--md-primary-bg-color);\n}\n\n/* \u5bfc\u822a\u680f\u641c\u7d22\u6846 */\n.md-search__input {\n border-radius: 2rem;\n background-color: rgba(255,255,255,.1);\n padding: 0 2.4rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5212","title":"5.2.1.2 \u4fa7\u8fb9\u680f\u6837\u5f0f","text":"CSS/* docs/stylesheets/components/sidebar.css */\n\n/* \u4fa7\u8fb9\u680f\u5bb9\u5668 */\n.md-sidebar {\n width: 14rem;\n background-color: var(--md-default-bg-color);\n padding: 1.2rem 0;\n}\n\n/* \u4fa7\u8fb9\u680f\u5bfc\u822a */\n.md-nav--primary {\n padding: 0 .8rem;\n}\n\n/* \u5bfc\u822a\u9879 */\n.md-nav__item {\n padding: .2rem 0;\n}\n\n/* \u5bfc\u822a\u94fe\u63a5 */\n.md-nav__link {\n color: var(--md-default-fg-color);\n padding: .4rem .6rem;\n border-radius: 4px;\n transition: all .2s;\n}\n\n.md-nav__link:hover {\n background-color: var(--md-code-bg-color);\n color: var(--md-accent-fg-color);\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-nav__link--active {\n font-weight: 600;\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5213","title":"5.2.1.3 \u9875\u811a\u6837\u5f0f","text":"CSS/* docs/stylesheets/components/footer.css */\n\n/* \u9875\u811a\u5bb9\u5668 */\n.md-footer {\n background-color: var(--md-default-bg-color--darkest);\n color: var(--md-footer-fg-color);\n}\n\n/* \u9875\u811a\u5185\u5bb9 */\n.md-footer-meta {\n background-color: rgba(0,0,0,.1);\n padding: 1rem 0;\n}\n\n/* \u9875\u811a\u94fe\u63a5 */\n.md-footer__link {\n padding: .4rem 1rem;\n color: var(--md-footer-fg-color--light);\n}\n\n/* \u7248\u6743\u4fe1\u606f */\n.md-footer-copyright {\n font-size: .8rem;\n color: var(--md-footer-fg-color--lighter);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#522","title":"5.2.2 \u81ea\u5b9a\u4e49\u8c03\u8272\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5221","title":"5.2.2.1 \u4e3b\u9898\u8272\u5b9a\u5236","text":"/* docs/stylesheets/theme/colors.css */\n\n:root {\n /* \u4e3b\u8272\u8c03 */\n --md-primary-hue: 210;\n --md-primary-saturation: 80%;\n --md-primary-lightness: 45%;\n\n /* \u5f3a\u8c03\u8272 */\n --md-accent-hue: 340;\n --md-accent-saturation: 90%;\n --md-accent-lightness: 50%;\n}\n
:root {\n --md-primary-fg-color: hsl(\n var(--md-primary-hue),\n var(--md-primary-saturation),\n var(--md-primary-lightness)\n );\n\n --md-accent-fg-color: hsl(\n var(--md-accent-hue),\n var(--md-accent-saturation),\n var(--md-accent-lightness)\n );\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5222","title":"5.2.2.2 \u914d\u8272\u65b9\u6848","text":"YAML# mkdocs.yml\ntheme:\n palette:\n # \u4eae\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: deep purple\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: blue grey\n accent: deep purple\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5223","title":"5.2.2.3 \u6697\u8272\u4e3b\u9898","text":"CSS/* \u6697\u8272\u4e3b\u9898\u53d8\u91cf */\n[data-md-color-scheme=\"slate\"] {\n --md-default-bg-color: #1a1a1a;\n --md-default-bg-color--light: #222222;\n --md-default-bg-color--lighter: #282828;\n\n --md-default-fg-color: rgba(255,255,255,0.87);\n --md-default-fg-color--light: rgba(255,255,255,0.54);\n --md-default-fg-color--lighter: rgba(255,255,255,0.32);\n\n --md-code-bg-color: #2d2d2d;\n --md-code-fg-color: #f5f5f5;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#523","title":"5.2.3 \u5b57\u4f53\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5231","title":"5.2.3.1 \u4e2d\u6587\u5b57\u4f53","text":"/* docs/stylesheets/theme/fonts.css */\n\n/* \u4e2d\u6587\u5b57\u4f53\u53d8\u91cf */\n:root {\n --md-font-chinese: \"LXGW WenKai\", \"PingFang SC\", \"Microsoft YaHei\";\n}\n\n/* \u5f15\u5165 LXGW WenKai \u5b57\u4f53 */\n@font-face {\n font-family: \"LXGW WenKai\";\n src: url(\"https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@1.1.0/style.css\");\n font-display: swap;\n}\n
body {\n font-family: var(--md-font-chinese), -apple-system, sans-serif;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5232","title":"5.2.3.2 \u4ee3\u7801\u5b57\u4f53","text":"CSS/* \u4ee3\u7801\u5b57\u4f53\u914d\u7f6e */\n:root {\n --md-code-font: \"JetBrains Mono\", \"Fira Code\", \"Source Code Pro\", monospace;\n}\n\n/* \u4ee3\u7801\u5757\u6837\u5f0f */\n.md-typeset code,\n.md-typeset pre {\n font-family: var(--md-code-font);\n font-size: 0.9em;\n}\n\n/* \u884c\u5185\u4ee3\u7801 */\n.md-typeset code {\n border-radius: 4px;\n padding: .2em .4em;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5233","title":"5.2.3.3 \u5b57\u4f53\u56de\u9000","text":"CSS/* \u5b57\u4f53\u56de\u9000\u7b56\u7565 */\n:root {\n --md-text-font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica,\n Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;\n\n --md-code-font-fallback: SFMono-Regular, Consolas, Menlo, monospace;\n}\n\n/* \u5e94\u7528\u56de\u9000\u5b57\u4f53 */\nbody {\n font-family: var(--md-font-chinese), var(--md-text-font-fallback);\n}\n\npre, code {\n font-family: var(--md-code-font), var(--md-code-font-fallback);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#524","title":"5.2.4 \u5e03\u5c40\u8c03\u6574","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5241","title":"5.2.4.1 \u54cd\u5e94\u5f0f\u5e03\u5c40","text":"CSS/* docs/stylesheets/theme/layout.css */\n\n/* \u57fa\u7840\u54cd\u5e94\u5f0f\u5e03\u5c40 */\n.md-grid {\n max-width: 100%;\n margin: 0 auto;\n}\n\n/* \u684c\u9762\u7aef */\n@media screen and (min-width: 76.25em) {\n .md-grid {\n max-width: 76rem;\n }\n\n .md-sidebar--primary {\n width: 14rem;\n }\n\n .md-sidebar--secondary {\n width: 12rem;\n margin-left: 76rem;\n }\n}\n\n/* \u5e73\u677f\u7aef */\n@media screen and (max-width: 76.1875em) {\n .md-grid {\n max-width: 60rem;\n }\n\n .md-header-nav__title {\n display: none;\n }\n}\n\n/* \u79fb\u52a8\u7aef */\n@media screen and (max-width: 44.9375em) {\n .md-grid {\n max-width: 100%;\n padding: 0 1rem;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5242","title":"5.2.4.2 \u7f51\u683c\u7cfb\u7edf","text":"CSS/* \u81ea\u5b9a\u4e49\u7f51\u683c\u7cfb\u7edf */\n.grid {\n display: grid;\n gap: 1rem;\n margin: 1rem 0;\n}\n\n/* \u7f51\u683c\u5217\u6570 */\n.grid-cols-1 { grid-template-columns: repeat(1, 1fr); }\n.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }\n.grid-cols-3 { grid-template-columns: repeat(3, 1fr); }\n.grid-cols-4 { grid-template-columns: repeat(4, 1fr); }\n\n/* \u54cd\u5e94\u5f0f\u7f51\u683c */\n@media (min-width: 768px) {\n .md-grid-cols-md-2 { grid-template-columns: repeat(2, 1fr); }\n .md-grid-cols-md-3 { grid-template-columns: repeat(3, 1fr); }\n}\n\n@media (min-width: 1024px) {\n .md-grid-cols-lg-3 { grid-template-columns: repeat(3, 1fr); }\n .md-grid-cols-lg-4 { grid-template-columns: repeat(4, 1fr); }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5243","title":"5.2.4.3 \u5bb9\u5668\u5bbd\u5ea6","text":"CSS/* \u5bb9\u5668\u5bbd\u5ea6\u5b9a\u4e49 */\n:root {\n --md-container-width: 80rem;\n --md-container-padding: 1rem;\n}\n\n/* \u5bb9\u5668\u6837\u5f0f */\n.md-container {\n max-width: var(--md-container-width);\n margin: 0 auto;\n padding: 0 var(--md-container-padding);\n}\n\n/* \u4e0d\u540c\u5c3a\u5bf8\u7684\u5bb9\u5668 */\n.md-container--small {\n max-width: 60rem;\n}\n\n.md-container--medium {\n max-width: 70rem;\n}\n\n.md-container--large {\n max-width: 90rem;\n}\n\n/* \u6d41\u5f0f\u5bb9\u5668 */\n.md-container--fluid {\n max-width: 100%;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#525","title":"5.2.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n font: false\n features:\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n palette:\n - scheme: default\n primary: indigo\n accent: deep purple\n - scheme: slate\n primary: blue grey\n accent: deep purple\n\nextra_css:\n - stylesheets/theme/colors.css\n - stylesheets/theme/fonts.css\n - stylesheets/theme/layout.css\n - stylesheets/components/header.css\n - stylesheets/components/sidebar.css\n - stylesheets/components/footer.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#53","title":"5.3 \u81ea\u5b9a\u4e49\u7ec4\u4ef6\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#531","title":"5.3.1 \u5361\u7247\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5311","title":"5.3.1.1 \u57fa\u7840\u5361\u7247","text":"\u57fa\u7840\u5361\u7247\u6837\u5f0f\u5b9a\u4e49\uff1a
CSS/* docs/stylesheets/components/cards.css */\n\n/* \u57fa\u7840\u5361\u7247\u5bb9\u5668 */\n.card {\n background-color: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n padding: 1.5rem;\n margin: 1rem 0;\n transition: all 0.3s ease;\n}\n\n/* \u5361\u7247\u6807\u9898 */\n.card__title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: var(--md-typeset-color);\n}\n\n/* \u5361\u7247\u5185\u5bb9 */\n.card__content {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n line-height: 1.6;\n}\n\n/* \u5361\u7247\u5e95\u90e8 */\n.card__footer {\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n
\u4f7f\u7528\u793a\u4f8b\uff1a
HTML<div class=\"card\">\n <div class=\"card__title\">\u5361\u7247\u6807\u9898</div>\n <div class=\"card__content\">\n \u8fd9\u91cc\u662f\u5361\u7247\u5185\u5bb9...\n </div>\n <div class=\"card__footer\">\n \u5361\u7247\u5e95\u90e8\u4fe1\u606f\n </div>\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5312","title":"5.3.1.2 \u56fe\u7247\u5361\u7247","text":"CSS/* \u56fe\u7247\u5361\u7247\u6837\u5f0f */\n.card--image {\n padding: 0;\n overflow: hidden;\n}\n\n/* \u56fe\u7247\u5bb9\u5668 */\n.card__image {\n width: 100%;\n height: 200px;\n position: relative;\n overflow: hidden;\n}\n\n/* \u56fe\u7247\u6837\u5f0f */\n.card__image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n/* \u56fe\u7247\u60ac\u505c\u6548\u679c */\n.card--image:hover img {\n transform: scale(1.05);\n}\n\n/* \u56fe\u7247\u5361\u7247\u5185\u5bb9\u533a */\n.card--image .card__content {\n padding: 1.5rem;\n}\n\n/* \u56fe\u7247\u6807\u9898\u8986\u76d6 */\n.card__image-title {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 1rem;\n background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);\n color: white;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5313","title":"5.3.1.3 \u7279\u6548\u5361\u7247","text":"CSS/* \u60ac\u6d6e\u6548\u679c\u5361\u7247 */\n.card--hover {\n cursor: pointer;\n}\n\n.card--hover:hover {\n transform: translateY(-4px);\n box-shadow: var(--md-shadow-z2);\n}\n\n/* \u6e10\u53d8\u80cc\u666f\u5361\u7247 */\n.card--gradient {\n background: linear-gradient(135deg, \n var(--md-primary-fg-color) 0%,\n var(--md-accent-fg-color) 100%);\n color: white;\n}\n\n/* \u6bdb\u73bb\u7483\u6548\u679c\u5361\u7247 */\n.card--glass {\n background: rgba(255, 255, 255, 0.1);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.2);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#532","title":"5.3.2 \u63d0\u793a\u6846\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5321","title":"5.3.2.1 \u4fe1\u606f\u63d0\u793a","text":"CSS/* docs/stylesheets/components/alerts.css */\n\n/* \u57fa\u7840\u63d0\u793a\u6846 */\n.alert {\n padding: 1rem 1.5rem;\n margin: 1rem 0;\n border-left: 4px solid;\n border-radius: 4px;\n}\n\n/* \u4fe1\u606f\u63d0\u793a */\n.alert--info {\n background-color: #e3f2fd;\n border-color: #2196f3;\n color: #0d47a1;\n}\n\n.alert--info::before {\n content: \"\u2139\ufe0f\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5322","title":"5.3.2.2 \u8b66\u544a\u63d0\u793a","text":"CSS/* \u8b66\u544a\u63d0\u793a */\n.alert--warning {\n background-color: #fff3e0;\n border-color: #ff9800;\n color: #e65100;\n}\n\n.alert--warning::before {\n content: \"\u26a0\ufe0f\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5323","title":"5.3.2.3 \u9519\u8bef\u63d0\u793a","text":"CSS/* \u9519\u8bef\u63d0\u793a */\n.alert--error {\n background-color: #ffebee;\n border-color: #f44336;\n color: #b71c1c;\n}\n\n.alert--error::before {\n content: \"\u274c\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#533","title":"5.3.3 \u53cb\u94fe\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5331","title":"5.3.3.1 \u53cb\u94fe\u5361\u7247","text":"CSS/* docs/stylesheets/components/friends.css */\n\n/* \u53cb\u94fe\u5bb9\u5668 */\n.friend-links {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 1.5rem;\n margin: 2rem 0;\n}\n\n/* \u53cb\u94fe\u5361\u7247 */\n.friend-link {\n display: flex;\n align-items: center;\n padding: 1rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n transition: all 0.3s ease;\n}\n\n/* \u5934\u50cf */\n.friend-link__avatar {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n margin-right: 1rem;\n}\n\n/* \u4fe1\u606f */\n.friend-link__info {\n flex: 1;\n}\n\n.friend-link__name {\n font-weight: 600;\n color: var(--md-typeset-color);\n}\n\n.friend-link__desc {\n font-size: 0.85rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.25rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5332","title":"5.3.3.2 \u5206\u7c7b\u5c55\u793a","text":"CSS/* \u53cb\u94fe\u5206\u7c7b */\n.friend-links-section {\n margin: 2rem 0;\n}\n\n/* \u5206\u7c7b\u6807\u9898 */\n.friend-links-section__title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-bottom: 1rem;\n padding-left: 1rem;\n border-left: 4px solid var(--md-accent-fg-color);\n}\n\n/* \u5206\u7c7b\u63cf\u8ff0 */\n.friend-links-section__desc {\n color: var(--md-default-fg-color--light);\n margin-bottom: 1.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5333","title":"5.3.3.3 \u60ac\u505c\u6548\u679c","text":"CSS/* \u60ac\u505c\u6548\u679c */\n.friend-link:hover {\n transform: translateY(-2px);\n box-shadow: var(--md-shadow-z2);\n}\n\n/* \u5934\u50cf\u52a8\u753b */\n.friend-link:hover .friend-link__avatar {\n transform: rotate(360deg);\n transition: transform 0.6s ease;\n}\n\n/* \u6807\u7b7e\u6548\u679c */\n.friend-link__tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n font-size: 0.75rem;\n border-radius: 12px;\n background-color: var(--md-code-bg-color);\n margin-top: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#534","title":"5.3.4 \u65f6\u95f4\u7ebf\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5341","title":"5.3.4.1 \u65f6\u95f4\u8f74\u8bbe\u8ba1","text":"CSS/* docs/stylesheets/components/timeline.css */\n\n/* \u65f6\u95f4\u7ebf\u5bb9\u5668 */\n.timeline {\n position: relative;\n max-width: 800px;\n margin: 2rem auto;\n padding: 2rem 0;\n}\n\n/* \u65f6\u95f4\u8f74\u7ebf */\n.timeline::before {\n content: '';\n position: absolute;\n top: 0;\n left: calc(50% - 1px);\n width: 2px;\n height: 100%;\n background-color: var(--md-default-fg-color--lightest);\n}\n\n/* \u65f6\u95f4\u7ebf\u9879\u76ee */\n.timeline-item {\n position: relative;\n margin: 2rem 0;\n}\n\n/* \u4ea4\u9519\u5e03\u5c40 */\n.timeline-item:nth-child(odd) {\n padding-right: calc(50% + 2rem);\n}\n\n.timeline-item:nth-child(even) {\n padding-left: calc(50% + 2rem);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5342","title":"5.3.4.2 \u8282\u70b9\u6837\u5f0f","text":"CSS/* \u65f6\u95f4\u8282\u70b9 */\n.timeline-node {\n position: absolute;\n top: 50%;\n width: 16px;\n height: 16px;\n background-color: var(--md-primary-fg-color);\n border-radius: 50%;\n transform: translateY(-50%);\n}\n\n.timeline-item:nth-child(odd) .timeline-node {\n right: calc(50% - 8px);\n}\n\n.timeline-item:nth-child(even) .timeline-node {\n left: calc(50% - 8px);\n}\n\n/* \u8282\u70b9\u5185\u5bb9 */\n.timeline-content {\n background-color: var(--md-default-bg-color);\n padding: 1.5rem;\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n}\n\n/* \u65f6\u95f4\u6807\u7b7e */\n.timeline-date {\n position: absolute;\n top: 50%;\n color: var(--md-default-fg-color--light);\n transform: translateY(-50%);\n}\n\n.timeline-item:nth-child(odd) .timeline-date {\n left: calc(50% + 2rem);\n}\n\n.timeline-item:nth-child(even) .timeline-date {\n right: calc(50% + 2rem);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5343","title":"5.3.4.3 \u54cd\u5e94\u5f0f\u9002\u914d","text":"CSS/* \u79fb\u52a8\u7aef\u9002\u914d */\n@media screen and (max-width: 768px) {\n .timeline::before {\n left: 0;\n }\n\n .timeline-item {\n padding-left: 2rem !important;\n padding-right: 0 !important;\n }\n\n .timeline-node {\n left: -8px !important;\n right: auto !important;\n }\n\n .timeline-date {\n position: relative;\n top: auto;\n left: auto !important;\n right: auto !important;\n margin-bottom: 0.5rem;\n }\n}\n\n/* \u5e73\u677f\u7aef\u9002\u914d */\n@media screen and (min-width: 769px) and (max-width: 1024px) {\n .timeline {\n max-width: 90%;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5344","title":"5.3.4.4 \u4f7f\u7528\u793a\u4f8b","text":"HTML<!-- \u65f6\u95f4\u7ebf\u793a\u4f8b -->\n<div class=\"timeline\">\n <div class=\"timeline-item\">\n <div class=\"timeline-node\"></div>\n <div class=\"timeline-date\">2024-01-01</div>\n <div class=\"timeline-content\">\n <h3>\u4e8b\u4ef6\u6807\u9898</h3>\n <p>\u4e8b\u4ef6\u63cf\u8ff0...</p>\n </div>\n </div>\n\n <!-- \u66f4\u591a\u65f6\u95f4\u7ebf\u9879\u76ee -->\n</div>\n\n<!-- \u53cb\u94fe\u793a\u4f8b -->\n<div class=\"friend-links-section\">\n <h2 class=\"friend-links-section__title\">\u6280\u672f\u535a\u5ba2</h2>\n <p class=\"friend-links-section__desc\">\u4f18\u79c0\u7684\u6280\u672f\u535a\u5ba2\u6536\u85cf</p>\n <div class=\"friend-links\">\n <a href=\"#\" class=\"friend-link\">\n <img src=\"avatar.jpg\" class=\"friend-link__avatar\">\n <div class=\"friend-link__info\">\n <div class=\"friend-link__name\">\u535a\u5ba2\u540d\u79f0</div>\n <div class=\"friend-link__desc\">\u535a\u5ba2\u63cf\u8ff0</div>\n <span class=\"friend-link__tag\">\u6807\u7b7e</span>\n </div>\n </a>\n </div>\n</div>\n\n<!-- \u63d0\u793a\u6846\u793a\u4f8b -->\n<div class=\"alert alert--info\">\n \u8fd9\u662f\u4e00\u6761\u4fe1\u606f\u63d0\u793a\n</div>\n\n<div class=\"alert alert--warning\">\n \u8fd9\u662f\u4e00\u6761\u8b66\u544a\u63d0\u793a\n</div>\n\n<div class=\"alert alert--error\">\n \u8fd9\u662f\u4e00\u6761\u9519\u8bef\u63d0\u793a\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#535","title":"5.3.5 \u5b8c\u6574\u914d\u7f6e","text":"YAML# mkdocs.yml\nextra_css:\n - stylesheets/components/cards.css\n - stylesheets/components/alerts.css\n - stylesheets/components/friends.css\n - stylesheets/components/timeline.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6-javascript","title":"6 JavaScript \u589e\u5f3a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#61","title":"6.1 \u57fa\u7840\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#611-js","title":"6.1.1 \u5f15\u5165 JS \u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6111","title":"6.1.1.1 \u672c\u5730\u6587\u4ef6","text":"docs/\n\u251c\u2500\u2500 javascripts/\n\u2502 \u251c\u2500\u2500 config/ # \u914d\u7f6e\u6587\u4ef6\n\u2502 \u2502 \u2514\u2500\u2500 main.js\n\u2502 \u251c\u2500\u2500 modules/ # \u529f\u80fd\u6a21\u5757\n\u2502 \u2502 \u251c\u2500\u2500 search.js\n\u2502 \u2502 \u2514\u2500\u2500 theme.js\n\u2502 \u251c\u2500\u2500 utils/ # \u5de5\u5177\u51fd\u6570\n\u2502 \u2502 \u2514\u2500\u2500 helpers.js\n\u2502 \u2514\u2500\u2500 extra.js # \u4e3b\u5165\u53e3\u6587\u4ef6\n
mkdocs.yml
\u4e2d\u5f15\u5165\uff1aextra_javascript:\n - javascripts/extra.js\n - javascripts/modules/search.js\n - javascripts/modules/theme.js\n
// docs/javascripts/extra.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u521d\u59cb\u5316\u4ee3\u7801\n console.log('Documentation loaded');\n});\n\n// docs/javascripts/modules/theme.js\nconst ThemeManager = {\n init() {\n // \u4e3b\u9898\u521d\u59cb\u5316\n },\n toggle() {\n // \u4e3b\u9898\u5207\u6362\n }\n};\n\n// docs/javascripts/utils/helpers.js\nconst Helpers = {\n debounce(fn, delay) {\n let timer = null;\n return function() {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, arguments), delay);\n };\n }\n};\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6112-cdn","title":"6.1.1.2 CDN \u5f15\u5165","text":"extra_javascript:\n # KaTeX \u6570\u5b66\u516c\u5f0f\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\n # Mermaid \u56fe\u8868\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\n # \u4ee3\u7801\u9ad8\u4eae\n - https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js\n
extra:\n cdn:\n # \u4f7f\u7528\u56fd\u5185 CDN\n enable: true\n provider: jsdelivr # \u6216 unpkg, cdnjs\n urls:\n katex: https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.js\n mermaid: https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.min.js\n
// docs/javascripts/config/cdn-fallback.js\nfunction loadFallbackScript(url, fallbackUrl) {\n const script = document.createElement('script');\n script.src = url;\n script.onerror = () => {\n console.warn(`Failed to load ${url}, trying fallback...`);\n const fallback = document.createElement('script');\n fallback.src = fallbackUrl;\n document.head.appendChild(fallback);\n };\n document.head.appendChild(script);\n}\n\n// \u4f7f\u7528\u793a\u4f8b\nloadFallbackScript(\n 'https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.js',\n 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js'\n);\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6113","title":"6.1.1.3 \u6a21\u5757\u5316\u7ba1\u7406","text":"// docs/javascripts/modules/theme.js\nexport class ThemeManager {\n constructor() {\n this.darkMode = false;\n }\n\n init() {\n this.loadPreference();\n this.bindEvents();\n }\n\n toggle() {\n this.darkMode = !this.darkMode;\n this.savePreference();\n this.applyTheme();\n }\n}\n\n// docs/javascripts/modules/search.js\nexport class SearchManager {\n constructor() {\n this.index = null;\n }\n\n init() {\n this.buildIndex();\n this.bindSearchEvents();\n }\n\n search(query) {\n // \u641c\u7d22\u5b9e\u73b0\n }\n}\n\n// docs/javascripts/extra.js\nimport { ThemeManager } from './modules/theme.js';\nimport { SearchManager } from './modules/search.js';\n\nconst theme = new ThemeManager();\nconst search = new SearchManager();\n\ndocument.addEventListener('DOMContentLoaded', () => {\n theme.init();\n search.init();\n});\n
// docs/javascripts/config/modules.js\nexport const ModuleConfig = {\n theme: {\n enabled: true,\n darkModeClass: 'dark-mode',\n storageKey: 'theme-preference'\n },\n search: {\n enabled: true,\n minChars: 3,\n maxResults: 10\n }\n};\n\n// \u4f7f\u7528\u914d\u7f6e\nimport { ModuleConfig } from '../config/modules.js';\n\nclass ThemeManager {\n constructor() {\n this.config = ModuleConfig.theme;\n if (!this.config.enabled) return;\n // \u521d\u59cb\u5316\u4ee3\u7801\n }\n}\n
// docs/javascripts/utils/helpers.js\nexport const DOM = {\n // DOM \u64cd\u4f5c\u8f85\u52a9\u51fd\u6570\n select: (selector) => document.querySelector(selector),\n selectAll: (selector) => document.querySelectorAll(selector),\n addClass: (element, className) => element.classList.add(className),\n removeClass: (element, className) => element.classList.remove(className)\n};\n\nexport const Storage = {\n // \u672c\u5730\u5b58\u50a8\u8f85\u52a9\u51fd\u6570\n get: (key) => localStorage.getItem(key),\n set: (key, value) => localStorage.setItem(key, value),\n remove: (key) => localStorage.removeItem(key)\n};\n\nexport const Events = {\n // \u4e8b\u4ef6\u5904\u7406\u8f85\u52a9\u51fd\u6570\n on: (element, event, handler) => element.addEventListener(event, handler),\n off: (element, event, handler) => element.removeEventListener(event, handler),\n trigger: (element, event) => element.dispatchEvent(new Event(event))\n};\n
# mkdocs.yml\nextra_javascript:\n # \u6838\u5fc3\u6587\u4ef6\n - javascripts/extra.js\n - javascripts/config/modules.js\n\n # \u529f\u80fd\u6a21\u5757\n - javascripts/modules/theme.js\n - javascripts/modules/search.js\n\n # \u5de5\u5177\u51fd\u6570\n - javascripts/utils/helpers.js\n\n # \u7b2c\u4e09\u65b9\u5e93\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\n# \u6a21\u5757\u914d\u7f6e\nextra:\n javascript_modules:\n theme:\n enabled: true\n default: light\n search:\n enabled: true\n min_chars: 3\n
"},{"location":"Tools/Blog/Mkdocs_Material/#62","title":"6.2 \u7b2c\u4e09\u65b9\u5e93\u96c6\u6210","text":""},{"location":"Tools/Blog/Mkdocs_Material/#621-katex","title":"6.2.1 KaTeX \u6570\u5b66\u516c\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6211","title":"6.2.1.1 \u57fa\u7840\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/katex.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n
// docs/javascripts/katex.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false},\n {left: \"\\\\(\", right: \"\\\\)\", display: false},\n {left: \"\\\\[\", right: \"\\\\]\", display: true}\n ],\n throwOnError: false,\n errorColor: \"#cc0000\",\n strict: \"ignore\"\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6212","title":"6.2.1.2 \u81ea\u52a8\u6e32\u67d3","text":"// docs/javascripts/katex-auto.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false}\n ],\n // \u81ea\u52a8\u6e32\u67d3\u8bbe\u7f6e\n ignoredTags: [\"script\", \"noscript\", \"style\", \"textarea\", \"pre\", \"code\"],\n ignoredClasses: [\"no-math\"],\n processEscapes: true,\n processEnvironments: true,\n // \u5904\u7406\u81ea\u5b9a\u4e49\u5b8f\n macros: {\n \"\\\\RR\": \"\\\\mathbb{R}\",\n \"\\\\NN\": \"\\\\mathbb{N}\",\n \"\\\\ZZ\": \"\\\\mathbb{Z}\"\n }\n });\n});\n
\u884c\u5185\u516c\u5f0f\uff1a$E = mc^2$\n\n\u5757\u7ea7\u516c\u5f0f\uff1a\n$$\n\\frac{n!}{k!(n-k)!} = \\binom{n}{k}\n$$\n\n\u81ea\u5b9a\u4e49\u5b8f\uff1a$\\RR$ \u8868\u793a\u5b9e\u6570\u96c6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6213","title":"6.2.1.3 \u516c\u5f0f\u7f16\u53f7","text":"// docs/javascripts/katex-numbering.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // \u516c\u5f0f\u7f16\u53f7\u8ba1\u6570\u5668\n let equationNumbers = {};\n let numberings = {};\n\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true}\n ],\n // \u516c\u5f0f\u7f16\u53f7\u5904\u7406\n preProcess: (math) => {\n if (math.includes('\\\\label')) {\n const label = math.match(/\\\\label{([^}]*)}/)[1];\n const number = Object.keys(numberings).length + 1;\n numberings[label] = number;\n return math.replace(/\\\\label{[^}]*}/, `(${number})`);\n }\n return math;\n }\n });\n});\n
\u5e26\u7f16\u53f7\u7684\u516c\u5f0f\uff1a\n$$\nE = mc^2 \\label{eq:einstein}\n$$\n\n\u5f15\u7528\u4e0a\u9762\u7684\u516c\u5f0f $\\eqref{eq:einstein}$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#622-mermaid","title":"6.2.2 Mermaid \u56fe\u8868","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6221","title":"6.2.2.1 \u521d\u59cb\u5316\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n - javascripts/mermaid.js\n
// docs/javascripts/mermaid.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n mermaid.initialize({\n startOnLoad: true,\n theme: 'default',\n sequence: {\n showSequenceNumbers: true,\n actorMargin: 50,\n messageMargin: 40\n },\n flowchart: {\n useMaxWidth: false,\n htmlLabels: true,\n curve: 'basis'\n },\n gantt: {\n titleTopMargin: 25,\n barHeight: 20,\n barGap: 4\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6222","title":"6.2.2.2 \u4e3b\u9898\u5b9a\u5236","text":"// docs/javascripts/mermaid-theme.js\nmermaid.initialize({\n theme: 'base',\n themeVariables: {\n // \u57fa\u7840\u989c\u8272\n primaryColor: '#2196f3',\n primaryTextColor: '#fff',\n primaryBorderColor: '#1976d2',\n lineColor: '#696969',\n\n // \u6d41\u7a0b\u56fe\u989c\u8272\n nodeBkg: '#fff',\n mainBkg: '#f8f9fa',\n nodeTextColor: '#333',\n\n // \u65f6\u5e8f\u56fe\u989c\u8272\n actorBkg: '#f8f9fa',\n actorBorder: '#2196f3',\n actorTextColor: '#333',\n\n // \u7518\u7279\u56fe\u989c\u8272\n sectionBkgColor: '#f8f9fa',\n altSectionBkgColor: '#fff',\n\n // \u6697\u8272\u4e3b\u9898\u652f\u6301\n darkMode: false\n }\n});\n
// \u76d1\u542c\u4e3b\u9898\u5207\u6362\ndocument.addEventListener('themeChanged', function(e) {\n const isDark = e.detail.theme === 'dark';\n mermaid.initialize({\n theme: isDark ? 'dark' : 'default',\n themeVariables: {\n darkMode: isDark\n }\n });\n // \u91cd\u65b0\u6e32\u67d3\u56fe\u8868\n mermaid.init(undefined, '.mermaid');\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6223","title":"6.2.2.3 \u4ea4\u4e92\u529f\u80fd","text":"// docs/javascripts/mermaid-interaction.js\nmermaid.initialize({\n securityLevel: 'loose',\n flowchart: {\n htmlLabels: true,\n useMaxWidth: true\n }\n});\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // \u4e3a\u56fe\u8868\u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n const diagrams = document.querySelectorAll('.mermaid');\n diagrams.forEach(diagram => {\n diagram.addEventListener('click', function(e) {\n const target = e.target;\n if (target.tagName === 'g' && target.classList.contains('node')) {\n const nodeId = target.id;\n console.log('Clicked node:', nodeId);\n // \u5904\u7406\u8282\u70b9\u70b9\u51fb\n handleNodeClick(nodeId);\n }\n });\n });\n});\n\nfunction handleNodeClick(nodeId) {\n // \u8282\u70b9\u70b9\u51fb\u5904\u7406\n const node = document.getElementById(nodeId);\n if (node) {\n // \u6dfb\u52a0\u9ad8\u4eae\u6548\u679c\n node.classList.add('node-highlight');\n setTimeout(() => {\n node.classList.remove('node-highlight');\n }, 1000);\n }\n}\n
/* docs/stylesheets/mermaid.css */\n.mermaid .node-highlight {\n animation: pulse 1s;\n}\n\n@keyframes pulse {\n 0% { opacity: 1; }\n 50% { opacity: 0.5; }\n 100% { opacity: 1; }\n}\n\n.mermaid .flowchart-link {\n transition: stroke-width 0.3s ease;\n}\n\n.mermaid .flowchart-link:hover {\n stroke-width: 2px;\n cursor: pointer;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6224","title":"6.2.2.4 \u4f7f\u7528\u793a\u4f8b","text":"```mermaid\ngraph TD\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B -->|Yes| C[\u5904\u7406]\n B -->|No| D[\u7ed3\u675f]\n C --> D\n```\n
```mermaid\nsequenceDiagram\n participant \u5ba2\u6237\u7aef\n participant \u670d\u52a1\u5668\n\n \u5ba2\u6237\u7aef->>\u670d\u52a1\u5668: \u8bf7\u6c42\u6570\u636e\n \u670d\u52a1\u5668-->>\u5ba2\u6237\u7aef: \u8fd4\u56de\u54cd\u5e94\n```\n
"},{"location":"Tools/Blog/Mkdocs_Material/#623","title":"6.2.3 \u4ee3\u7801\u590d\u5236","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6231","title":"6.2.3.1 \u590d\u5236\u6309\u94ae","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1atheme:\n features:\n - content.code.copy\n\nextra_css:\n - stylesheets/code-copy.css\nextra_javascript:\n - javascripts/code-copy.js\n
/* docs/stylesheets/code-copy.css */\n\n/* \u590d\u5236\u6309\u94ae\u5bb9\u5668 */\n.copy-button {\n position: absolute;\n right: 0.5rem;\n top: 0.5rem;\n padding: 0.4rem;\n background-color: rgba(0, 0, 0, 0.1);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u6309\u94ae\u60ac\u505c\u6548\u679c */\n.copy-button:hover {\n background-color: rgba(0, 0, 0, 0.2);\n}\n\n/* \u56fe\u6807\u6837\u5f0f */\n.copy-button i {\n font-size: 1rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u6210\u529f\u72b6\u6001 */\n.copy-button.success {\n background-color: var(--md-accent-fg-color);\n}\n\n.copy-button.success i {\n color: white;\n}\n
// docs/javascripts/code-copy.js\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u4e3a\u6240\u6709\u4ee3\u7801\u5757\u6dfb\u52a0\u590d\u5236\u6309\u94ae\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach((codeBlock) => {\n const container = codeBlock.parentNode;\n const copyButton = document.createElement('button');\n copyButton.className = 'copy-button';\n copyButton.innerHTML = '<i class=\"material-icons\">content_copy</i>';\n container.style.position = 'relative';\n container.appendChild(copyButton);\n\n // \u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n copyButton.addEventListener('click', async () => {\n try {\n await navigator.clipboard.writeText(codeBlock.textContent);\n showSuccess(copyButton);\n } catch (err) {\n showError(copyButton);\n }\n });\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6232","title":"6.2.3.2 \u63d0\u793a\u6d88\u606f","text":"/* \u63d0\u793a\u6d88\u606f\u6837\u5f0f */\n.copy-tooltip {\n position: absolute;\n top: -2rem;\n right: 0;\n padding: 0.4rem 0.8rem;\n background-color: var(--md-default-fg-color);\n color: var(--md-default-bg-color);\n border-radius: 4px;\n font-size: 0.8rem;\n opacity: 0;\n transform: translateY(0.4rem);\n transition: all 0.2s ease;\n}\n\n.copy-tooltip.show {\n opacity: 1;\n transform: translateY(0);\n}\n
// \u663e\u793a\u63d0\u793a\u6d88\u606f\nfunction showTooltip(button, message, type = 'success') {\n const tooltip = document.createElement('div');\n tooltip.className = `copy-tooltip ${type}`;\n tooltip.textContent = message;\n button.appendChild(tooltip);\n\n // \u6dfb\u52a0\u663e\u793a\u7c7b\n setTimeout(() => tooltip.classList.add('show'), 10);\n\n // \u81ea\u52a8\u79fb\u9664\n setTimeout(() => {\n tooltip.classList.remove('show');\n setTimeout(() => tooltip.remove(), 200);\n }, 2000);\n}\n\n// \u6210\u529f\u63d0\u793a\nfunction showSuccess(button) {\n button.classList.add('success');\n showTooltip(button, '\u590d\u5236\u6210\u529f\uff01');\n setTimeout(() => button.classList.remove('success'), 2000);\n}\n\n// \u9519\u8bef\u63d0\u793a\nfunction showError(button) {\n button.classList.add('error');\n showTooltip(button, '\u590d\u5236\u5931\u8d25\uff01', 'error');\n setTimeout(() => button.classList.remove('error'), 2000);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6233","title":"6.2.3.3 \u590d\u5236\u56de\u8c03","text":"JavaScript// \u5b9a\u4e49\u590d\u5236\u4e8b\u4ef6\u5904\u7406\u5668\nconst copyHandlers = {\n // \u590d\u5236\u524d\u5904\u7406\n beforeCopy: (code) => {\n // \u53ef\u4ee5\u5728\u8fd9\u91cc\u5bf9\u4ee3\u7801\u8fdb\u884c\u9884\u5904\u7406\n return code.trim();\n },\n\n // \u590d\u5236\u6210\u529f\u56de\u8c03\n onSuccess: (button, code) => {\n console.log('Copied:', code.length, 'characters');\n showSuccess(button);\n\n // \u89e6\u53d1\u81ea\u5b9a\u4e49\u4e8b\u4ef6\n const event = new CustomEvent('codeCopied', {\n detail: { code }\n });\n document.dispatchEvent(event);\n },\n\n // \u590d\u5236\u5931\u8d25\u56de\u8c03\n onError: (button, error) => {\n console.error('Copy failed:', error);\n showError(button);\n }\n};\n\n// \u4f7f\u7528\u56de\u8c03\nasync function copyCode(button, code) {\n try {\n const processedCode = copyHandlers.beforeCopy(code);\n await navigator.clipboard.writeText(processedCode);\n copyHandlers.onSuccess(button, processedCode);\n } catch (err) {\n copyHandlers.onError(button, err);\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#624","title":"6.2.4 \u56fe\u7247\u9884\u89c8","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6241-lightbox","title":"6.2.4.1 lightbox \u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - attr_list\n - md_in_html\n\nplugins:\n - glightbox\n\nextra_css:\n - stylesheets/glightbox.css\nextra_javascript:\n - javascripts/glightbox.js\n
// docs/javascripts/glightbox.js\ndocument.addEventListener('DOMContentLoaded', () => {\n const lightbox = GLightbox({\n selector: '.glightbox',\n touchNavigation: true,\n loop: false,\n autoplayVideos: true,\n preload: true,\n // \u57fa\u672c\u8bbe\u7f6e\n height: 'auto',\n zoomable: true,\n draggable: true,\n // \u52a8\u753b\u8bbe\u7f6e\n openEffect: 'zoom',\n closeEffect: 'fade',\n cssEfects: {\n fade: { in: 'fadeIn', out: 'fadeOut' },\n zoom: { in: 'zoomIn', out: 'zoomOut' }\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6242","title":"6.2.4.2 \u7f29\u653e\u529f\u80fd","text":"JavaScript// \u7f29\u653e\u529f\u80fd\u914d\u7f6e\nconst zoomConfig = {\n // \u7f29\u653e\u9009\u9879\n zoomable: true,\n dragToZoom: true,\n touchToZoom: true,\n\n // \u7f29\u653e\u7ea7\u522b\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.5,\n\n // \u53cc\u51fb\u7f29\u653e\n doubleTapZoom: 2,\n\n // \u7f29\u653e\u52a8\u753b\n zoomAnimation: true,\n zoomDuration: 300,\n\n // \u7f29\u653e\u63a7\u5236\u5668\n controls: {\n zoom: true,\n zoomIn: true,\n zoomOut: true,\n rotate: true\n }\n};\n\n// \u5e94\u7528\u7f29\u653e\u914d\u7f6e\nconst lightbox = GLightbox({\n ...zoomConfig,\n\n // \u7f29\u653e\u4e8b\u4ef6\u5904\u7406\n onZoom: (slider) => {\n const { zoom, image } = slider;\n console.log(`Current zoom level: ${zoom}`);\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6243","title":"6.2.4.3 \u624b\u52bf\u652f\u6301","text":"JavaScript// \u624b\u52bf\u914d\u7f6e\nconst gestureConfig = {\n // \u89e6\u6478\u5bfc\u822a\n touchNavigation: true,\n touchFollowAxis: true,\n\n // \u62d6\u52a8\u8bbe\u7f6e\n draggable: true,\n dragToleranceX: 40,\n dragToleranceY: 65,\n\n // \u624b\u52bf\u4e8b\u4ef6\n gestures: {\n // \u634f\u5408\u7f29\u653e\n pinchToZoom: true,\n pinchThreshold: 50,\n\n // \u53cc\u6307\u65cb\u8f6c\n rotateToZoom: true,\n rotateThreshold: 15,\n\n // \u6ed1\u52a8\u5207\u6362\n swipeThreshold: 50,\n swipeToClose: true\n }\n};\n\n// \u624b\u52bf\u4e8b\u4ef6\u5904\u7406\nconst gestureHandlers = {\n // \u89e6\u6478\u5f00\u59cb\n onTouchStart: (e) => {\n const touch = e.touches[0];\n startX = touch.clientX;\n startY = touch.clientY;\n },\n\n // \u89e6\u6478\u79fb\u52a8\n onTouchMove: (e) => {\n if (!isDragging) return;\n const touch = e.touches[0];\n const deltaX = touch.clientX - startX;\n const deltaY = touch.clientY - startY;\n\n // \u5904\u7406\u79fb\u52a8\n handleImageMove(deltaX, deltaY);\n },\n\n // \u89e6\u6478\u7ed3\u675f\n onTouchEnd: (e) => {\n isDragging = false;\n // \u5904\u7406\u60ef\u6027\u6ed1\u52a8\n handleMomentum();\n }\n};\n\n// \u521b\u5efa\u589e\u5f3a\u7684\u56fe\u7247\u9884\u89c8\nconst enhancedLightbox = GLightbox({\n ...zoomConfig,\n ...gestureConfig,\n\n // \u4e8b\u4ef6\u76d1\u542c\n listeners: {\n touchstart: gestureHandlers.onTouchStart,\n touchmove: gestureHandlers.onTouchMove,\n touchend: gestureHandlers.onTouchEnd\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6244","title":"6.2.4.4 \u5b8c\u6574\u793a\u4f8b","text":"JavaScript// docs/javascripts/image-preview.js\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u521d\u59cb\u5316\u914d\u7f6e\n const config = {\n // \u57fa\u7840\u8bbe\u7f6e\n selector: '.glightbox',\n touchNavigation: true,\n loop: false,\n\n // \u7f29\u653e\u8bbe\u7f6e\n zoomable: true,\n draggable: true,\n dragToleranceX: 40,\n dragToleranceY: 65,\n\n // \u52a8\u753b\u8bbe\u7f6e\n openEffect: 'zoom',\n closeEffect: 'fade',\n\n // \u624b\u52bf\u8bbe\u7f6e\n touchFollowAxis: true,\n\n // \u754c\u9762\u8bbe\u7f6e\n preload: true,\n height: 'auto',\n\n // \u4e8b\u4ef6\u5904\u7406\n onOpen: () => {\n console.log('Lightbox opened');\n },\n onClose: () => {\n console.log('Lightbox closed');\n },\n onZoom: (slider) => {\n console.log('Image zoomed');\n }\n };\n\n // \u521d\u59cb\u5316 GLightbox\n const lightbox = GLightbox(config);\n\n // \u6dfb\u52a0\u952e\u76d8\u652f\u6301\n document.addEventListener('keydown', (e) => {\n if (!lightbox.isOpen) return;\n\n switch(e.key) {\n case 'ArrowLeft':\n lightbox.prev();\n break;\n case 'ArrowRight':\n lightbox.next();\n break;\n case 'Escape':\n lightbox.close();\n break;\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#63","title":"6.3 \u81ea\u5b9a\u4e49\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#631","title":"6.3.1 \u9875\u9762\u4ea4\u4e92","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6311","title":"6.3.1.1 \u6eda\u52a8\u4e8b\u4ef6","text":"// docs/javascripts/scroll.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6eda\u52a8\u5904\u7406\u51fd\u6570\n function handleScroll() {\n const scrollTop = window.scrollY;\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight;\n\n // \u6eda\u52a8\u8fdb\u5ea6\n const scrollPercent = (scrollTop / (docHeight - windowHeight)) * 100;\n\n // \u66f4\u65b0\u8fdb\u5ea6\u6761\n updateProgress(scrollPercent);\n\n // \u5904\u7406\u5143\u7d20\u53ef\u89c1\u6027\n handleVisibility();\n }\n\n // \u4f7f\u7528\u8282\u6d41\u4f18\u5316\u6eda\u52a8\u4e8b\u4ef6\n const throttledScroll = throttle(handleScroll, 100);\n window.addEventListener('scroll', throttledScroll);\n});\n\n// \u8282\u6d41\u51fd\u6570\nfunction throttle(fn, delay) {\n let lastCall = 0;\n return function(...args) {\n const now = Date.now();\n if (now - lastCall >= delay) {\n lastCall = now;\n fn.apply(this, args);\n }\n };\n}\n
// \u68c0\u6d4b\u5143\u7d20\u662f\u5426\u8fdb\u5165\u89c6\u53e3\nfunction handleVisibility() {\n const elements = document.querySelectorAll('.animate-on-scroll');\n\n elements.forEach(element => {\n const rect = element.getBoundingClientRect();\n const isVisible = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth\n );\n\n if (isVisible) {\n element.classList.add('is-visible');\n }\n });\n}\n\n// CSS \u6837\u5f0f\n.animate-on-scroll {\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.6s ease;\n}\n\n.animate-on-scroll.is-visible {\n opacity: 1;\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6312","title":"6.3.1.2 \u70b9\u51fb\u4e8b\u4ef6","text":"// docs/javascripts/click.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u4ee3\u7801\u5757\u70b9\u51fb\u590d\u5236\n setupCodeCopy();\n\n // \u56fe\u7247\u70b9\u51fb\u653e\u5927\n setupImageZoom();\n\n // \u76ee\u5f55\u70b9\u51fb\u6eda\u52a8\n setupTocScroll();\n});\n\n// \u4ee3\u7801\u590d\u5236\u529f\u80fd\nfunction setupCodeCopy() {\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach(block => {\n block.addEventListener('click', async function(e) {\n if (e.target.classList.contains('copy-button')) {\n try {\n await navigator.clipboard.writeText(block.textContent);\n showToast('\u590d\u5236\u6210\u529f\uff01');\n } catch (err) {\n showToast('\u590d\u5236\u5931\u8d25', 'error');\n }\n }\n });\n });\n}\n\n// \u56fe\u7247\u7f29\u653e\u529f\u80fd\nfunction setupImageZoom() {\n const images = document.querySelectorAll('.md-content img');\n\n images.forEach(img => {\n img.addEventListener('click', function() {\n const overlay = document.createElement('div');\n overlay.className = 'image-overlay';\n overlay.innerHTML = `\n <img src=\"${img.src}\" alt=\"${img.alt}\">\n <button class=\"close-button\">\u00d7</button>\n `;\n\n document.body.appendChild(overlay);\n\n overlay.querySelector('.close-button').addEventListener('click', () => {\n overlay.remove();\n });\n });\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6313","title":"6.3.1.3 \u952e\u76d8\u4e8b\u4ef6","text":"JavaScript// docs/javascripts/keyboard.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u952e\u76d8\u5bfc\u822a\n setupKeyboardNav();\n\n // \u641c\u7d22\u5feb\u6377\u952e\n setupSearchShortcut();\n});\n\n// \u952e\u76d8\u5bfc\u822a\nfunction setupKeyboardNav() {\n document.addEventListener('keydown', function(e) {\n // ALT + \u65b9\u5411\u952e\u5bfc\u822a\n if (e.altKey) {\n switch(e.key) {\n case 'ArrowLeft': // \u4e0a\u4e00\u9875\n navigatePage('prev');\n break;\n case 'ArrowRight': // \u4e0b\u4e00\u9875\n navigatePage('next');\n break;\n case 'ArrowUp': // \u56de\u5230\u9876\u90e8\n window.scrollTo({top: 0, behavior: 'smooth'});\n break;\n case 'ArrowDown': // \u5230\u8fbe\u5e95\u90e8\n window.scrollTo({\n top: document.documentElement.scrollHeight,\n behavior: 'smooth'\n });\n break;\n }\n }\n });\n}\n\n// \u641c\u7d22\u5feb\u6377\u952e\nfunction setupSearchShortcut() {\n document.addEventListener('keydown', function(e) {\n // \u6309\u4e0b '/' \u952e\u89e6\u53d1\u641c\u7d22\n if (e.key === '/' && !e.ctrlKey && !e.altKey && !e.metaKey) {\n e.preventDefault();\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.focus();\n }\n }\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#632","title":"6.3.2 \u52a8\u753b\u6548\u679c","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6321","title":"6.3.2.1 \u8fc7\u6e21\u52a8\u753b","text":"/* docs/stylesheets/transitions.css */\n\n/* \u9875\u9762\u5207\u6362\u8fc7\u6e21 */\n.md-content {\n animation: fadeIn 0.3s ease-in-out;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* \u5bfc\u822a\u8fc7\u6e21 */\n.md-nav__link {\n transition: color 0.2s ease, padding-left 0.2s ease;\n}\n\n.md-nav__link:hover {\n padding-left: 0.5rem;\n color: var(--md-accent-fg-color);\n}\n
// docs/javascripts/transitions.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u9875\u9762\u5207\u6362\u52a8\u753b\n setupPageTransitions();\n});\n\nfunction setupPageTransitions() {\n // \u76d1\u542c\u9875\u9762\u5207\u6362\u4e8b\u4ef6\n document.addEventListener('DOMContentLoaded', function() {\n document.body.classList.add('page-transition-ready');\n });\n\n // \u9875\u9762\u79bb\u5f00\u52a8\u753b\n window.addEventListener('beforeunload', function() {\n document.body.classList.add('page-transition-exit');\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6322","title":"6.3.2.2 \u52a0\u8f7d\u52a8\u753b","text":"/* docs/stylesheets/loading.css */\n\n/* \u52a0\u8f7d\u52a8\u753b\u5bb9\u5668 */\n.loading-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--md-default-bg-color);\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 999;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n/* \u52a0\u8f7d\u52a8\u753b */\n.loading-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid var(--md-primary-fg-color--light);\n border-top-color: var(--md-primary-fg-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n
// docs/javascripts/loading.js\nclass LoadingManager {\n constructor() {\n this.overlay = null;\n this.createLoadingOverlay();\n }\n\n createLoadingOverlay() {\n this.overlay = document.createElement('div');\n this.overlay.className = 'loading-overlay';\n this.overlay.innerHTML = '<div class=\"loading-spinner\"></div>';\n document.body.appendChild(this.overlay);\n }\n\n show() {\n this.overlay.style.opacity = '1';\n this.overlay.style.visibility = 'visible';\n }\n\n hide() {\n this.overlay.style.opacity = '0';\n setTimeout(() => {\n this.overlay.style.visibility = 'hidden';\n }, 300);\n }\n}\n\n// \u4f7f\u7528\u52a0\u8f7d\u7ba1\u7406\u5668\nconst loading = new LoadingManager();\n\n// \u9875\u9762\u52a0\u8f7d\u5b8c\u6210\u540e\u9690\u85cf\nwindow.addEventListener('load', () => {\n loading.hide();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6323","title":"6.3.2.3 \u4ea4\u4e92\u52a8\u753b","text":"// docs/javascripts/interactions.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6309\u94ae\u6ce2\u7eb9\u6548\u679c\n setupRippleEffect();\n\n // \u5361\u7247\u60ac\u6d6e\u6548\u679c\n setupCardHover();\n\n // \u5217\u8868\u9879\u52a8\u753b\n setupListAnimations();\n});\n\n// \u6ce2\u7eb9\u6548\u679c\nfunction setupRippleEffect() {\n const buttons = document.querySelectorAll('.md-button');\n\n buttons.forEach(button => {\n button.addEventListener('click', function(e) {\n const ripple = document.createElement('div');\n ripple.className = 'ripple';\n\n const rect = button.getBoundingClientRect();\n const size = Math.max(rect.width, rect.height);\n\n ripple.style.width = ripple.style.height = `${size}px`;\n ripple.style.left = `${e.clientX - rect.left - size/2}px`;\n ripple.style.top = `${e.clientY - rect.top - size/2}px`;\n\n button.appendChild(ripple);\n\n setTimeout(() => ripple.remove(), 600);\n });\n });\n}\n\n// \u5361\u7247\u60ac\u6d6e\u6548\u679c\nfunction setupCardHover() {\n const cards = document.querySelectorAll('.md-card');\n\n cards.forEach(card => {\n card.addEventListener('mousemove', function(e) {\n const rect = card.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const centerX = rect.width / 2;\n const centerY = rect.height / 2;\n\n const angleY = -(x - centerX) / 20;\n const angleX = (y - centerY) / 20;\n\n card.style.transform = \n `perspective(1000px) rotateX(${angleX}deg) rotateY(${angleY}deg)`;\n });\n\n card.addEventListener('mouseleave', function() {\n card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';\n });\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#633","title":"6.3.3 \u6570\u636e\u7edf\u8ba1","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6331","title":"6.3.3.1 \u8bbf\u95ee\u7edf\u8ba1","text":"// docs/javascripts/analytics.js\nclass Analytics {\n constructor() {\n this.storageKey = 'site_analytics';\n this.data = this.loadData();\n }\n\n loadData() {\n const stored = localStorage.getItem(this.storageKey);\n return stored ? JSON.parse(stored) : {\n pageViews: {},\n totalVisits: 0,\n firstVisit: Date.now(),\n lastVisit: Date.now()\n };\n }\n\n saveData() {\n localStorage.setItem(this.storageKey, JSON.stringify(this.data));\n }\n\n recordPageView() {\n const path = window.location.pathname;\n this.data.pageViews[path] = (this.data.pageViews[path] || 0) + 1;\n this.data.totalVisits++;\n this.data.lastVisit = Date.now();\n this.saveData();\n }\n\n getStats() {\n return {\n totalVisits: this.data.totalVisits,\n uniquePages: Object.keys(this.data.pageViews).length,\n mostViewed: this.getMostViewedPages(5)\n };\n }\n\n getMostViewedPages(limit = 5) {\n return Object.entries(this.data.pageViews)\n .sort(([,a], [,b]) => b - a)\n .slice(0, limit);\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6332","title":"6.3.3.2 \u9605\u8bfb\u65f6\u957f","text":"JavaScript// docs/javascripts/read-time.js\nclass ReadTimeTracker {\n constructor() {\n this.startTime = Date.now();\n this.isReading = true;\n this.totalTime = 0;\n this.idleTimeout = null;\n this.setupTracking();\n }\n\n setupTracking() {\n // \u76d1\u542c\u7528\u6237\u6d3b\u52a8\n ['mousemove', 'keydown', 'scroll', 'click'].forEach(event => {\n document.addEventListener(event, () => this.handleActivity());\n });\n\n // \u9875\u9762\u5931\u7126\u6682\u505c\u8ba1\u65f6\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) {\n this.pauseTracking();\n } else {\n this.resumeTracking();\n }\n });\n }\n\n handleActivity() {\n if (!this.isReading) {\n this.resumeTracking();\n }\n\n clearTimeout(this.idleTimeout);\n this.idleTimeout = setTimeout(() => this.pauseTracking(), 60000); // 1\u5206\u949f\u65e0\u6d3b\u52a8\u6682\u505c\n }\n\n pauseTracking() {\n if (this.isReading) {\n this.totalTime += Date.now() - this.startTime;\n this.isReading = false;\n }\n }\n\n resumeTracking() {\n if (!this.isReading) {\n this.startTime = Date.now();\n this.isReading = true;\n }\n }\n\n getReadTime() {\n const currentTime = this.isReading ? \n this.totalTime + (Date.now() - this.startTime) : \n this.totalTime;\n\n return Math.floor(currentTime / 1000 / 60); // \u8fd4\u56de\u5206\u949f\n // \u663e\u793a\u9605\u8bfb\u65f6\u957f\n displayReadTime() {\n const readTimeElement = document.querySelector('.read-time');\n if (readTimeElement) {\n const minutes = this.getReadTime();\n readTimeElement.textContent = `\u9605\u8bfb\u65f6\u957f: ${minutes} \u5206\u949f`;\n }\n }\n\n // \u83b7\u53d6\u9605\u8bfb\u8fdb\u5ea6\n getReadProgress() {\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight - windowHeight;\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return Math.min((scrollTop / docHeight) * 100, 100);\n }\n\n // \u4fdd\u5b58\u9605\u8bfb\u8bb0\u5f55\n saveReadingHistory() {\n const path = window.location.pathname;\n const history = JSON.parse(localStorage.getItem('reading_history') || '{}');\n\n history[path] = {\n lastRead: Date.now(),\n readTime: this.getReadTime(),\n progress: this.getReadProgress()\n };\n\n localStorage.setItem('reading_history', JSON.stringify(history));\n }\n}\n\n// \u521d\u59cb\u5316\u9605\u8bfb\u65f6\u957f\u8ffd\u8e2a\nconst readTracker = new ReadTimeTracker();\n\n// \u5b9a\u671f\u66f4\u65b0\u663e\u793a\nsetInterval(() => {\n readTracker.displayReadTime();\n}, 30000); // \u6bcf30\u79d2\u66f4\u65b0\u4e00\u6b21\n\n// \u9875\u9762\u79bb\u5f00\u65f6\u4fdd\u5b58\u8bb0\u5f55\nwindow.addEventListener('beforeunload', () => {\n readTracker.saveReadingHistory();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6333","title":"6.3.3.3 \u5206\u4eab\u7edf\u8ba1","text":"// docs/javascripts/share.js\nclass ShareTracker {\n constructor() {\n this.storageKey = 'share_statistics';\n this.data = this.loadData();\n this.setupShareButtons();\n }\n\n loadData() {\n return JSON.parse(localStorage.getItem(this.storageKey) || '{}');\n }\n\n saveData() {\n localStorage.setItem(this.storageKey, JSON.stringify(this.data));\n }\n\n setupShareButtons() {\n const shareButtons = document.querySelectorAll('.share-button');\n\n shareButtons.forEach(button => {\n button.addEventListener('click', (e) => {\n const platform = button.dataset.platform;\n this.shareContent(platform);\n this.recordShare(platform);\n });\n });\n }\n\n shareContent(platform) {\n const url = encodeURIComponent(window.location.href);\n const title = encodeURIComponent(document.title);\n const description = encodeURIComponent(\n document.querySelector('meta[name=\"description\"]')?.content || ''\n );\n\n let shareUrl;\n switch (platform) {\n case 'twitter':\n shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;\n break;\n case 'facebook':\n shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;\n break;\n case 'linkedin':\n shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;\n break;\n case 'weibo':\n shareUrl = `http://service.weibo.com/share/share.php?url=${url}&title=${title}`;\n break;\n }\n\n if (shareUrl) {\n window.open(shareUrl, '_blank', 'width=600,height=400');\n }\n }\n\n recordShare(platform) {\n const path = window.location.pathname;\n if (!this.data[path]) {\n this.data[path] = {};\n }\n if (!this.data[path][platform]) {\n this.data[path][platform] = 0;\n }\n this.data[path][platform]++;\n this.saveData();\n this.updateShareCount(platform);\n }\n\n updateShareCount(platform) {\n const countElement = document.querySelector(`.share-count[data-platform=\"${platform}\"]`);\n if (countElement) {\n const path = window.location.pathname;\n countElement.textContent = this.data[path][platform] || 0;\n }\n }\n\n getShareStats() {\n return Object.entries(this.data).map(([path, platforms]) => ({\n path,\n total: Object.values(platforms).reduce((a, b) => a + b, 0),\n platforms\n }));\n }\n\n displayShareStats() {\n const stats = this.getShareStats();\n console.table(stats);\n return stats;\n }\n}\n
// docs/javascripts/statistics-visualization.js\nclass StatisticsVisualizer {\n constructor(analytics, readTracker, shareTracker) {\n this.analytics = analytics;\n this.readTracker = readTracker;\n this.shareTracker = shareTracker;\n }\n\n createDashboard() {\n const dashboard = document.createElement('div');\n dashboard.className = 'statistics-dashboard';\n dashboard.innerHTML = `\n <div class=\"dashboard-section\">\n <h3>\u8bbf\u95ee\u7edf\u8ba1</h3>\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.analytics.data.totalVisits}</div>\n <div class=\"stat-label\">\u603b\u8bbf\u95ee\u91cf</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.readTracker.getReadTime()}</div>\n <div class=\"stat-label\">\u603b\u9605\u8bfb\u65f6\u957f(\u5206\u949f)</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.getTotalShares()}</div>\n <div class=\"stat-label\">\u603b\u5206\u4eab\u6b21\u6570</div>\n </div>\n </div>\n <div id=\"visitsChart\"></div>\n </div>\n `;\n\n document.body.appendChild(dashboard);\n this.renderCharts();\n }\n\n renderCharts() {\n // \u4f7f\u7528 Chart.js \u7ed8\u5236\u56fe\u8868\n const ctx = document.getElementById('visitsChart').getContext('2d');\n new Chart(ctx, {\n type: 'line',\n data: {\n labels: this.getTimeLabels(),\n datasets: [{\n label: '\u8bbf\u95ee\u8d8b\u52bf',\n data: this.getVisitData(),\n borderColor: 'rgb(75, 192, 192)',\n tension: 0.1\n }]\n },\n options: {\n responsive: true,\n scales: {\n y: {\n beginAtZero: true\n }\n }\n }\n });\n }\n\n getTotalShares() {\n const stats = this.shareTracker.getShareStats();\n return stats.reduce((total, page) => total + page.total, 0);\n }\n\n getTimeLabels() {\n // \u83b7\u53d6\u6700\u8fd17\u5929\u7684\u65e5\u671f\u6807\u7b7e\n return Array.from({length: 7}, (_, i) => {\n const d = new Date();\n d.setDate(d.getDate() - i);\n return d.toLocaleDateString();\n }).reverse();\n }\n\n getVisitData() {\n // \u5904\u7406\u8bbf\u95ee\u6570\u636e\n return this.analytics.getVisitsByDate(7);\n }\n}\n\n// \u6837\u5f0f\nconst styles = `\n .statistics-dashboard {\n padding: 2rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z2);\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1rem;\n margin: 1rem 0;\n }\n\n .stat-card {\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n text-align: center;\n }\n\n .stat-value {\n font-size: 2rem;\n font-weight: bold;\n color: var(--md-primary-fg-color);\n }\n\n .stat-label {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.5rem;\n }\n`;\n\n// \u5c06\u6837\u5f0f\u6dfb\u52a0\u5230\u6587\u6863\nconst styleSheet = document.createElement('style');\nstyleSheet.textContent = styles;\ndocument.head.appendChild(styleSheet);\n\n// \u521d\u59cb\u5316\u7edf\u8ba1\u53ef\u89c6\u5316\nconst visualizer = new StatisticsVisualizer(analytics, readTracker, shareTracker);\nvisualizer.createDashboard();\n
\u8fd9\u6837\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u5b8c\u6574\u7684\u6570\u636e\u7edf\u8ba1\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u4f7f\u7528\u65f6\uff0c\u53ea\u9700\u8981\u5728 mkdocs.yml \u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684 JavaScript \u6587\u4ef6\uff1a
YAMLextra_javascript:\n - javascripts/analytics.js\n - javascripts/read-time.js\n - javascripts/share.js\n - javascripts/statistics-visualization.js\n - https://cdn.jsdelivr.net/npm/chart.js\n
\u7136\u540e\u5728\u9875\u9762\u4e2d\u6dfb\u52a0\u5fc5\u8981\u7684 HTML \u5143\u7d20\u5373\u53ef\u542f\u7528\u8fd9\u4e9b\u529f\u80fd\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#7","title":"7 \u6a21\u677f\u590d\u5199","text":""},{"location":"Tools/Blog/Mkdocs_Material/#71","title":"7.1 \u91cd\u5199\u9875\u9762\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#711","title":"7.1.1 \u4e3b\u9875\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7111","title":"7.1.1.1 \u5e03\u5c40\u7ed3\u6784","text":"<!-- docs/overrides/main.html -->\n{% extends \"base.html\" %}\n\n{% block hero %}\n<section class=\"home-hero\">\n <div class=\"hero-content\">\n <h1>{{ config.site_name }}</h1>\n <p>{{ config.site_description }}</p>\n\n <!-- \u81ea\u5b9a\u4e49\u641c\u7d22\u6846 -->\n <div class=\"hero-search\">\n <input type=\"text\" placeholder=\"\u641c\u7d22\u6587\u6863...\" id=\"hero-search-input\">\n <button>\n <span class=\"twemoji\">\n {% include \".icons/material/magnify.svg\" %}\n </span>\n </button>\n </div>\n\n <!-- \u5feb\u901f\u5165\u53e3 -->\n <div class=\"hero-buttons\">\n <a href=\"{{ page.next_page.url | url }}\" class=\"md-button md-button--primary\">\n \u5feb\u901f\u5f00\u59cb\n <span class=\"twemoji\">\n {% include \".icons/material/arrow-right.svg\" %}\n </span>\n </a>\n <a href=\"{{ config.repo_url }}\" class=\"md-button\">\n \u67e5\u770b\u6e90\u7801\n <span class=\"twemoji\">\n {% include \".icons/material/github.svg\" %}\n </span>\n </a>\n </div>\n </div>\n</section>\n{% endblock %}\n\n{% block content %}\n<section class=\"home-features\">\n <h2>\u7279\u8272\u529f\u80fd</h2>\n <div class=\"features-grid\">\n <!-- \u529f\u80fd\u5361\u7247 -->\n <div class=\"feature-card\">\n <div class=\"feature-icon\">\n {% include \".icons/material/speedometer.svg\" %}\n </div>\n <h3>\u9ad8\u6027\u80fd</h3>\n <p>\u57fa\u4e8e\u9759\u6001\u7ad9\u70b9\u751f\u6210\uff0c\u52a0\u8f7d\u8fc5\u901f</p>\n </div>\n <!-- \u66f4\u591a\u529f\u80fd\u5361\u7247 -->\n </div>\n</section>\n\n<!-- \u6700\u8fd1\u66f4\u65b0 -->\n<section class=\"home-updates\">\n <h2>\u6700\u8fd1\u66f4\u65b0</h2>\n <div class=\"updates-list\">\n {% for update in config.theme.updates[:5] %}\n <div class=\"update-item\">\n <span class=\"update-date\">{{ update.date }}</span>\n <a href=\"{{ update.url | url }}\">{{ update.title }}</a>\n </div>\n {% endfor %}\n </div>\n</section>\n{% endblock %}\n
/* docs/stylesheets/home.css */\n\n/* \u4e3b\u9875\u82f1\u96c4\u533a */\n.home-hero {\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n background: linear-gradient(\n to bottom right,\n var(--md-primary-fg-color),\n var(--md-accent-fg-color)\n );\n color: var(--md-primary-bg-color);\n}\n\n.hero-content {\n max-width: 800px;\n padding: 2rem;\n}\n\n.hero-content h1 {\n font-size: 3rem;\n margin-bottom: 1rem;\n}\n\n/* \u641c\u7d22\u6846\u6837\u5f0f */\n.hero-search {\n margin: 2rem 0;\n position: relative;\n}\n\n.hero-search input {\n width: 100%;\n padding: 1rem 3rem 1rem 1rem;\n border: none;\n border-radius: 2rem;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n backdrop-filter: blur(10px);\n}\n\n/* \u529f\u80fd\u533a\u6837\u5f0f */\n.features-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 2rem;\n padding: 2rem;\n}\n\n.feature-card {\n padding: 2rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n transition: transform 0.3s ease;\n}\n\n.feature-card:hover {\n transform: translateY(-4px);\n}\n\n/* \u66f4\u65b0\u5217\u8868\u6837\u5f0f */\n.updates-list {\n max-width: 800px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.update-item {\n display: flex;\n align-items: center;\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .hero-content h1 {\n font-size: 2rem;\n }\n\n .features-grid {\n grid-template-columns: 1fr;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7112","title":"7.1.1.2 \u7ec4\u4ef6\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\u4e3b\u9898\uff1atheme:\n name: material\n custom_dir: docs/overrides\n features:\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n\n # \u4e3b\u9875\u914d\u7f6e\n homepage:\n hero:\n title: \u7f51\u7ad9\u6807\u9898\n subtitle: \u7f51\u7ad9\u63cf\u8ff0\n image: assets/hero.svg\n\n # \u529f\u80fd\u7279\u6027\n features:\n - title: \u9ad8\u6027\u80fd\n description: \u57fa\u4e8e\u9759\u6001\u7ad9\u70b9\u751f\u6210\uff0c\u52a0\u8f7d\u8fc5\u901f\n icon: material/speedometer\n - title: \u6613\u4e8e\u4f7f\u7528\n description: \u7b80\u5355\u7684\u914d\u7f6e\uff0c\u5feb\u901f\u4e0a\u624b\n icon: material/puzzle\n # \u66f4\u591a\u529f\u80fd\u7279\u6027...\n\n # \u66f4\u65b0\u5217\u8868\n updates:\n - date: 2024-01-20\n title: \u65b0\u589e\u529f\u80fdA\n url: /new-feature-a\n - date: 2024-01-18\n title: \u95ee\u9898\u4fee\u590dB\n url: /bug-fix-b\n # \u66f4\u591a\u66f4\u65b0...\n
// docs/javascripts/home.js\nclass HomePage {\n constructor() {\n this.searchInput = document.getElementById('hero-search-input');\n this.setupSearch();\n this.setupFeatureCards();\n }\n\n setupSearch() {\n this.searchInput?.addEventListener('keyup', (e) => {\n if (e.key === 'Enter') {\n const query = e.target.value;\n window.location.href = `${window.location.origin}/search.html?q=${encodeURIComponent(query)}`;\n }\n });\n }\n\n setupFeatureCards() {\n const cards = document.querySelectorAll('.feature-card');\n\n cards.forEach(card => {\n card.addEventListener('mousemove', (e) => {\n const rect = card.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n card.style.setProperty('--mouse-x', `${x}px`);\n card.style.setProperty('--mouse-y', `${y}px`);\n });\n });\n }\n}\n\n// \u521d\u59cb\u5316\u4e3b\u9875\ndocument.addEventListener('DOMContentLoaded', () => {\n new HomePage();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7113","title":"7.1.1.3 \u81ea\u5b9a\u4e49\u533a\u57df","text":"<!-- docs/overrides/partials/custom-content.html -->\n{% if page.meta.custom_content %}\n<section class=\"custom-content\">\n <!-- \u516c\u544a\u533a -->\n {% if page.meta.announcements %}\n <div class=\"announcements\">\n {% for announcement in page.meta.announcements %}\n <div class=\"announcement-item\">\n <span class=\"announcement-tag\">{{ announcement.tag }}</span>\n <p>{{ announcement.content }}</p>\n </div>\n {% endfor %}\n </div>\n {% endif %}\n\n <!-- \u8d21\u732e\u8005\u533a\u57df -->\n {% if page.meta.contributors %}\n <div class=\"contributors\">\n <h3>\u9879\u76ee\u8d21\u732e\u8005</h3>\n <div class=\"contributors-grid\">\n {% for contributor in page.meta.contributors %}\n <a href=\"{{ contributor.url }}\" class=\"contributor-card\">\n <img src=\"{{ contributor.avatar }}\" alt=\"{{ contributor.name }}\">\n <span>{{ contributor.name }}</span>\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n\n <!-- \u8d5e\u52a9\u5546\u533a\u57df -->\n {% if page.meta.sponsors %}\n <div class=\"sponsors\">\n <h3>\u8d5e\u52a9\u5546</h3>\n <div class=\"sponsors-grid\">\n {% for sponsor in page.meta.sponsors %}\n <a href=\"{{ sponsor.url }}\" class=\"sponsor-card\">\n <img src=\"{{ sponsor.logo }}\" alt=\"{{ sponsor.name }}\">\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n</section>\n{% endif %}\n
/* docs/stylesheets/custom-content.css */\n\n/* \u516c\u544a\u533a\u57df */\n.announcements {\n margin: 2rem 0;\n}\n\n.announcement-item {\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n margin-bottom: 1rem;\n}\n\n.announcement-tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n background: var(--md-accent-fg-color);\n color: white;\n border-radius: 2rem;\n font-size: 0.8rem;\n margin-right: 0.5rem;\n}\n\n/* \u8d21\u732e\u8005\u533a\u57df */\n.contributors-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 1rem;\n margin: 1rem 0;\n}\n\n.contributor-card {\n text-align: center;\n text-decoration: none;\n color: var(--md-default-fg-color);\n}\n\n.contributor-card img {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n margin-bottom: 0.5rem;\n}\n\n/* \u8d5e\u52a9\u5546\u533a\u57df */\n.sponsors-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 2rem;\n margin: 1rem 0;\n}\n\n.sponsor-card img {\n width: 100%;\n height: auto;\n filter: grayscale(100%);\n transition: filter 0.3s ease;\n}\n\n.sponsor-card:hover img {\n filter: grayscale(0%);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#712","title":"7.1.2 \u6587\u7ae0\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7121","title":"7.1.2.1 \u6587\u7ae0\u5934\u90e8","text":"HTML<!-- docs/overrides/partials/article-header.html -->\n<header class=\"article-header\">\n <!-- \u6587\u7ae0\u6807\u9898 -->\n <h1>{{ page.title }}</h1>\n\n <!-- \u6587\u7ae0\u5143\u4fe1\u606f -->\n <div class=\"article-meta\">\n {% if page.meta.author %}\n <div class=\"meta-item\">\n <span class=\"meta-icon\">\n {% include \".icons/material/account.svg\" %}\n </span>\n <span>{{ page.meta.author }}</span>\n </div>\n {% endif %}\n\n {% if page.meta.date %}\n <div class=\"meta-item\">\n <span class=\"meta-icon\">\n {% include \".icons/material/calendar.svg\" %}\n </span>\n <span>{{ page.meta.date }}</span>\n </div>\n {% endif %}\n\n {% if page.meta.tags %}\n <div class=\"article-tags\">\n {% for tag in page.meta.tags %}\n <a href=\"{{ base_url }}/tags/#{{ tag }}\" class=\"tag\">\n # {{ tag }}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n </div>\n\n <!-- \u6587\u7ae0\u6982\u8ff0 -->\n {% if page.meta.description %}\n <div class=\"article-description\">\n {{ page.meta.description }}\n </div>\n {% endif %}\n</header>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7122","title":"7.1.2.2 \u6b63\u6587\u6837\u5f0f","text":"CSS/* docs/stylesheets/article.css */\n\n/* \u6587\u7ae0\u5bb9\u5668 */\n.md-content article {\n max-width: 800px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n/* \u6587\u7ae0\u5934\u90e8 */\n.article-header {\n margin-bottom: 3rem;\n text-align: center;\n}\n\n.article-meta {\n display: flex;\n justify-content: center;\n gap: 1rem;\n margin: 1rem 0;\n color: var(--md-default-fg-color--light);\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.article-tags {\n margin-top: 1rem;\n}\n\n.tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n margin: 0.2rem;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n font-size: 0.8rem;\n}\n\n/* \u6587\u7ae0\u5185\u5bb9\u6837\u5f0f */\n.md-content article {\n font-size: 1.1rem;\n line-height: 1.8;\n}\n\n/* \u6807\u9898\u6837\u5f0f */\n.md-content article h2 {\n margin-top: 3rem;\n padding-bottom: 0.5rem;\n border-bottom: 2px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u4ee3\u7801\u5757\u6837\u5f0f */\n.md-content pre {\n border-radius: 8px;\n margin: 1.5rem 0;\n}\n\n/* \u5f15\u7528\u6837\u5f0f */\n.md-content blockquote {\n border-left: 4px solid var(--md-accent-fg-color);\n padding: 1rem;\n background: var(--md-code-bg-color);\n margin: 1.5rem 0;\n}\n\n/* \u56fe\u7247\u6837\u5f0f */\n.md-content img {\n max-width: 100%;\n border-radius: 8px;\n margin: 1.5rem 0;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7123","title":"7.1.2.3 \u5e95\u90e8\u4fe1\u606f","text":"HTML<!-- docs/overrides/partials/article-footer.html -->\n<footer class=\"article-footer\">\n <!-- \u6587\u7ae0\u5bfc\u822a -->\n <nav class=\"article-nav\">\n {% if page.previous_page %}\n <a href=\"{{ page.previous_page.url | url }}\" class=\"nav-link nav-prev\">\n <span class=\"nav-icon\">\n {% include \".icons/material/arrow-left.svg\" %}\n </span>\n <span class=\"nav-text\">\n <span class=\"nav-direction\">\u4e0a\u4e00\u7bc7</span>\n <span class=\"nav-title\">{{ page.previous_page.title }}</span>\n </span>\n </a>\n {% endif %}\n\n {% if page.next_page %}\n <a href=\"{{ page.next_page.url | url }}\" class=\"nav-link nav-next\">\n <span class=\"nav-text\">\n <span class=\"nav-direction\">\u4e0b\u4e00\u7bc7</span>\n <span class=\"nav-title\">{{ page.next_page.title }}</span>\n </span>\n <span class=\"nav-icon\">\n {% include \".icons/material/arrow-right.svg\" %}\n </span>\n </a>\n {% endif %}\n </nav>\n\n <!-- \u5206\u4eab\u6309\u94ae -->\n <div class=\"article-share\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n <button class=\"share-button\" data-platform=\"twitter\">\n {% include \".icons/material/twitter.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"facebook\">\n {% include \".icons/material/facebook.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"linkedin\">\n {% include \".icons/material/linkedin.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"weibo\">\n {% include \".icons/material/sina-weibo.svg\" %}\n </button>\n </div>\n </div>\n\n <!-- \u76f8\u5173\u6587\u7ae0 -->\n {% if page.meta.related_posts %}\n <div class=\"related-posts\">\n <h4>\u76f8\u5173\u6587\u7ae0</h4>\n <div class=\"related-grid\">\n {% for post in page.meta.related_posts %}\n <a href=\"{{ post.url | url }}\" class=\"related-post\">\n {% if post.image %}\n <img src=\"{{ post.image }}\" alt=\"{{ post.title }}\">\n {% endif %}\n <h5>{{ post.title }}</h5>\n <p>{{ post.excerpt }}</p>\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n\n <!-- \u8bc4\u8bba\u533a -->\n <div class=\"article-comments\">\n <h4>\u8bc4\u8bba</h4>\n {% if config.extra.comments.provider == 'giscus' %}\n <script src=\"https://giscus.app/client.js\"\n data-repo=\"{{ config.extra.comments.repo }}\"\n data-repo-id=\"{{ config.extra.comments.repo_id }}\"\n data-category=\"{{ config.extra.comments.category }}\"\n data-category-id=\"{{ config.extra.comments.category_id }}\"\n data-mapping=\"pathname\"\n data-reactions-enabled=\"1\"\n data-emit-metadata=\"0\"\n data-theme=\"light\"\n crossorigin=\"anonymous\"\n async>\n </script>\n {% endif %}\n </div>\n</footer>\n\n<!-- \u6587\u7ae0\u5e95\u90e8\u6837\u5f0f -->\n<style>\n.article-footer {\n margin-top: 4rem;\n padding-top: 2rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u6587\u7ae0\u5bfc\u822a */\n.article-nav {\n display: flex;\n justify-content: space-between;\n margin-bottom: 2rem;\n}\n\n.nav-link {\n display: flex;\n align-items: center;\n padding: 1rem;\n text-decoration: none;\n color: var(--md-default-fg-color);\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n max-width: 45%;\n}\n\n.nav-link:hover {\n transform: translateY(-2px);\n}\n\n.nav-text {\n display: flex;\n flex-direction: column;\n}\n\n.nav-direction {\n font-size: 0.8rem;\n color: var(--md-default-fg-color--light);\n}\n\n.nav-title {\n font-weight: 500;\n}\n\n/* \u5206\u4eab\u6309\u94ae */\n.share-buttons {\n display: flex;\n gap: 1rem;\n margin: 1rem 0;\n}\n\n.share-button {\n padding: 0.8rem;\n border: none;\n border-radius: 50%;\n background: var(--md-code-bg-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n\n/* \u76f8\u5173\u6587\u7ae0 */\n.related-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin: 1rem 0;\n}\n\n.related-post {\n text-decoration: none;\n color: var(--md-default-fg-color);\n background: var(--md-code-bg-color);\n border-radius: 8px;\n overflow: hidden;\n transition: transform 0.2s ease;\n}\n\n.related-post:hover {\n transform: translateY(-4px);\n}\n\n.related-post img {\n width: 100%;\n height: 150px;\n object-fit: cover;\n}\n\n.related-post h5 {\n margin: 1rem;\n font-size: 1.1rem;\n}\n\n.related-post p {\n margin: 0 1rem 1rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u8bc4\u8bba\u533a */\n.article-comments {\n margin-top: 3rem;\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .article-nav {\n flex-direction: column;\n gap: 1rem;\n }\n\n .nav-link {\n max-width: 100%;\n }\n\n .related-grid {\n grid-template-columns: 1fr;\n }\n}\n</style>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#713-404","title":"7.1.3 404\u9875\u9762","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7131","title":"7.1.3.1 \u9519\u8bef\u63d0\u793a","text":"HTML<!-- docs/overrides/404.html -->\n{% extends \"base.html\" %}\n\n{% block content %}\n<div class=\"error-page\">\n <div class=\"error-content\">\n <!-- 404 \u56fe\u6807 -->\n <div class=\"error-icon\">\n {% include \".icons/material/alert-circle-outline.svg\" %}\n <span class=\"error-code\">404</span>\n </div>\n\n <!-- \u9519\u8bef\u4fe1\u606f -->\n <h1>\u9875\u9762\u672a\u627e\u5230</h1>\n <p>\u62b1\u6b49\uff0c\u60a8\u8bbf\u95ee\u7684\u9875\u9762\u4e0d\u5b58\u5728\u6216\u5df2\u88ab\u79fb\u52a8</p>\n\n <!-- \u641c\u7d22\u6846 -->\n <div class=\"error-search\">\n <input type=\"text\" \n id=\"error-search-input\" \n placeholder=\"\u5c1d\u8bd5\u641c\u7d22...\"\n autocomplete=\"off\">\n <button id=\"error-search-button\">\n {% include \".icons/material/magnify.svg\" %}\n </button>\n </div>\n\n <!-- \u5feb\u6377\u64cd\u4f5c -->\n <div class=\"error-actions\">\n <a href=\"{{ base_url }}\" class=\"md-button md-button--primary\">\n \u8fd4\u56de\u9996\u9875\n </a>\n <button class=\"md-button\" onclick=\"window.history.back()\">\n \u8fd4\u56de\u4e0a\u9875\n </button>\n </div>\n </div>\n\n <!-- \u641c\u7d22\u5efa\u8bae -->\n <div class=\"search-suggestions\" id=\"search-suggestions\">\n <h3>\u60a8\u662f\u5426\u5728\u627e\uff1a</h3>\n <div class=\"suggestions-list\" id=\"suggestions-list\">\n <!-- \u52a8\u6001\u751f\u6210\u7684\u5efa\u8bae\u5217\u8868 -->\n </div>\n </div>\n</div>\n\n<!-- 404\u9875\u9762\u6837\u5f0f -->\n<style>\n.error-page {\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n text-align: center;\n}\n\n.error-content {\n max-width: 600px;\n}\n\n.error-icon {\n font-size: 6rem;\n color: var(--md-primary-fg-color);\n margin-bottom: 2rem;\n position: relative;\n}\n\n.error-code {\n position: absolute;\n bottom: -1rem;\n right: -1rem;\n font-size: 2rem;\n font-weight: bold;\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0.5rem 1rem;\n border-radius: 1rem;\n}\n\n.error-search {\n margin: 2rem 0;\n position: relative;\n}\n\n.error-search input {\n width: 100%;\n padding: 1rem 3rem 1rem 1rem;\n border: 2px solid var(--md-default-fg-color--lightest);\n border-radius: 2rem;\n font-size: 1.1rem;\n}\n\n.error-search button {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: var(--md-default-fg-color);\n cursor: pointer;\n}\n\n.error-actions {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin: 2rem 0;\n}\n\n/* \u641c\u7d22\u5efa\u8bae\u6837\u5f0f */\n.search-suggestions {\n margin-top: 3rem;\n width: 100%;\n max-width: 600px;\n}\n\n.suggestions-list {\n margin-top: 1rem;\n}\n\n.suggestion-item {\n padding: 1rem;\n margin: 0.5rem 0;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.suggestion-item:hover {\n background: var(--md-accent-fg-color--transparent);\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .error-icon {\n font-size: 4rem;\n }\n\n .error-code {\n font-size: 1.5rem;\n }\n\n .error-actions {\n flex-direction: column;\n }\n}\n</style>\n\n<!-- 404\u9875\u9762\u811a\u672c -->\n<script>\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u641c\u7d22\u5efa\u8bae\u529f\u80fd\n setupSearchSuggestions();\n // \u5168\u5c40\u70ed\u952e\n setupHotkeys();\n});\n\nfunction setupSearchSuggestions() {\n const searchInput = document.getElementById('error-search-input');\n const suggestionsList = document.getElementById('suggestions-list');\n\n searchInput?.addEventListener('input', debounce(async (e) => {\n const query = e.target.value;\n if (query.length < 2) {\n suggestionsList.innerHTML = '';\n return;\n }\n\n // \u83b7\u53d6\u641c\u7d22\u5efa\u8bae\n const suggestions = await getSearchSuggestions(query);\n\n // \u6e32\u67d3\u5efa\u8bae\u5217\u8868\n suggestionsList.innerHTML = suggestions\n .map(suggestion => `\n <div class=\"suggestion-item\" onclick=\"window.location.href='${suggestion.url}'\">\n <div class=\"suggestion-title\">${suggestion.title}</div>\n <div class=\"suggestion-excerpt\">${suggestion.excerpt}</div>\n </div>\n `)\n .join('');\n }, 300));\n}\n\nasync function getSearchSuggestions(query) {\n // \u8fd9\u91cc\u53ef\u4ee5\u5b9e\u73b0\u5b9e\u9645\u7684\u641c\u7d22\u903b\u8f91\n // \u793a\u4f8b\u8fd4\u56de\u6570\u636e\n return [\n {\n title: '\u76f8\u5173\u6587\u6863 1',\n excerpt: '\u8fd9\u662f\u4e00\u6bb5\u76f8\u5173\u7684\u6587\u6863\u63cf\u8ff0...',\n url: '#'\n },\n {\n title: '\u76f8\u5173\u6587\u6863 2',\n excerpt: '\u8fd9\u662f\u53e6\u4e00\u6bb5\u76f8\u5173\u7684\u6587\u6863\u63cf\u8ff0...',\n url: '#'\n }\n ];\n}\n\nfunction setupHotkeys() {\n document.addEventListener('keydown', (e) => {\n // \u6309 ESC \u8fd4\u56de\u4e0a\u9875\n if (e.key === 'Escape') {\n window.history.back();\n }\n\n // \u6309 Enter \u6267\u884c\u641c\u7d22\n if (e.key === 'Enter' && document.activeElement.id === 'error-search-input') {\n const query = document.activeElement.value;\n if (query) {\n window.location.href = `${window.location.origin}/search.html?q=${encodeURIComponent(query)}`;\n }\n }\n });\n}\n\n// \u9632\u6296\u51fd\u6570\nfunction debounce(fn, delay) {\n let timer = null;\n return function(...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n</script>\n
\u8fd9\u6837\uff0c\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u6587\u7ae0\u5e95\u90e8\u4fe1\u606f\u548c404\u9875\u9762\u7684\u6a21\u677f\u3002\u4e3b\u8981\u7279\u70b9\u5305\u62ec\uff1a
\u6587\u7ae0\u5e95\u90e8\uff1a - \u6e05\u6670\u7684\u4e0a\u4e0b\u6587\u7ae0\u5bfc\u822a - \u793e\u4ea4\u5206\u4eab\u6309\u94ae - \u76f8\u5173\u6587\u7ae0\u63a8\u8350 - \u96c6\u6210\u8bc4\u8bba\u7cfb\u7edf
404\u9875\u9762\uff1a - \u53cb\u597d\u7684\u9519\u8bef\u63d0\u793a - \u5b9e\u65f6\u641c\u7d22\u5efa\u8bae - \u591a\u79cd\u8fd4\u56de\u9009\u9879 - \u952e\u76d8\u5feb\u6377\u952e\u652f\u6301
\u4f7f\u7528\u8fd9\u4e9b\u6a21\u677f\u65f6\uff0c\u9700\u8981\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n custom_dir: docs/overrides\n features:\n - navigation.tracking\n - search.suggest\n - search.highlight\n\nextra:\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your-repo-id\n category: Comments\n category_id: your-category-id\n
"},{"location":"Tools/Blog/Mkdocs_Material/#72","title":"7.2 \u4fee\u6539\u7ec4\u4ef6\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#721","title":"7.2.1 \u5bfc\u822a\u680f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7211","title":"7.2.1.1 \u5bfc\u822a\u9879\u5b9a\u5236","text":"HTML<!-- docs/overrides/partials/nav.html -->\n{% extends \"base.html\" %}\n\n{% block site_nav %}\n<nav class=\"md-nav md-nav--primary\">\n <!-- \u81ea\u5b9a\u4e49\u5bfc\u822a\u5934\u90e8 -->\n <div class=\"nav-header\">\n {% if config.theme.logo %}\n <img src=\"{{ config.theme.logo }}\" alt=\"logo\" class=\"nav-logo\">\n {% endif %}\n <span class=\"nav-title\">{{ config.site_name }}</span>\n </div>\n\n <!-- \u81ea\u5b9a\u4e49\u5bfc\u822a\u9879 -->\n <ul class=\"nav-items\">\n {% for nav_item in nav %}\n {% include \"partials/nav-item.html\" %}\n {% endfor %}\n\n <!-- \u6dfb\u52a0\u81ea\u5b9a\u4e49\u5bfc\u822a\u9879 -->\n {% if config.extra.nav_links %}\n {% for link in config.extra.nav_links %}\n <li class=\"nav-item custom\">\n <a href=\"{{ link.url }}\" class=\"nav-link\" {% if link.target %}target=\"{{ link.target }}\"{% endif %}>\n {% if link.icon %}\n <span class=\"nav-icon\">\n {% include \".icons/\" ~ link.icon ~ \".svg\" %}\n </span>\n {% endif %}\n {{ link.title }}\n </a>\n </li>\n {% endfor %}\n {% endif %}\n </ul>\n</nav>\n
\u914d\u7f6e\u548c\u6837\u5f0f\uff1a
YAML# mkdocs.yml\nextra:\n nav_links:\n - title: GitHub\n url: https://github.com/your/repo\n icon: material/github\n target: _blank\n - title: \u6587\u6863\n url: /docs/\n icon: material/file-document\n
CSS/* docs/stylesheets/nav.css */\n.nav-header {\n display: flex;\n align-items: center;\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.nav-logo {\n width: 32px;\n height: 32px;\n margin-right: 0.8rem;\n}\n\n.nav-items {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.nav-item {\n margin: 0.2rem 0;\n}\n\n.nav-link {\n display: flex;\n align-items: center;\n padding: 0.8rem 1rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: background-color 0.2s ease;\n}\n\n.nav-link:hover {\n background-color: var(--md-code-bg-color);\n}\n\n.nav-icon {\n margin-right: 0.8rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n/* \u81ea\u5b9a\u4e49\u5bfc\u822a\u9879\u6837\u5f0f */\n.nav-item.custom .nav-link {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7212","title":"7.2.1.2 \u641c\u7d22\u6846\u4f4d\u7f6e","text":"HTML<!-- docs/overrides/partials/search.html -->\n{% block search_box %}\n<div class=\"md-search\" data-md-component=\"search\" role=\"dialog\">\n <label class=\"md-search__overlay\" for=\"__search\"></label>\n <div class=\"md-search__inner\" role=\"search\">\n <!-- \u641c\u7d22\u8f93\u5165\u6846 -->\n <form class=\"md-search__form\">\n <input\n type=\"text\"\n class=\"md-search__input\"\n name=\"query\"\n aria-label=\"\u641c\u7d22\"\n placeholder=\"\u641c\u7d22\u6587\u6863...\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n data-md-component=\"search-query\"\n >\n <!-- \u641c\u7d22\u5feb\u6377\u952e\u63d0\u793a -->\n <div class=\"md-search__shortcuts\">\n <kbd>Ctrl</kbd> + <kbd>K</kbd>\n </div>\n </form>\n\n <!-- \u641c\u7d22\u7ed3\u679c -->\n <div class=\"md-search__output\">\n <div class=\"md-search__scrollwrap\" data-md-scrollfix>\n <div class=\"md-search-result\" data-md-component=\"search-result\">\n <div class=\"md-search-result__meta\">\n \u6b63\u5728\u641c\u7d22...\n </div>\n <ol class=\"md-search-result__list\"></ol>\n </div>\n </div>\n </div>\n </div>\n</div>\n
\u6837\u5f0f\u5b9a\u5236\uff1a
CSS/* docs/stylesheets/search.css */\n/* \u641c\u7d22\u6846\u5bb9\u5668 */\n.md-search {\n margin: 0 1rem;\n padding: 0;\n position: relative;\n}\n\n/* \u641c\u7d22\u8f93\u5165\u6846 */\n.md-search__input {\n width: 100%;\n height: 2.4rem;\n padding: 0 2.4rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color);\n background-color: var(--md-default-bg-color);\n border: 1px solid var(--md-default-fg-color--lightest);\n border-radius: 1.2rem;\n}\n\n/* \u641c\u7d22\u56fe\u6807 */\n.md-search__icon {\n position: absolute;\n left: 0.8rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--md-default-fg-color--light);\n}\n\n/* \u5feb\u6377\u952e\u63d0\u793a */\n.md-search__shortcuts {\n position: absolute;\n right: 0.8rem;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n gap: 0.2rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u641c\u7d22\u7ed3\u679c\u5bb9\u5668 */\n.md-search__output {\n position: absolute;\n top: 100%;\n width: 100%;\n margin-top: 0.4rem;\n background-color: var(--md-default-bg-color);\n border-radius: 0.2rem;\n box-shadow: var(--md-shadow-z2);\n overflow: auto;\n z-index: 1;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7213","title":"7.2.1.3 \u79fb\u52a8\u7aef\u9002\u914d","text":"CSS/* \u79fb\u52a8\u7aef\u5bfc\u822a\u6837\u5f0f */\n@media screen and (max-width: 76.1875em) {\n /* \u5bfc\u822a\u5207\u6362\u6309\u94ae */\n .md-header-nav__button.md-icon {\n padding: 0.4rem;\n margin: 0.4rem;\n }\n\n /* \u5bfc\u822a\u62bd\u5c49 */\n .md-nav--primary {\n position: fixed;\n top: 0;\n left: -18rem;\n width: 18rem;\n height: 100%;\n background-color: var(--md-default-bg-color);\n transition: left 0.25s;\n z-index: 2;\n }\n\n /* \u5bfc\u822a\u62bd\u5c49\u6253\u5f00\u72b6\u6001 */\n .md-nav--primary.md-nav--opened {\n left: 0;\n }\n\n /* \u641c\u7d22\u6846\u5168\u5c4f */\n .md-search__inner {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 1rem;\n background-color: var(--md-default-bg-color);\n z-index: 3;\n }\n\n /* \u641c\u7d22\u7ed3\u679c\u5168\u5c4f */\n .md-search__output {\n position: fixed;\n top: 4rem;\n height: calc(100% - 4rem);\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) and (max-width: 96.25em) {\n .md-nav--primary {\n width: 16rem;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#722","title":"7.2.2 \u9875\u811a","text":"HTML<!-- docs/overrides/partials/footer.html -->\n<footer class=\"md-footer\">\n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <!-- \u7248\u6743\u4fe1\u606f -->\n <div class=\"md-footer-copyright\">\n {% if config.copyright %}\n <div class=\"md-footer-copyright__highlight\">\n {{ config.copyright }}\n </div>\n {% endif %}\n\n <!-- \u6784\u5efa\u4fe1\u606f -->\n <div class=\"md-footer-build\">\n Documentation built with\n <a href=\"https://www.mkdocs.org\" target=\"_blank\" rel=\"noopener\">\n MkDocs\n </a>\n and\n <a href=\"https://squidfunk.github.io/mkdocs-material/\" target=\"_blank\" rel=\"noopener\">\n Material for MkDocs\n </a>\n </div>\n </div>\n\n <!-- \u793e\u4ea4\u94fe\u63a5 -->\n {% if config.extra.social %}\n <div class=\"md-footer-social\">\n {% for social in config.extra.social %}\n <a href=\"{{ social.link }}\" \n target=\"_blank\" \n rel=\"noopener\" \n title=\"{{ social.name }}\"\n class=\"md-footer-social__link\">\n {% include \".icons/\" ~ social.icon ~ \".svg\" %}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n\n <!-- \u5907\u6848\u4fe1\u606f -->\n {% if config.extra.icp %}\n <div class=\"md-footer-icp\">\n <a href=\"https://beian.miit.gov.cn/\" target=\"_blank\" rel=\"noopener\">\n {{ config.extra.icp }}\n </a>\n </div>\n {% endif %}\n </div>\n </div>\n</footer>\n
\u914d\u7f6e\uff1a
YAML# mkdocs.yml\ncopyright: Copyright © 2024 Your Name\nextra:\n social:\n - icon: material/github\n name: GitHub\n link: https://github.com/your-username\n - icon: material/twitter\n name: Twitter\n link: https://twitter.com/your-username\n icp: \u4eacICP\u5907xxxxxxxx\u53f7\n
\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/footer.css */\n.md-footer {\n background-color: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n padding: 2rem 0;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.md-footer-meta__inner {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n}\n\n/* \u7248\u6743\u4fe1\u606f */\n.md-footer-copyright {\n font-size: 0.8rem;\n}\n\n.md-footer-copyright__highlight {\n margin-bottom: 0.5rem;\n}\n\n.md-footer-build {\n color: var(--md-default-fg-color--light);\n}\n\n/* \u793e\u4ea4\u94fe\u63a5 */\n.md-footer-social {\n display: flex;\n gap: 1rem;\n}\n\n.md-footer-social__link {\n width: 2rem;\n height: 2rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--md-default-fg-color);\n border-radius: 50%;\n transition: all 0.2s ease;\n}\n\n.md-footer-social__link:hover {\n background-color: var(--md-code-bg-color);\n color: var(--md-accent-fg-color);\n}\n\n/* \u5907\u6848\u4fe1\u606f */\n.md-footer-icp {\n width: 100%;\n text-align: center;\n margin-top: 1rem;\n font-size: 0.8rem;\n}\n\n.md-footer-icp a {\n color: var(--md-default-fg-color--light);\n text-decoration: none;\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .md-footer-meta__inner {\n flex-direction: column;\n text-align: center;\n }\n\n .md-footer-social {\n justify-content: center;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#723","title":"7.2.3 \u641c\u7d22\u6846","text":"HTML<!-- docs/overrides/partials/search-modal.html -->\n<div class=\"md-search-modal\" data-md-component=\"search-modal\">\n <div class=\"md-search-modal__overlay\" data-md-component=\"search-modal-overlay\"></div>\n\n <div class=\"md-search-modal__inner\">\n <!-- \u641c\u7d22\u5934\u90e8 -->\n <header class=\"md-search-modal__header\">\n <form class=\"md-search-modal__form\">\n <input\n type=\"text\"\n class=\"md-search-modal__input\"\n name=\"query\"\n placeholder=\"\u641c\u7d22\u6587\u6863...\"\n data-md-component=\"search-query\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n >\n <!-- \u5feb\u6377\u952e\u63d0\u793a -->\n <div class=\"md-search-modal__shortcuts\">\n <kbd>\u2191</kbd><kbd>\u2193</kbd> \u9009\u62e9\n <kbd>\u21b5</kbd> \u6253\u5f00\n <kbd>ESC</kbd> \u5173\u95ed\n </div>\n </form>\n </header>\n\n <!-- \u641c\u7d22\u7ed3\u679c -->\n <main class=\"md-search-modal__body\">\n <div class=\"md-search-modal__scrollwrap\">\n <div class=\"md-search-modal__meta\">\n \u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22\n </div>\n\n <div class=\"md-search-modal__results\">\n <!-- \u641c\u7d22\u7ed3\u679c\u5217\u8868 -->\n <div class=\"md-search-modal__list\"></div>\n\n <!-- \u641c\u7d22\u5efa\u8bae -->\n <div class=\"md-search-modal__suggestions\">\n <h3>\u60a8\u53ef\u80fd\u611f\u5174\u8da3\uff1a</h3>\n <div class=\"suggestions-list\">\n <!-- \u52a8\u6001\u751f\u6210\u7684\u5efa\u8bae\u5217\u8868 -->\n </div>\n </div>\n </div>\n </div>\n </main>\n </div>\n</div>\n
\u641c\u7d22\u529f\u80fd\u811a\u672c\uff1a
JavaScript// docs/javascripts/search.js\nclass SearchModal {\n constructor() {\n this.modal = document.querySelector('.md-search-modal');\n this.overlay = document.querySelector('.md-search-modal__overlay');\n this.input = document.querySelector('.md-search-modal__input');\n this.resultsList = document.querySelector('.md-search-modal__list');\n this.suggestions = document.querySelector('.md-search-modal__suggestions');\n\n this.searchIndex = null;\n this.searchResults = [];\n this.currentFocus = -1;\n\n this.init();\n }\n\n init() {\n // \u521d\u59cb\u5316\u641c\u7d22\u7d22\u5f15\n this.buildSearchIndex();\n // \u7ed1\u5b9a\u4e8b\u4ef6\n this.bindEvents();\n // \u8bbe\u7f6e\u5feb\u6377\u952e\n this.setupShortcuts();\n }\n\n async buildSearchIndex() {\n // \u6784\u5efa\u641c\u7d22\u7d22\u5f15\n const response = await fetch('/search/search_index.json');\n const data = await response.json();\n\n // \u4f7f\u7528 lunr.js \u6784\u5efa\u7d22\u5f15\n this.searchIndex = lunr(function() {\n this.field('title', { boost: 10 });\n this.field('text');\n this.ref('location');\n\n data.docs.forEach(function(doc) {\n this.add(doc);\n }, this);\n });\n }\n\n bindEvents() {\n // \u641c\u7d22\u6846\u8f93\u5165\u4e8b\u4ef6\n this.input.addEventListener('input', debounce(() => {\n const query = this.input.value;\n if (query.length >= 2) {\n this.performSearch(query);\n } else {\n this.clearResults();\n }\n }, 200));\n\n // \u641c\u7d22\u7ed3\u679c\u5bfc\u822a\n this.input.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault();\n this.navigateResults('up');\n break;\n case 'ArrowDown':\n e.preventDefault();\n this.navigateResults('down');\n break;\n case 'Enter':\n e.preventDefault();\n this.openResult();\n break;\n case 'Escape':\n e.preventDefault();\n this.closeModal();\n break;\n }\n });\n\n // \u70b9\u51fb\u906e\u7f69\u5173\u95ed\n this.overlay.addEventListener('click', () => this.closeModal());\n }\n\n setupShortcuts() {\n // \u5168\u5c40\u641c\u7d22\u5feb\u6377\u952e\n document.addEventListener('keydown', (e) => {\n // Ctrl/Cmd + K \u6253\u5f00\u641c\u7d22\n if ((e.ctrlKey || e.metaKey) && e.key === 'k') {\n e.preventDefault();\n this.openModal();\n }\n });\n }\n\n async performSearch(query) {\n if (!this.searchIndex) return;\n\n // \u6267\u884c\u641c\u7d22\n this.searchResults = this.searchIndex.search(query).map(result => {\n return {\n ref: result.ref,\n score: result.score,\n ...this.getDocumentByRef(result.ref)\n };\n });\n\n // \u6e32\u67d3\u7ed3\u679c\n this.renderResults();\n // \u66f4\u65b0\u5efa\u8bae\n this.updateSuggestions(query);\n }\n\n renderResults() {\n this.resultsList.innerHTML = this.searchResults\n .map((result, index) => `\n <div class=\"search-result-item ${index === this.currentFocus ? 'focused' : ''}\"\n data-index=\"${index}\">\n <div class=\"result-title\">${this.highlightText(result.title)}</div>\n <div class=\"result-excerpt\">${this.highlightText(result.excerpt)}</div>\n <div class=\"result-location\">${result.location}</div>\n </div>\n `)\n .join('');\n }\n\n highlightText(text) {\n const query = this.input.value;\n if (!query) return text;\n\n const regex = new RegExp(`(${query})`, 'gi');\n return text.replace(regex, '<mark>$1</mark>');\n }\n\n updateSuggestions(query) {\n // \u6839\u636e\u641c\u7d22\u5386\u53f2\u548c\u70ed\u95e8\u641c\u7d22\u751f\u6210\u5efa\u8bae\n const suggestions = this.generateSuggestions(query);\n\n this.suggestions.innerHTML = suggestions\n .map(suggestion => `\n <div class=\"suggestion-item\" data-query=\"${suggestion.query}\">\n <span class=\"suggestion-icon\">\n ${suggestion.type === 'history' ? '\u23f1\ufe0f' : '\ud83d\udd25'}\n </span>\n ${suggestion.query}\n </div>\n `)\n .join('');\n }\n\n navigateResults(direction) {\n const maxIndex = this.searchResults.length - 1;\n\n if (direction === 'up') {\n this.currentFocus = this.currentFocus > 0 ? this.currentFocus - 1 : maxIndex;\n } else {\n this.currentFocus = this.currentFocus < maxIndex ? this.currentFocus + 1 : 0;\n }\n\n this.renderResults();\n this.scrollToFocused();\n }\n\n scrollToFocused() {\n const focused = this.resultsList.querySelector('.focused');\n if (focused) {\n focused.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest'\n });\n }\n }\n\n openResult() {\n const result = this.searchResults[this.currentFocus];\n if (result) {\n window.location.href = result.location;\n }\n }\n\n openModal() {\n this.modal.classList.add('active');\n this.input.focus();\n document.body.style.overflow = 'hidden';\n }\n\n closeModal() {\n this.modal.classList.remove('active');\n this.input.value = '';\n this.clearResults();\n document.body.style.overflow = '';\n }\n\n clearResults() {\n this.searchResults = [];\n this.currentFocus = -1;\n this.resultsList.innerHTML = '';\n this.suggestions.innerHTML = '';\n }\n}\n\n// \u521d\u59cb\u5316\u641c\u7d22\u529f\u80fd\ndocument.addEventListener('DOMContentLoaded', () => {\n new SearchModal();\n});\n
\u641c\u7d22\u6846\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search-modal.css */\n.md-search-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1000;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n}\n\n.md-search-modal.active {\n opacity: 1;\n visibility: visible;\n}\n\n.md-search-modal__overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n}\n\n.md-search-modal__inner {\n position: relative;\n width: 90%;\n max-width: 800px;\n margin: 2rem auto;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z3);\n}\n\n/* \u641c\u7d22\u7ed3\u679c\u6837\u5f0f */\n.search-result-item {\n padding: 1rem;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.search-result-item:hover,\n.search-result-item.focused {\n background: var(--md-code-bg-color);\n}\n\n.result-title {\n font-size: 1.1rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n}\n\n.result-excerpt {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-bottom: 0.5rem;\n}\n\n.result-location {\n font-size: 0.8rem;\n color: var(--md-accent-fg-color);\n}\n\n/* \u9ad8\u4eae\u5339\u914d\u6587\u672c */\nmark {\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0 0.2rem;\n border-radius: 2px;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#724","title":"7.2.4 \u76ee\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7241","title":"7.2.4.1 \u76ee\u5f55\u7ed3\u6784","text":"HTML<!-- docs/overrides/partials/toc.html -->\n<nav class=\"md-toc\" aria-label=\"\u76ee\u5f55\">\n <div class=\"md-toc__header\">\n <h2 class=\"md-toc__title\">\u76ee\u5f55</h2>\n <button class=\"md-toc__toggle\" aria-label=\"\u5c55\u5f00/\u6536\u8d77\">\n {% include \".icons/material/chevron-down.svg\" %}\n </button>\n </div>\n\n <div class=\"md-toc__inner\">\n {% set toc = page.toc %}\n <ul class=\"md-toc__list\">\n {% for toc_item in toc %}\n {% include \"partials/toc-item.html\" %}\n {% endfor %}\n </ul>\n </div>\n</nav>\n\n<!-- docs/overrides/partials/toc-item.html -->\n<li class=\"md-toc__item\">\n <a href=\"{{ toc_item.url }}\" class=\"md-toc__link\">\n {{ toc_item.title }}\n </a>\n\n {% if toc_item.children %}\n <ul class=\"md-toc__list\">\n {% for toc_item in toc_item.children %}\n {% include \"partials/toc-item.html\" %}\n {% endfor %}\n </ul>\n {% endif %}\n</li>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7242","title":"7.2.4.2 \u6eda\u52a8\u540c\u6b65","text":"JavaScript// docs/javascripts/toc.js\nclass TableOfContents {\n constructor() {\n this.toc = document.querySelector('.md-toc');\n this.tocLinks = this.toc.querySelectorAll('.md-toc__link');\n this.headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');\n this.intersectionObserver = null;\n\n this.init();\n }\n\n init() {\n this.setupIntersectionObserver();\n this.setupScrollSpy();\n this.setupToggle();\n }\n\n setupIntersectionObserver() {\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n const id = entry.target.getAttribute('id');\n this.highlightTocItem(id);\n }\n });\n },\n {\n rootMargin: '0px 0px -80% 0px'\n }\n );\n\n this.headings.forEach(heading => {\n this.intersectionObserver.observe(heading);\n });\n }\n\n setupScrollSpy() {\n this.tocLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const id = link.getAttribute('href').substring(1);\n const target = document.getElementById(id);\n\n if (target) {\n window.scrollTo({\n top: target.offsetTop - 100,\n behavior: 'smooth'\n });\n\n // \u66f4\u65b0 URL\n history.pushState(null, null, `#${id}`);\n }\n });\n });\n }\n\n highlightTocItem(id) {\n // \u79fb\u9664\u6240\u6709\u9ad8\u4eae\n this.tocLinks.forEach(link => {\n link.classList.remove('active');\n });\n\n // \u6dfb\u52a0\u65b0\u9ad8\u4eae\n const activeLink = this.toc.querySelector(`a[href=\"#${id}\"]`);\n if (activeLink) {\n activeLink.classList.add('active');\n this.expandParents(activeLink);\n }\n }\n\n expandParents(element) {\n let parent = element.parentElement;\n while (parent && parent.classList.contains('md-toc__item')) {\n const list = parent.querySelector('.md-toc__list');\n if (list) {\n list.style.height = 'auto';\n parent.classList.add('expanded');\n }\n parent = parent.parentElement;\n }\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7243","title":"7.2.4.3 \u5c55\u5f00\u6536\u8d77","text":"JavaScriptsetupToggle() {\n const toggleButton = this.toc.querySelector('.md-toc__toggle');\n const tocInner = this.toc.querySelector('.md-toc__inner');\n\n toggleButton?.addEventListener('click', () => {\n const isExpanded = this.toc.classList.contains('expanded');\n\n if (isExpanded) {\n this.toc.classList.remove('expanded');\n tocInner.style.height = '0';\n } else {\n this.toc.classList.add('expanded');\n tocInner.style.height = tocInner.scrollHeight + 'px';\n }\n });\n\n // \u6dfb\u52a0\u5c55\u5f00/\u6536\u8d77\u6240\u6709\u6309\u94ae\n const expandAllButton = document.createElement('button');\n expandAllButton.className = 'md-toc__expand-all';\n expandAllButton.innerHTML = '\u5c55\u5f00\u5168\u90e8';\n expandAllButton.addEventListener('click', () => this.toggleAll(true));\n\n const collapseAllButton = document.createElement('button');\n collapseAllButton.className = 'md-toc__collapse-all';\n collapseAllButton.innerHTML = '\u6536\u8d77\u5168\u90e8';\n collapseAllButton.addEventListener('click', () => this.toggleAll(false));\n\n const buttonGroup = document.createElement('div');\n buttonGroup.className = 'md-toc__button-group';\n buttonGroup.appendChild(expandAllButton);\n buttonGroup.appendChild(collapseAllButton);\n\n this.toc.querySelector('.md-toc__header').appendChild(buttonGroup);\n}\n\ntoggleAll(expand) {\n const lists = this.toc.querySelectorAll('.md-toc__list');\n lists.forEach(list => {\n if (expand) {\n list.style.height = 'auto';\n list.parentElement.classList.add('expanded');\n } else {\n list.style.height = '0';\n list.parentElement.classList.remove('expanded');\n }\n });\n}\n
\u76ee\u5f55\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/toc.css */\n.md-toc {\n position: sticky;\n top: 4rem;\n padding: 1rem;\n max-height: calc(100vh - 4rem);\n overflow-y: auto;\n background: var(--md-default-bg-color);\n border-left: 1px solid var(--md-default-fg-color--lightest);\n font-size: 0.8rem;\n}\n\n/* \u76ee\u5f55\u5934\u90e8 */\n.md-toc__header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n padding-bottom: 0.5rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.md-toc__title {\n font-size: 1rem;\n font-weight: 600;\n margin: 0;\n}\n\n.md-toc__button-group {\n display: flex;\n gap: 0.5rem;\n}\n\n.md-toc__button-group button {\n padding: 0.2rem 0.5rem;\n font-size: 0.7rem;\n color: var(--md-default-fg-color--light);\n background: var(--md-code-bg-color);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.md-toc__button-group button:hover {\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color--light);\n}\n\n/* \u76ee\u5f55\u5217\u8868 */\n.md-toc__list {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.md-toc__item {\n margin: 0.2rem 0;\n}\n\n/* \u76ee\u5f55\u94fe\u63a5 */\n.md-toc__link {\n display: block;\n padding: 0.2rem 0;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: all 0.2s ease;\n border-radius: 4px;\n}\n\n.md-toc__link:hover {\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color);\n padding-left: 0.5rem;\n}\n\n/* \u5f53\u524d\u6fc0\u6d3b\u9879 */\n.md-toc__link.active {\n color: var(--md-accent-fg-color);\n font-weight: 500;\n background: var(--md-code-bg-color);\n padding-left: 0.5rem;\n}\n\n/* \u5d4c\u5957\u5c42\u7ea7 */\n.md-toc__item .md-toc__list {\n margin-left: 1rem;\n border-left: 1px solid var(--md-default-fg-color--lightest);\n overflow: hidden;\n height: 0;\n transition: height 0.3s ease;\n}\n\n.md-toc__item.expanded > .md-toc__list {\n height: auto;\n}\n\n/* \u6298\u53e0\u6307\u793a\u5668 */\n.md-toc__item > .md-toc__link::before {\n content: '';\n display: inline-block;\n width: 0.8rem;\n height: 0.8rem;\n margin-right: 0.2rem;\n background-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z\"/></svg>');\n background-size: contain;\n transform: rotate(0);\n transition: transform 0.3s ease;\n}\n\n.md-toc__item.expanded > .md-toc__link::before {\n transform: rotate(90deg);\n}\n\n/* \u6eda\u52a8\u6761\u6837\u5f0f */\n.md-toc::-webkit-scrollbar {\n width: 4px;\n}\n\n.md-toc::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.md-toc::-webkit-scrollbar-thumb {\n background: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n}\n\n/* \u54cd\u5e94\u5f0f\u8bbe\u8ba1 */\n@media screen and (max-width: 76.1875em) {\n .md-toc {\n position: fixed;\n top: 0;\n right: -18rem;\n width: 18rem;\n height: 100vh;\n max-height: none;\n margin: 0;\n padding: 1rem;\n background: var(--md-default-bg-color);\n border-left: 1px solid var(--md-default-fg-color--lightest);\n box-shadow: var(--md-shadow-z3);\n transition: right 0.3s ease;\n z-index: 3;\n }\n\n .md-toc.expanded {\n right: 0;\n }\n\n /* \u79fb\u52a8\u7aef\u8986\u76d6\u5c42 */\n .md-toc-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.3);\n z-index: 2;\n }\n\n .md-toc.expanded + .md-toc-overlay {\n display: block;\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) and (max-width: 96.25em) {\n .md-toc {\n padding: 0.8rem;\n }\n\n .md-toc__list {\n margin-left: 0.8rem;\n }\n}\n
\u5b8c\u6574\u7684\u76ee\u5f55\u529f\u80fd\u5b9e\u73b0\uff1a
JavaScript// docs/javascripts/toc.js\nclass TableOfContents {\n constructor() {\n this.toc = document.querySelector('.md-toc');\n this.tocLinks = this.toc.querySelectorAll('.md-toc__link');\n this.headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');\n this.intersectionObserver = null;\n this.isScrolling = false;\n this.scrollTimeout = null;\n\n this.init();\n }\n\n init() {\n this.setupIntersectionObserver();\n this.setupScrollSpy();\n this.setupToggle();\n this.setupMobileToggle();\n this.handleInitialHash();\n }\n\n handleInitialHash() {\n // \u5904\u7406\u9875\u9762\u52a0\u8f7d\u65f6\u7684 hash\n if (window.location.hash) {\n const id = window.location.hash.substring(1);\n const target = document.getElementById(id);\n if (target) {\n setTimeout(() => {\n target.scrollIntoView();\n this.highlightTocItem(id);\n }, 100);\n }\n }\n }\n\n setupMobileToggle() {\n // \u521b\u5efa\u79fb\u52a8\u7aef\u5f00\u5173\u6309\u94ae\n const toggleButton = document.createElement('button');\n toggleButton.className = 'md-toc-toggle';\n toggleButton.innerHTML = `\n <span class=\"md-toc-toggle__icon\">\n {% include \".icons/material/menu.svg\" %}\n </span>\n `;\n\n // \u521b\u5efa\u906e\u7f69\u5c42\n const overlay = document.createElement('div');\n overlay.className = 'md-toc-overlay';\n\n document.body.appendChild(toggleButton);\n document.body.appendChild(overlay);\n\n // \u7ed1\u5b9a\u4e8b\u4ef6\n toggleButton.addEventListener('click', () => {\n this.toc.classList.toggle('expanded');\n document.body.style.overflow = this.toc.classList.contains('expanded') ? 'hidden' : '';\n });\n\n overlay.addEventListener('click', () => {\n this.toc.classList.remove('expanded');\n document.body.style.overflow = '';\n });\n }\n\n updateTocHeight() {\n const lists = this.toc.querySelectorAll('.md-toc__list');\n lists.forEach(list => {\n if (list.parentElement.classList.contains('expanded')) {\n list.style.height = list.scrollHeight + 'px';\n }\n });\n }\n\n onResize() {\n // \u76d1\u542c\u7a97\u53e3\u5927\u5c0f\u53d8\u5316\uff0c\u66f4\u65b0\u76ee\u5f55\u9ad8\u5ea6\n window.addEventListener('resize', debounce(() => {\n this.updateTocHeight();\n }, 100));\n }\n}\n\n// \u5de5\u5177\u51fd\u6570\nfunction debounce(fn, delay) {\n let timer = null;\n return function(...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n// \u521d\u59cb\u5316\u76ee\u5f55\ndocument.addEventListener('DOMContentLoaded', () => {\n new TableOfContents();\n});\n
\u4f7f\u7528\u8fd9\u4e9b\u4ee3\u7801\uff0c\u9700\u8981\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n custom_dir: docs/overrides\n features:\n - toc.integrate\n - toc.follow\n\nextra_css:\n - stylesheets/toc.css\n\nextra_javascript:\n - javascripts/toc.js\n
\u8fd9\u6837\u5c31\u5b8c\u6210\u4e86\u4e00\u4e2a\u529f\u80fd\u5b8c\u6574\u3001\u4ea4\u4e92\u53cb\u597d\u7684\u76ee\u5f55\u5bfc\u822a\u7cfb\u7edf\uff0c\u4e3b\u8981\u7279\u70b9\u5305\u62ec\uff1a
pip install mkdocs-material\n
# mkdocs.yml\nplugins:\n - search:\n # \u641c\u7d22\u7d22\u5f15\u8bbe\u7f6e\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+' # \u5206\u8bcd\u5206\u9694\u7b26\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n\n # \u641c\u7d22\u5185\u5bb9\u914d\u7f6e\n indexing:\n full_sections: true # \u7d22\u5f15\u5b8c\u6574\u7ae0\u8282\n headings: true # \u7d22\u5f15\u6807\u9898\n content: true # \u7d22\u5f15\u5185\u5bb9\n tags: true # \u7d22\u5f15\u6807\u7b7e\n\n # \u641c\u7d22\u7ed3\u679c\u6392\u5e8f\n scoring:\n title_boost: 10 # \u6807\u9898\u6743\u91cd\n heading_boost: 5 # \u6807\u9898\u6743\u91cd\n content_boost: 1 # \u5185\u5bb9\u6743\u91cd\n
theme:\n features:\n - search.highlight # \u641c\u7d22\u9ad8\u4eae\n - search.share # \u641c\u7d22\u5206\u4eab\n - search.suggest # \u641c\u7d22\u5efa\u8bae\n\n # \u641c\u7d22\u754c\u9762\u6587\u5b57\n language: zh\n palette:\n - search:\n placeholder: \u641c\u7d22\u6587\u6863\n result:\n no_results_text: \u672a\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching_text: \u6b63\u5728\u641c\u7d22...\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8113","title":"8.1.1.3 \u4e2d\u6587\u641c\u7d22","text":"plugins:\n - search:\n jieba_dict: dict.txt # \u81ea\u5b9a\u4e49\u8bcd\u5178\u8def\u5f84\n jieba_dict_user: user_dict.txt # \u7528\u6237\u8bcd\u5178\u8def\u5f84\n\n # \u4e2d\u6587\u5206\u8bcd\u89c4\u5219\n separator: '[\uff0c\u3002\uff01\uff1f,!?]+'\n\n # \u4e2d\u6587\u505c\u7528\u8bcd\n stopwords:\n - \u7684\n - \u4e86\n - \u548c\n - \u662f\n - \u5c31\n - \u90fd\n - \u800c\n - \u53ca\n - \u4e0e\n - \u8fd9\n
\u6280\u672f\u6587\u6863 5\n\u5f00\u53d1\u6307\u5357 5\n\u6700\u4f73\u5b9e\u8df5 5\n\u4f7f\u7528\u6559\u7a0b 5\n\u914d\u7f6e\u8bf4\u660e 5\n\u5e38\u89c1\u95ee\u9898 5\n
# docs/search_optimize.py\nimport jieba\nimport json\nfrom pathlib import Path\n\ndef optimize_search_index(index_file, dict_file):\n # \u52a0\u8f7d\u81ea\u5b9a\u4e49\u8bcd\u5178\n jieba.load_userdict(dict_file)\n\n # \u8bfb\u53d6\u641c\u7d22\u7d22\u5f15\n with open(index_file, 'r', encoding='utf-8') as f:\n index = json.load(f)\n\n # \u4f18\u5316\u5206\u8bcd\n for doc in index['docs']:\n # \u5206\u8bcd\u5904\u7406\u6807\u9898\n title_words = list(jieba.cut(doc['title']))\n doc['title'] = ' '.join(title_words)\n\n # \u5206\u8bcd\u5904\u7406\u5185\u5bb9\n if 'text' in doc:\n text_words = list(jieba.cut(doc['text']))\n doc['text'] = ' '.join(text_words)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7d22\u5f15\n with open(index_file, 'w', encoding='utf-8') as f:\n json.dump(index, f, ensure_ascii=False, indent=2)\n\nif __name__ == '__main__':\n index_file = 'site/search/search_index.json'\n dict_file = 'docs/dict.txt'\n optimize_search_index(index_file, dict_file)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8114","title":"8.1.1.4 \u641c\u7d22\u4f18\u5316","text":"# docs/search_index_optimizer.py\nfrom pathlib import Path\nimport json\nimport re\n\nclass SearchIndexOptimizer:\n def __init__(self, index_path):\n self.index_path = Path(index_path)\n self.index = self.load_index()\n\n def load_index(self):\n with open(self.index_path, 'r', encoding='utf-8') as f:\n return json.load(f)\n\n def save_index(self):\n with open(self.index_path, 'w', encoding='utf-8') as f:\n json.dump(self.index, f, ensure_ascii=False, indent=2)\n\n def optimize(self):\n # \u6e05\u7406\u65e0\u7528\u6570\u636e\n self._clean_data()\n # \u4f18\u5316\u6587\u672c\n self._optimize_text()\n # \u6dfb\u52a0\u6743\u91cd\n self._add_weights()\n # \u6784\u5efa\u53cd\u5411\u7d22\u5f15\n self._build_inverted_index()\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7d22\u5f15\n self.save_index()\n\n def _clean_data(self):\n # \u79fb\u9664\u7a7a\u6587\u6863\n self.index['docs'] = [\n doc for doc in self.index['docs']\n if doc.get('text') or doc.get('title')\n ]\n\n # \u79fb\u9664\u91cd\u590d\u6587\u6863\n seen = set()\n unique_docs = []\n for doc in self.index['docs']:\n key = f\"{doc['location']}:{doc['title']}\"\n if key not in seen:\n seen.add(key)\n unique_docs.append(doc)\n self.index['docs'] = unique_docs\n\n def _optimize_text(self):\n for doc in self.index['docs']:\n # \u6e05\u7406HTML\u6807\u7b7e\n if 'text' in doc:\n doc['text'] = re.sub(r'<[^>]+>', '', doc['text'])\n\n # \u538b\u7f29\u7a7a\u767d\u5b57\u7b26\n for field in ['title', 'text']:\n if field in doc:\n doc[field] = ' '.join(doc[field].split())\n\n def _add_weights(self):\n for doc in self.index['docs']:\n # \u57fa\u7840\u6743\u91cd\n doc['weight'] = 1.0\n\n # \u6807\u9898\u957f\u5ea6\u6743\u91cd\n if 'title' in doc:\n title_len = len(doc['title'])\n doc['weight'] *= 1 + (1.0 / (1 + title_len))\n\n # \u6587\u672c\u957f\u5ea6\u6743\u91cd\n if 'text' in doc:\n text_len = len(doc['text'])\n doc['weight'] *= 1 + (100.0 / (1 + text_len))\n\n # URL\u6df1\u5ea6\u6743\u91cd\n depth = doc['location'].count('/')\n doc['weight'] *= 1 + (1.0 / (1 + depth))\n\n def _build_inverted_index(self):\n # \u6784\u5efa\u53cd\u5411\u7d22\u5f15\n inverted_index = {}\n for i, doc in enumerate(self.index['docs']):\n terms = set()\n\n # \u6dfb\u52a0\u6807\u9898\u8bcd\n if 'title' in doc:\n terms.update(doc['title'].lower().split())\n\n # \u6dfb\u52a0\u6587\u672c\u8bcd\n if 'text' in doc:\n terms.update(doc['text'].lower().split())\n\n # \u66f4\u65b0\u53cd\u5411\u7d22\u5f15\n for term in terms:\n if term not in inverted_index:\n inverted_index[term] = []\n inverted_index[term].append({\n 'id': i,\n 'weight': doc['weight']\n })\n\n self.index['inverted_index'] = inverted_index\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = SearchIndexOptimizer('site/search/search_index.json')\noptimizer.optimize()\n
// docs/javascripts/search-monitor.js\nclass SearchMonitor {\n constructor() {\n this.metrics = {\n searches: 0,\n avgTime: 0,\n slowest: 0,\n fastest: Infinity\n };\n\n this.init();\n }\n\n init() {\n this.monitorSearchInput();\n this.monitorSearchResults();\n this.setupReporting();\n }\n\n monitorSearchInput() {\n const searchInput = document.querySelector('.md-search__input');\n let startTime;\n\n searchInput?.addEventListener('input', () => {\n startTime = performance.now();\n });\n\n searchInput?.addEventListener('search', () => {\n const endTime = performance.now();\n const duration = endTime - startTime;\n\n this.updateMetrics(duration);\n });\n }\n\n updateMetrics(duration) {\n this.metrics.searches++;\n this.metrics.avgTime = (\n (this.metrics.avgTime * (this.metrics.searches - 1) + duration) /\n this.metrics.searches\n );\n this.metrics.slowest = Math.max(this.metrics.slowest, duration);\n this.metrics.fastest = Math.min(this.metrics.fastest, duration);\n\n // \u53d1\u9001\u7edf\u8ba1\u6570\u636e\n this.sendMetrics();\n }\n\n sendMetrics() {\n // \u53ef\u4ee5\u53d1\u9001\u5230\u7edf\u8ba1\u670d\u52a1\n console.log('Search Metrics:', this.metrics);\n }\n}\n\n// \u521d\u59cb\u5316\u76d1\u63a7\nnew SearchMonitor();\n
"},{"location":"Tools/Blog/Mkdocs_Material/#812-glightbox","title":"8.1.2 glightbox","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8121","title":"8.1.2.1 \u56fe\u7247\u9884\u89c8","text":"pip install mkdocs-glightbox\n
# mkdocs.yml\nplugins:\n - glightbox:\n # \u57fa\u7840\u8bbe\u7f6e\n auto_caption: true # \u81ea\u52a8\u6dfb\u52a0\u6807\u9898\n caption_position: bottom # \u6807\u9898\u4f4d\u7f6e\n display_description: true # \u663e\u793a\u63cf\u8ff0\n\n # \u89e6\u6478\u8bbe\u7f6e\n touchNavigation: true # \u89e6\u6478\u5bfc\u822a\n loop: true # \u5faa\u73af\u6d4f\u89c8\n effect: zoom # \u8fc7\u6e21\u6548\u679c\n\n # \u56fe\u7247\u8bbe\u7f6e\n width: 100% # \u56fe\u7247\u5bbd\u5ea6\n height: auto # \u56fe\u7247\u9ad8\u5ea6\n zoomable: true # \u542f\u7528\u7f29\u653e\n draggable: true # \u542f\u7528\u62d6\u52a8\n
/* docs/stylesheets/glightbox.css */\n.glightbox-clean {\n /* \u5bb9\u5668\u6837\u5f0f */\n --glow-padding: 2rem;\n --glow-bg: rgba(0, 0, 0, 0.95);\n\n /* \u63a7\u5236\u6309\u94ae */\n --glow-btn-color: rgba(255, 255, 255, 0.8);\n --glow-btn-hover: #fff;\n\n /* \u52a0\u8f7d\u52a8\u753b */\n --glow-loading-bg: rgba(0, 0, 0, 0.5);\n --glow-loading-width: 40px;\n --glow-loading-height: 40px;\n}\n\n/* \u6807\u9898\u6837\u5f0f */\n.glightbox-caption {\n font-family: var(--md-font-family);\n font-size: 0.9rem;\n padding: 1rem;\n background: rgba(0, 0, 0, 0.8);\n}\n\n/* \u63cf\u8ff0\u6837\u5f0f */\n.glightbox-description {\n font-size: 0.8rem;\n color: rgba(255, 255, 255, 0.7);\n margin-top: 0.5rem;\n}\n\n/* \u52a0\u8f7d\u52a8\u753b */\n.glightbox-loading {\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #fff;\n border-radius: 50%;\n animation: glow-spin 1s linear infinite;\n}\n\n@keyframes glow-spin {\n to { transform: rotate(360deg); }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8122","title":"8.1.2.2 \u753b\u5eca\u6a21\u5f0f","text":"plugins:\n - glightbox:\n # \u753b\u5eca\u8bbe\u7f6e\n gallery: true # \u542f\u7528\u753b\u5eca\n gallery_mode: true # \u753b\u5eca\u6a21\u5f0f\n gallery_trigger: click # \u89e6\u53d1\u65b9\u5f0f\n\n # \u7f29\u7565\u56fe\u8bbe\u7f6e\n thumb_width: 150 # \u7f29\u7565\u56fe\u5bbd\u5ea6\n thumb_height: 100 # \u7f29\u7565\u56fe\u9ad8\u5ea6\n thumb_fit: cover # \u7f29\u7565\u56fe\u9002\u5e94\u65b9\u5f0f\n
<!-- docs/overrides/gallery.html -->\n<div class=\"gallery\">\n {% for image in page.meta.gallery %}\n <a href=\"{{ image.url }}\" \n class=\"gallery-item\"\n data-gallery=\"gallery\"\n data-glightbox=\"title: {{ image.title }}; description: {{ image.description }}\">\n <img src=\"{{ image.thumbnail or image.url }}\" \n alt=\"{{ image.title }}\"\n loading=\"lazy\">\n {% if image.title %}\n <div class=\"gallery-caption\">{{ image.title }}</div>\n {% endif %}\n </a>\n {% endfor %}\n</div>\n
/* docs/stylesheets/gallery.css */\n.gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 1rem;\n padding: 1rem;\n}\n\n.gallery-item {\n position: relative;\n overflow: hidden;\n border-radius: 4px;\n cursor: pointer;\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover {\n transform: translateY(-4px);\n}\n\n.gallery-item img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover img {\n transform: scale(1.1);\n}\n\n.gallery-caption {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 0.5rem;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n font-size: 0.8rem;\n transform: translateY(100%);\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover .gallery-caption {\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#82","title":"8.2 \u63a8\u8350\u63d2\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8211-git-revision-date","title":"8.2.1.1 git-revision-date","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8212","title":"8.2.1.2 \u65f6\u95f4\u663e\u793a","text":"pip install mkdocs-git-revision-date-localized-plugin\n
# mkdocs.yml\nplugins:\n - git-revision-date-localized:\n enabled: true\n type: date # \u663e\u793a\u7c7b\u578b\uff1adate, datetime, iso_date, iso_datetime, timeago\n timezone: Asia/Shanghai # \u65f6\u533a\u8bbe\u7f6e\n locale: zh # \u672c\u5730\u5316\u8bed\u8a00\n fallback_to_build_date: true # \u65e0 git \u4fe1\u606f\u65f6\u4f7f\u7528\u6784\u5efa\u65f6\u95f4\n\n # \u65f6\u95f4\u683c\u5f0f\n enable_creation_date: true # \u663e\u793a\u521b\u5efa\u65f6\u95f4\n exclude:\n - index.md\n - 404.md\n
<!-- docs/overrides/partials/date.html -->\n{% if page.meta.git_revision_date_localized %}\n<div class=\"page-date\">\n <!-- \u6700\u540e\u66f4\u65b0\u65f6\u95f4 -->\n <div class=\"date-item\">\n <span class=\"date-icon\">\n {% include \".icons/material/update.svg\" %}\n </span>\n <span class=\"date-text\">\n \u6700\u540e\u66f4\u65b0: {{ page.meta.git_revision_date_localized }}\n </span>\n </div>\n\n <!-- \u521b\u5efa\u65f6\u95f4 -->\n {% if page.meta.git_creation_date_localized %}\n <div class=\"date-item\">\n <span class=\"date-icon\">\n {% include \".icons/material/clock-outline.svg\" %}\n </span>\n <span class=\"date-text\">\n \u521b\u5efa\u65f6\u95f4: {{ page.meta.git_creation_date_localized }}\n </span>\n </div>\n {% endif %}\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8213","title":"8.2.1.3 \u66f4\u65b0\u8bb0\u5f55","text":"<!-- docs/overrides/partials/revision.html -->\n{% if page.meta.git_revision_date_localized %}\n<div class=\"revision-history\">\n <h3>\u66f4\u65b0\u8bb0\u5f55</h3>\n <div class=\"revision-list\">\n {% for revision in page.meta.git_history %}\n <div class=\"revision-item\">\n <div class=\"revision-date\">\n {{ revision.date }}\n </div>\n <div class=\"revision-message\">\n {{ revision.message }}\n </div>\n </div>\n {% endfor %}\n </div>\n</div>\n
/* docs/stylesheets/revision.css */\n.revision-history {\n margin: 2rem 0;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n}\n\n.revision-item {\n display: flex;\n padding: 0.5rem 0;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.revision-date {\n flex: 0 0 200px;\n color: var(--md-default-fg-color--light);\n}\n\n.revision-message {\n flex: 1;\n}\n\n/* \u65f6\u95f4\u7ebf\u6837\u5f0f */\n.revision-item {\n position: relative;\n padding-left: 2rem;\n}\n\n.revision-item::before {\n content: '';\n position: absolute;\n left: 0;\n top: 1rem;\n width: 12px;\n height: 12px;\n background: var(--md-accent-fg-color);\n border-radius: 50%;\n}\n\n.revision-item::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1.5rem;\n bottom: -0.5rem;\n width: 2px;\n background: var(--md-default-fg-color--lightest);\n}\n\n.revision-item:last-child::after {\n display: none;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8214","title":"8.2.1.4 \u4f5c\u8005\u4fe1\u606f","text":"plugins:\n - git-revision-date-localized:\n enabled: true\n type: date\n enable_authors: true # \u542f\u7528\u4f5c\u8005\u4fe1\u606f\n authors_file: authors.yaml # \u4f5c\u8005\u914d\u7f6e\u6587\u4ef6\n
authors:\n john:\n name: John Doe\n email: john@example.com\n avatar: assets/authors/john.jpg\n bio: \u8d44\u6df1\u6280\u672f\u4f5c\u8005\n social:\n github: johndoe\n twitter: johndoe\n\n jane:\n name: Jane Smith\n email: jane@example.com\n avatar: assets/authors/jane.jpg\n bio: \u524d\u7aef\u5f00\u53d1\u4e13\u5bb6\n social:\n github: janesmith\n linkedin: janesmith\n
<!-- docs/overrides/partials/author.html -->\n{% if page.meta.git_authors %}\n<div class=\"page-authors\">\n {% for author in page.meta.git_authors %}\n <div class=\"author-card\">\n <!-- \u4f5c\u8005\u5934\u50cf -->\n <div class=\"author-avatar\">\n {% if author.avatar %}\n <img src=\"{{ author.avatar }}\" alt=\"{{ author.name }}\">\n {% else %}\n <div class=\"avatar-placeholder\">\n {{ author.name[0] }}\n </div>\n {% endif %}\n </div>\n\n <!-- \u4f5c\u8005\u4fe1\u606f -->\n <div class=\"author-info\">\n <h4 class=\"author-name\">{{ author.name }}</h4>\n {% if author.bio %}\n <p class=\"author-bio\">{{ author.bio }}</p>\n {% endif %}\n\n <!-- \u793e\u4ea4\u94fe\u63a5 -->\n {% if author.social %}\n <div class=\"author-social\">\n {% for platform, username in author.social.items() %}\n <a href=\"https://{{ platform }}.com/{{ username }}\" \n target=\"_blank\"\n class=\"social-link\">\n {% include \".icons/material/\" ~ platform ~ \".svg\" %}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n </div>\n </div>\n {% endfor %}\n</div>\n
/* docs/stylesheets/author.css */\n.page-authors {\n margin: 2rem 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1rem;\n}\n\n.author-card {\n display: flex;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.author-card:hover {\n transform: translateY(-2px);\n}\n\n.author-avatar {\n flex: 0 0 80px;\n margin-right: 1rem;\n}\n\n.author-avatar img {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n object-fit: cover;\n}\n\n.avatar-placeholder {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--md-accent-fg-color);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 2rem;\n}\n\n.author-info {\n flex: 1;\n}\n\n.author-name {\n margin: 0 0 0.5rem;\n font-size: 1.1rem;\n}\n\n.author-bio {\n color: var(--md-default-fg-color--light);\n font-size: 0.9rem;\n margin: 0 0 0.5rem;\n}\n\n.author-social {\n display: flex;\n gap: 0.5rem;\n}\n\n.social-link {\n color: var(--md-default-fg-color--light);\n transition: color 0.2s ease;\n}\n\n.social-link:hover {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#822-minify","title":"8.2.2 minify","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8221-html","title":"8.2.2.1 HTML \u538b\u7f29","text":"pip install mkdocs-minify-plugin\n
# mkdocs.yml\nplugins:\n - minify:\n minify_html: true\n htmlmin_opts:\n # HTML\u538b\u7f29\u9009\u9879\n remove_comments: true # \u79fb\u9664\u6ce8\u91ca\n remove_empty_space: true # \u79fb\u9664\u7a7a\u767d\n remove_all_empty_space: true # \u79fb\u9664\u6240\u6709\u7a7a\u767d\n reduce_boolean_attributes: true # \u7b80\u5316\u5e03\u5c14\u5c5e\u6027\n remove_optional_tags: false # \u4fdd\u7559\u53ef\u9009\u6807\u7b7e\n remove_redundant_attributes: true # \u79fb\u9664\u5197\u4f59\u5c5e\u6027\n minify_js: true # \u538b\u7f29\u5185\u8054JS\n minify_css: true # \u538b\u7f29\u5185\u8054CSS\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8222-css","title":"8.2.2.2 CSS \u538b\u7f29","text":"plugins:\n - minify:\n minify_css: true\n css_files:\n - stylesheets/extra.css\n - stylesheets/custom.css\n cssmin_opts:\n # CSS\u538b\u7f29\u9009\u9879\n level: 2 # \u538b\u7f29\u7ea7\u522b(1-2)\n compatibility: ie9 # \u517c\u5bb9\u6027\n format: beautify # \u683c\u5f0f\u5316\u8f93\u51fa\n
# docs/tools/css_optimizer.py\nimport re\nfrom pathlib import Path\nfrom csscompressor import compress\n\nclass CSSOptimizer:\n def __init__(self, input_dir, output_dir):\n self.input_dir = Path(input_dir)\n self.output_dir = Path(output_dir)\n self.output_dir.mkdir(exist_ok=True)\n\n def optimize(self):\n \"\"\"\u4f18\u5316\u6240\u6709CSS\u6587\u4ef6\"\"\"\n for css_file in self.input_dir.glob('**/*.css'):\n # \u8bfb\u53d6CSS\u5185\u5bb9\n content = css_file.read_text(encoding='utf-8')\n\n # \u4f18\u5316CSS\n optimized = self.optimize_css(content)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u6587\u4ef6\n output_file = self.output_dir / css_file.name\n output_file.write_text(optimized, encoding='utf-8')\n\n def optimize_css(self, content):\n \"\"\"\u4f18\u5316\u5355\u4e2aCSS\u6587\u4ef6\u5185\u5bb9\"\"\"\n # \u79fb\u9664\u6ce8\u91ca\n content = re.sub(r'/\\*[\\s\\S]*?\\*/', '', content)\n\n # \u79fb\u9664\u591a\u4f59\u7a7a\u767d\n content = re.sub(r'\\s+', ' ', content)\n\n # \u538b\u7f29CSS\n content = compress(content)\n\n return content\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = CSSOptimizer(\n input_dir='docs/stylesheets',\n output_dir='docs/stylesheets/min'\n)\noptimizer.optimize()\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8223-js","title":"8.2.2.3 JS \u538b\u7f29","text":"plugins:\n - minify:\n minify_js: true\n js_files:\n - javascripts/extra.js\n - javascripts/custom.js\n jsmin_opts:\n # JS\u538b\u7f29\u9009\u9879\n mangle: true # \u6df7\u6dc6\u53d8\u91cf\u540d\n compress: true # \u538b\u7f29\u4ee3\u7801\n output:\n beautify: false # \u4e0d\u7f8e\u5316\u8f93\u51fa\n
# docs/tools/js_optimizer.py\nimport re\nfrom pathlib import Path\nimport terser\n\nclass JSOptimizer:\n def __init__(self, input_dir, output_dir):\n self.input_dir = Path(input_dir)\n self.output_dir = Path(output_dir)\n self.output_dir.mkdir(exist_ok=True)\n\n def optimize(self):\n \"\"\"\u4f18\u5316\u6240\u6709JS\u6587\u4ef6\"\"\"\n for js_file in self.input_dir.glob('**/*.js'):\n # \u8bfb\u53d6JS\u5185\u5bb9\n content = js_file.read_text(encoding='utf-8')\n\n # \u4f18\u5316JS\n optimized = self.optimize_js(content)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u6587\u4ef6\n output_file = self.output_dir / js_file.name\n output_file.write_text(optimized, encoding='utf-8')\n\n def optimize_js(self, content):\n \"\"\"\u4f18\u5316\u5355\u4e2aJS\u6587\u4ef6\u5185\u5bb9\"\"\"\n options = {\n 'compress': {\n 'pure_funcs': ['console.log'], # \u79fb\u9664console.log\n 'drop_debugger': True, # \u79fb\u9664debugger\n 'unsafe': True, # \u542f\u7528\u4e0d\u5b89\u5168\u4f18\u5316\n 'passes': 2 # \u4f18\u5316\u6b21\u6570\n },\n 'mangle': {\n 'toplevel': True, # \u6df7\u6dc6\u9876\u7ea7\u4f5c\u7528\u57df\n 'eval': True # \u6df7\u6dc6eval\u4e2d\u7684\u53d8\u91cf\n }\n }\n\n # \u4f7f\u7528terser\u538b\u7f29\n result = terser.minify(content, options)\n return result['code']\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = JSOptimizer(\n input_dir='docs/javascripts',\n output_dir='docs/javascripts/min'\n)\noptimizer.optimize()\n
\u8fd9\u4e9b\u914d\u7f6e\u548c\u811a\u672c\u53ef\u4ee5\u6709\u6548\u51cf\u5c0f\u7ad9\u70b9\u8d44\u6e90\u5927\u5c0f\uff0c\u63d0\u5347\u52a0\u8f7d\u901f\u5ea6\u3002\u8bb0\u5f97\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u538b\u7f29\u540e\u7684\u8d44\u6e90\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#823-social","title":"8.2.3 social","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8231","title":"8.2.3.1 \u793e\u4ea4\u94fe\u63a5","text":"pip install mkdocs-social-plugin\n
# mkdocs.yml\nplugins:\n - social:\n enabled: true\n # \u793e\u4ea4\u5e73\u53f0\u914d\u7f6e\n cards: true # \u542f\u7528\u793e\u4ea4\u5361\u7247\n cards_color: # \u5361\u7247\u989c\u8272\n fill: \"#0FF1CE\" # \u80cc\u666f\u8272\n text: \"#FFFFFF\" # \u6587\u5b57\u8272\n cards_font: Roboto # \u5361\u7247\u5b57\u4f53\n\nextra:\n social:\n - icon: material/github\n link: https://github.com/username\n name: GitHub\n - icon: material/twitter\n link: https://twitter.com/username\n name: Twitter\n - icon: material/linkedin\n link: https://linkedin.com/in/username\n name: LinkedIn\n
<!-- docs/overrides/partials/social.html -->\n{% if config.extra.social %}\n<div class=\"social-links\">\n {% for social in config.extra.social %}\n <a href=\"{{ social.link }}\" \n target=\"_blank\"\n rel=\"noopener\"\n title=\"{{ social.name }}\"\n class=\"social-link\">\n <span class=\"social-icon\">\n {% include \".icons/\" ~ social.icon ~ \".svg\" %}\n </span>\n <span class=\"social-name\">{{ social.name }}</span>\n </a>\n {% endfor %}\n</div>\n{% endif %}\n
\u6837\u5f0f\u914d\u7f6e\uff1a
CSS/* docs/stylesheets/social.css */\n.social-links {\n display: flex;\n gap: 1rem;\n margin: 2rem 0;\n}\n\n.social-link {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n transition: all 0.2s ease;\n}\n\n.social-link:hover {\n transform: translateY(-2px);\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color--light);\n}\n\n.social-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n.social-name {\n font-size: 0.9rem;\n}\n\n/* \u52a8\u753b\u6548\u679c */\n.social-link .social-icon {\n transition: transform 0.2s ease;\n}\n\n.social-link:hover .social-icon {\n transform: scale(1.2);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8232","title":"8.2.3.2 \u5206\u4eab\u529f\u80fd","text":"# mkdocs.yml\nextra:\n social_share:\n - platform: twitter\n text: \u5206\u4eab\u5230 Twitter\n icon: material/twitter\n - platform: facebook\n text: \u5206\u4eab\u5230 Facebook\n icon: material/facebook\n - platform: linkedin\n text: \u5206\u4eab\u5230 LinkedIn\n icon: material/linkedin\n - platform: weibo\n text: \u5206\u4eab\u5230\u5fae\u535a\n icon: material/sina-weibo\n
<!-- docs/overrides/partials/share.html -->\n<div class=\"page-share\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n {% for share in config.extra.social_share %}\n <button class=\"share-button\" \n data-platform=\"{{ share.platform }}\"\n onclick=\"shareContent('{{ share.platform }}')\">\n <span class=\"share-icon\">\n {% include \".icons/\" ~ share.icon ~ \".svg\" %}\n </span>\n <span class=\"share-text\">{{ share.text }}</span>\n </button>\n {% endfor %}\n </div>\n</div>\n\n<script>\nfunction shareContent(platform) {\n const url = encodeURIComponent(window.location.href);\n const title = encodeURIComponent(document.title);\n const text = encodeURIComponent(document.querySelector('meta[name=\"description\"]')?.content || '');\n\n let shareUrl;\n switch(platform) {\n case 'twitter':\n shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;\n break;\n case 'facebook':\n shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;\n break;\n case 'linkedin':\n shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;\n break;\n case 'weibo':\n shareUrl = `http://service.weibo.com/share/share.php?url=${url}&title=${title}`;\n break;\n }\n\n window.open(shareUrl, '_blank', 'width=600,height=400');\n}\n</script>\n
/* docs/stylesheets/share.css */\n.page-share {\n margin: 2rem 0;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n}\n\n.share-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n}\n\n.share-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n border: none;\n border-radius: 2rem;\n background: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n\n.share-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8233","title":"8.2.3.3 \u5173\u6ce8\u6309\u94ae","text":"extra:\n follow_buttons:\n - platform: github\n username: your-username\n icon: material/github\n text: \u5173\u6ce8\u6211\u7684 GitHub\n - platform: twitter\n username: your-username\n icon: material/twitter\n text: \u5173\u6ce8\u6211\u7684 Twitter\n
<!-- docs/overrides/partials/follow.html -->\n<div class=\"follow-buttons\">\n {% for btn in config.extra.follow_buttons %}\n <a href=\"https://{{ btn.platform }}.com/{{ btn.username }}\"\n target=\"_blank\"\n class=\"follow-button\"\n data-platform=\"{{ btn.platform }}\">\n <span class=\"follow-icon\">\n {% include \".icons/\" ~ btn.icon ~ \".svg\" %}\n </span>\n <span class=\"follow-text\">{{ btn.text }}</span>\n <span class=\"follow-count\" id=\"{{ btn.platform }}-count\">\n <!-- \u5c06\u901a\u8fc7API\u52a8\u6001\u66f4\u65b0 -->\n </span>\n </a>\n {% endfor %}\n</div>\n\n<script>\nasync function updateFollowCounts() {\n const buttons = document.querySelectorAll('.follow-button');\n\n for (const button of buttons) {\n const platform = button.dataset.platform;\n const username = button.href.split('/').pop();\n\n // \u83b7\u53d6\u5173\u6ce8\u6570\n const count = await getFollowCount(platform, username);\n\n // \u66f4\u65b0\u663e\u793a\n const countElement = button.querySelector('.follow-count');\n if (countElement && count) {\n countElement.textContent = formatCount(count);\n }\n }\n}\n\nasync function getFollowCount(platform, username) {\n switch (platform) {\n case 'github':\n const response = await fetch(`https://api.github.com/users/${username}`);\n const data = await response.json();\n return data.followers;\n\n // \u5176\u4ed6\u5e73\u53f0API\u5b9e\u73b0...\n default:\n return null;\n }\n}\n\nfunction formatCount(count) {\n if (count >= 1000000) {\n return (count / 1000000).toFixed(1) + 'M';\n }\n if (count >= 1000) {\n return (count / 1000).toFixed(1) + 'K';\n }\n return count.toString();\n}\n\n// \u521d\u59cb\u5316\nupdateFollowCounts();\n</script>\n
/* docs/stylesheets/follow.css */\n.follow-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 2rem 0;\n}\n\n.follow-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n text-decoration: none;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n transition: all 0.2s ease;\n}\n\n.follow-button:hover {\n transform: translateY(-2px);\n}\n\n/* \u5e73\u53f0\u7279\u5b9a\u6837\u5f0f */\n.follow-button[data-platform=\"github\"] {\n color: #333;\n}\n\n.follow-button[data-platform=\"github\"]:hover {\n background: #333;\n color: white;\n}\n\n.follow-button[data-platform=\"twitter\"] {\n color: #1DA1F2;\n}\n\n.follow-button[data-platform=\"twitter\"]:hover {\n background: #1DA1F2;\n color: white;\n}\n\n.follow-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n.follow-count {\n margin-left: 0.5rem;\n padding: 0.2rem 0.5rem;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 1rem;\n font-size: 0.8rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#824-tags","title":"8.2.4 tags","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8241","title":"8.2.4.1 \u6807\u7b7e\u7cfb\u7edf","text":"pip install mkdocs-tags-plugin\n
# mkdocs.yml\nplugins:\n - tags:\n tags_file: tags.md\n tags_allowed: # \u5141\u8bb8\u7684\u6807\u7b7e\u5217\u8868\n - Python\n - JavaScript\n - CSS\n - HTML\n tags_extra_files:\n cloud: tag_cloud.md # \u6807\u7b7e\u4e91\u9875\u9762\n list: tag_list.md # \u6807\u7b7e\u5217\u8868\u9875\u9762\n
---\ntags:\n - Python\n - \u6559\u7a0b\n---\n\n# Python \u5165\u95e8\u6559\u7a0b\n
<!-- docs/overrides/partials/tags.html -->\n{% if page.meta.tags %}\n<div class=\"page-tags\">\n {% for tag in page.meta.tags %}\n <a href=\"{{ base_url }}/tags/#{{ tag|lower }}\" class=\"tag\">\n <span class=\"tag-icon\">\n {% include \".icons/material/tag.svg\" %}\n </span>\n <span class=\"tag-text\">{{ tag }}</span>\n </a>\n {% endfor %}\n</div>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8242","title":"8.2.4.2 \u6807\u7b7e\u4e91","text":"# docs/plugins/tags/cloud.py\nfrom collections import Counter\nimport math\n\nclass TagCloud:\n def __init__(self, tags):\n self.tags = Counter(tags)\n self.min_size = 0.8\n self.max_size = 2.0\n\n def get_tag_sizes(self):\n \"\"\"\u8ba1\u7b97\u6807\u7b7e\u5927\u5c0f\"\"\"\n if not self.tags:\n return {}\n\n # \u83b7\u53d6\u6700\u5927\u548c\u6700\u5c0f\u9891\u7387\n max_freq = max(self.tags.values())\n min_freq = min(self.tags.values())\n\n # \u8ba1\u7b97\u6bcf\u4e2a\u6807\u7b7e\u7684\u5927\u5c0f\n sizes = {}\n for tag, freq in self.tags.items():\n if max_freq == min_freq:\n sizes[tag] = (self.max_size + self.min_size) / 2\n else:\n size = self.min_size + (self.max_size - self.min_size) * \\\n ((freq - min_freq) / (max_freq - min_freq))\n sizes[tag] = round(size, 2)\n\n return sizes\n\ndef generate_tag_cloud(tags):\n \"\"\"\u751f\u6210\u6807\u7b7e\u4e91HTML\"\"\"\n cloud = TagCloud(tags)\n sizes = cloud.get_tag_sizes()\n\n html = ['<div class=\"tag-cloud\">']\n\n for tag, size in sizes.items():\n html.append(f'''\n <a href=\"#tag-{tag.lower()}\" \n class=\"tag-cloud-item\"\n style=\"font-size: {size}rem\">\n {tag}\n </a>\n ''')\n\n html.append('</div>')\n return '\\n'.join(html)\n
/* docs/stylesheets/tags.css */\n.tag-cloud {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 1rem;\n padding: 2rem;\n}\n\n.tag-cloud-item {\n color: var(--md-default-fg-color);\n text-decoration: none;\n padding: 0.5rem 1rem;\n border-radius: 2rem;\n background: var(--md-code-bg-color);\n transition: all 0.2s ease;\n}\n\n.tag-cloud-item:hover {\n transform: scale(1.1);\n background: var(--md-accent-fg-color);\n color: white;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8243","title":"8.2.4.3 \u6807\u7b7e\u9875\u9762","text":"# \u6807\u7b7e\u7d22\u5f15\n\n## \u6807\u7b7e\u4e91\n[TAGS_CLOUD]\n\n## \u6807\u7b7e\u5217\u8868\n[TAGS_LIST]\n
# docs/plugins/tags/generator.py\nfrom pathlib import Path\nimport yaml\n\nclass TagPageGenerator:\n def __init__(self, config):\n self.config = config\n self.tags = {}\n\n def collect_tags(self):\n \"\"\"\u6536\u96c6\u6240\u6709\u6807\u7b7e\"\"\"\n docs_dir = Path(self.config['docs_dir'])\n\n for md_file in docs_dir.glob('**/*.md'):\n # \u8bfb\u53d6\u6587\u4ef6frontmatter\n content = md_file.read_text(encoding='utf-8')\n if content.startswith('---'):\n try:\n # \u89e3\u6790frontmatter\n _, frontmatter, _ = content.split('---', 2)\n meta = yaml.safe_load(frontmatter)\n\n if 'tags' in meta:\n # \u83b7\u53d6\u76f8\u5bf9\u8def\u5f84\n rel_path = md_file.relative_to(docs_dir)\n url = str(rel_path).replace('\\\\', '/')[:-3] # \u79fb\u9664.md\n\n # \u6dfb\u52a0\u5230\u6807\u7b7e\u7d22\u5f15\n for tag in meta['tags']:\n if tag not in self.tags:\n self.tags[tag] = []\n self.tags[tag].append({\n 'title': meta.get('title', url),\n 'url': url,\n 'description': meta.get('description', '')\n })\n except:\n continue\n\n def generate_tag_pages(self):\n \"\"\"\u751f\u6210\u6807\u7b7e\u76f8\u5173\u9875\u9762\"\"\"\n self.collect_tags()\n\n # \u751f\u6210\u6807\u7b7e\u5217\u8868\u9875\u9762\n if 'list' in self.config['tags_extra_files']:\n self.generate_list_page()\n\n # \u751f\u6210\u6bcf\u4e2a\u6807\u7b7e\u7684\u8be6\u60c5\u9875\u9762\n self.generate_tag_detail_pages()\n\n def generate_list_page(self):\n \"\"\"\u751f\u6210\u6807\u7b7e\u5217\u8868\u9875\u9762\"\"\"\n template = \"\"\"\n# \u6807\u7b7e\u5217\u8868\n\n{% for tag, posts in tags.items() %}\n## {{ tag }}\n\n{% for post in posts %}\n- [{{ post.title }}]({{ post.url }}){% if post.description %} - {{ post.description }}{% endif %}\n{% endfor %}\n\n{% endfor %}\n\"\"\"\n # \u4f7f\u7528 Jinja2 \u6e32\u67d3\u6a21\u677f\n from jinja2 import Template\n content = Template(template).render(tags=self.tags)\n\n # \u4fdd\u5b58\u9875\u9762\n output_file = Path(self.config['docs_dir']) / 'tags' / 'list.md'\n output_file.parent.mkdir(exist_ok=True)\n output_file.write_text(content, encoding='utf-8')\n\n def generate_tag_detail_pages(self):\n \"\"\"\u751f\u6210\u6bcf\u4e2a\u6807\u7b7e\u7684\u8be6\u60c5\u9875\u9762\"\"\"\n template = \"\"\"\n# \u6807\u7b7e: {{ tag }}\n\n## \u76f8\u5173\u6587\u7ae0\n\n{% for post in posts %}\n### [{{ post.title }}]({{ post.url }})\n{% if post.description %}\n{{ post.description }}\n{% endif %}\n{% endfor %}\n\n## \u76f8\u5173\u6807\u7b7e\n{% for related_tag in related_tags %}\n- [{{ related_tag }}](../{{ related_tag | lower }})\n{% endfor %}\n\"\"\"\n # \u6807\u7b7e\u76ee\u5f55\n tags_dir = Path(self.config['docs_dir']) / 'tags'\n tags_dir.mkdir(exist_ok=True)\n\n # \u4e3a\u6bcf\u4e2a\u6807\u7b7e\u751f\u6210\u9875\u9762\n for tag, posts in self.tags.items():\n # \u67e5\u627e\u76f8\u5173\u6807\u7b7e\n related_tags = self.find_related_tags(tag)\n\n # \u6e32\u67d3\u5185\u5bb9\n content = Template(template).render(\n tag=tag,\n posts=posts,\n related_tags=related_tags\n )\n\n # \u4fdd\u5b58\u9875\u9762\n output_file = tags_dir / f\"{tag.lower()}.md\"\n output_file.write_text(content, encoding='utf-8')\n\n def find_related_tags(self, current_tag):\n \"\"\"\u67e5\u627e\u76f8\u5173\u6807\u7b7e\"\"\"\n related = set()\n\n # \u83b7\u53d6\u5f53\u524d\u6807\u7b7e\u7684\u6240\u6709\u6587\u7ae0\n current_posts = self.tags[current_tag]\n\n # \u904d\u5386\u6240\u6709\u5176\u4ed6\u6807\u7b7e\n for tag, posts in self.tags.items():\n if tag == current_tag:\n continue\n\n # \u8ba1\u7b97\u6587\u7ae0\u4ea4\u96c6\n intersection = set(p['url'] for p in posts) & \\\n set(p['url'] for p in current_posts)\n\n # \u5982\u679c\u6709\u5171\u540c\u6587\u7ae0\uff0c\u8ba4\u4e3a\u662f\u76f8\u5173\u6807\u7b7e\n if intersection:\n related.add(tag)\n\n return list(related)\n
/* docs/stylesheets/tags-page.css */\n/* \u6807\u7b7e\u5217\u8868\u9875\u9762 */\n.tags-list {\n margin: 2rem 0;\n}\n\n.tag-section {\n margin-bottom: 3rem;\n}\n\n.tag-section h2 {\n color: var(--md-accent-fg-color);\n border-bottom: 2px solid var(--md-accent-fg-color);\n padding-bottom: 0.5rem;\n}\n\n.tag-section .post-list {\n margin-left: 1rem;\n}\n\n.post-list-item {\n margin: 1rem 0;\n}\n\n.post-list-item .post-title {\n font-weight: 500;\n color: var(--md-default-fg-color);\n text-decoration: none;\n}\n\n.post-list-item .post-description {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.2rem;\n}\n\n/* \u6807\u7b7e\u8be6\u60c5\u9875\u9762 */\n.tag-detail {\n padding: 2rem;\n}\n\n.tag-detail-header {\n text-align: center;\n margin-bottom: 3rem;\n}\n\n.tag-detail-title {\n font-size: 2rem;\n color: var(--md-primary-fg-color);\n}\n\n.tag-detail-count {\n color: var(--md-default-fg-color--light);\n}\n\n.related-posts {\n margin: 2rem 0;\n}\n\n.related-post {\n padding: 1rem;\n margin: 1rem 0;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.related-post:hover {\n transform: translateX(0.5rem);\n}\n\n.related-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin: 2rem 0;\n}\n\n.related-tag {\n padding: 0.2rem 0.8rem;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: all 0.2s ease;\n}\n\n.related-tag:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n
// docs/javascripts/tags.js\nclass TagsManager {\n constructor() {\n this.initializeFilters();\n this.setupSearch();\n this.setupSorting();\n }\n\n initializeFilters() {\n const tagList = document.querySelector('.tags-list');\n if (!tagList) return;\n\n // \u521b\u5efa\u8fc7\u6ee4\u5668\n const filterContainer = document.createElement('div');\n filterContainer.className = 'tags-filter';\n filterContainer.innerHTML = `\n <input type=\"text\" \n class=\"filter-input\" \n placeholder=\"\u641c\u7d22\u6807\u7b7e...\">\n <select class=\"sort-select\">\n <option value=\"name\">\u6309\u540d\u79f0\u6392\u5e8f</option>\n <option value=\"count\">\u6309\u6587\u7ae0\u6570\u91cf\u6392\u5e8f</option>\n </select>\n `;\n\n tagList.insertBefore(filterContainer, tagList.firstChild);\n }\n\n setupSearch() {\n const input = document.querySelector('.filter-input');\n if (!input) return;\n\n input.addEventListener('input', () => {\n const query = input.value.toLowerCase();\n const sections = document.querySelectorAll('.tag-section');\n\n sections.forEach(section => {\n const tag = section.querySelector('h2').textContent.toLowerCase();\n section.style.display = tag.includes(query) ? 'block' : 'none';\n });\n });\n }\n\n setupSorting() {\n const select = document.querySelector('.sort-select');\n if (!select) return;\n\n select.addEventListener('change', () => {\n const sections = Array.from(document.querySelectorAll('.tag-section'));\n const container = sections[0].parentElement;\n\n sections.sort((a, b) => {\n const aTag = a.querySelector('h2').textContent;\n const bTag = b.querySelector('h2').textContent;\n const aCount = this.getPostCount(a);\n const bCount = this.getPostCount(b);\n\n if (select.value === 'name') {\n return aTag.localeCompare(bTag);\n } else {\n return bCount - aCount;\n }\n });\n\n // \u91cd\u65b0\u63d2\u5165\u6392\u5e8f\u540e\u7684\u7ae0\u8282\n sections.forEach(section => container.appendChild(section));\n });\n }\n\n getPostCount(section) {\n return section.querySelectorAll('.post-list-item').length;\n }\n}\n\n// \u521d\u59cb\u5316\u6807\u7b7e\u7ba1\u7406\u5668\ndocument.addEventListener('DOMContentLoaded', () => {\n new TagsManager();\n});\n
\u4f7f\u7528\u4ee5\u4e0a\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5b8c\u6574\u7684\u6807\u7b7e\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u914d\u7f6e\u6587\u4ef6\u9700\u8981\u6dfb\u52a0\u76f8\u5e94\u7684\u5f15\u7528\uff1a
YAML# mkdocs.yml\nextra_css:\n - stylesheets/tags.css\n - stylesheets/tags-page.css\n\nextra_javascript:\n - javascripts/tags.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#9","title":"9 \u529f\u80fd\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#91","title":"9.1 \u8bc4\u8bba\u7cfb\u7edf","text":""},{"location":"Tools/Blog/Mkdocs_Material/#911-giscus","title":"9.1.1 Giscus \u914d\u7f6e","text":"# mkdocs.yml\nextra:\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your_repo_id\n category: Comments\n category_id: your_category_id\n
<!-- docs/overrides/partials/comments.html -->\n{% if config.extra.comments.provider == 'giscus' %}\n<div class=\"comments-container\">\n <h3>\u8bc4\u8bba</h3>\n <div class=\"giscus\"></div>\n\n <script>\n function loadGiscus() {\n const script = document.createElement('script');\n script.src = 'https://giscus.app/client.js';\n script.setAttribute('data-repo', '{{ config.extra.comments.repo }}');\n script.setAttribute('data-repo-id', '{{ config.extra.comments.repo_id }}');\n script.setAttribute('data-category', '{{ config.extra.comments.category }}');\n script.setAttribute('data-category-id', '{{ config.extra.comments.category_id }}');\n script.setAttribute('data-mapping', 'pathname');\n script.setAttribute('data-reactions-enabled', '1');\n script.setAttribute('data-emit-metadata', '0');\n script.setAttribute('data-theme', 'preferred_color_scheme');\n script.setAttribute('crossorigin', 'anonymous');\n script.async = true;\n\n document.querySelector('.giscus').appendChild(script);\n }\n\n // \u5ef6\u8fdf\u52a0\u8f7d\u8bc4\u8bba\n if ('IntersectionObserver' in window) {\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) {\n loadGiscus();\n observer.disconnect();\n }\n });\n\n observer.observe(document.querySelector('.comments-container'));\n } else {\n loadGiscus();\n }\n </script>\n</div>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#912","title":"9.1.2 \u81ea\u5b9a\u4e49\u8bc4\u8bba\u6837\u5f0f","text":"CSS/* docs/stylesheets/comments.css */\n.comments-container {\n margin: 3rem 0;\n padding-top: 2rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.giscus {\n width: 100%;\n}\n\n/* Giscus \u4e3b\u9898\u9002\u914d */\n.giscus-frame {\n background-color: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n}\n\n/* \u6697\u8272\u6a21\u5f0f\u9002\u914d */\n[data-md-color-scheme=\"slate\"] .giscus-frame {\n background-color: var(--md-default-bg-color--dark);\n color: var(--md-default-fg-color--dark);\n}\n\n/* \u8bc4\u8bba\u6846\u6837\u5f0f */\n.giscus .gsc-comment-box {\n background-color: var(--md-code-bg-color);\n border-radius: 8px;\n padding: 1rem;\n}\n\n/* \u8bc4\u8bba\u5217\u8868\u6837\u5f0f */\n.giscus .gsc-comment {\n margin: 1rem 0;\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.giscus .gsc-comment:hover {\n transform: translateX(4px);\n}\n\n/* \u6309\u94ae\u6837\u5f0f */\n.giscus .gsc-button {\n background-color: var(--md-primary-fg-color);\n color: var(--md-primary-bg-color);\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.giscus .gsc-button:hover {\n background-color: var(--md-primary-fg-color--dark);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#92","title":"9.2 \u6570\u636e\u7edf\u8ba1","text":""},{"location":"Tools/Blog/Mkdocs_Material/#921-google-analytics","title":"9.2.1 Google Analytics","text":"# mkdocs.yml\nextra:\n analytics:\n provider: google\n property: G-XXXXXXXXXX\n\n # \u4e8b\u4ef6\u8ffd\u8e2a\n events: true\n # \u7528\u6237\u884c\u4e3a\u8ffd\u8e2a\n behavior: true\n
<!-- docs/overrides/partials/analytics.html -->\n{% if config.extra.analytics.provider == 'google' %}\n<!-- Google Analytics -->\n<script async src=\"https://www.googletagmanager.com/gtag/js?id={{ config.extra.analytics.property }}\"></script>\n<script>\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '{{ config.extra.analytics.property }}');\n\n // \u4e8b\u4ef6\u8ffd\u8e2a\n if ({{ config.extra.analytics.events|tojson }}) {\n document.addEventListener('DOMContentLoaded', function() {\n // \u70b9\u51fb\u4e8b\u4ef6\u8ffd\u8e2a\n document.addEventListener('click', function(e) {\n const target = e.target.closest('a');\n if (target) {\n gtag('event', 'click', {\n 'event_category': 'link',\n 'event_label': target.href\n });\n }\n });\n\n // \u6eda\u52a8\u4e8b\u4ef6\u8ffd\u8e2a\n let lastScrollDepth = 0;\n window.addEventListener('scroll', debounce(function() {\n const scrollDepth = Math.round(\n (window.scrollY + window.innerHeight) / \n document.documentElement.scrollHeight * 100\n );\n\n if (scrollDepth > lastScrollDepth) {\n gtag('event', 'scroll_depth', {\n 'depth': scrollDepth\n });\n lastScrollDepth = scrollDepth;\n }\n }, 500));\n\n // \u641c\u7d22\u4e8b\u4ef6\u8ffd\u8e2a\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.addEventListener('search', function() {\n gtag('event', 'search', {\n 'search_term': this.value\n });\n });\n }\n });\n }\n\n // \u7528\u6237\u884c\u4e3a\u8ffd\u8e2a\n if ({{ config.extra.analytics.behavior|tojson }}) {\n // \u9875\u9762\u505c\u7559\u65f6\u95f4\n let startTime = Date.now();\n window.addEventListener('beforeunload', function() {\n const duration = Math.round((Date.now() - startTime) / 1000);\n gtag('event', 'time_on_page', {\n 'duration': duration\n });\n });\n\n // \u590d\u5236\u884c\u4e3a\u8ffd\u8e2a\n document.addEventListener('copy', function() {\n gtag('event', 'content_copy');\n });\n }\n</script>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#922","title":"9.2.2 \u4e0d\u849c\u5b50\u7edf\u8ba1","text":"extra:\n analytics:\n busuanzi: true\n
<!-- docs/overrides/partials/busuanzi.html -->\n{% if config.extra.analytics.busuanzi %}\n<script async src=\"//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js\"></script>\n\n<div class=\"page-views\">\n <!-- \u603b\u8bbf\u95ee\u91cf -->\n <span id=\"busuanzi_container_site_pv\">\n \u603b\u8bbf\u95ee\u91cf: <span id=\"busuanzi_value_site_pv\"></span>\u6b21\n </span>\n\n <!-- \u603b\u8bbf\u5ba2\u6570 -->\n <span id=\"busuanzi_container_site_uv\">\n \u8bbf\u5ba2\u6570: <span id=\"busuanzi_value_site_uv\"></span>\u4eba\n </span>\n\n <!-- \u9875\u9762\u8bbf\u95ee\u91cf -->\n <span id=\"busuanzi_container_page_pv\">\n \u672c\u6587\u8bbf\u95ee\u91cf: <span id=\"busuanzi_value_page_pv\"></span>\u6b21\n </span>\n</div>\n\n<style>\n.page-views {\n display: flex;\n gap: 1rem;\n margin: 1rem 0;\n padding: 0.5rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n font-size: 0.9rem;\n}\n\n.page-views span {\n color: var(--md-default-fg-color--light);\n}\n\n.page-views span span {\n color: var(--md-accent-fg-color);\n font-weight: bold;\n}\n</style>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#93","title":"9.3 \u793e\u4ea4\u5206\u4eab","text":""},{"location":"Tools/Blog/Mkdocs_Material/#931","title":"9.3.1 \u5206\u4eab\u6309\u94ae","text":"extra:\n social_share:\n enabled: true\n platforms:\n - name: twitter\n icon: material/twitter\n color: '#1DA1F2'\n - name: facebook\n icon: material/facebook\n color: '#4267B2'\n - name: linkedin\n icon: material/linkedin\n color: '#0A66C2'\n - name: weibo\n icon: material/sina-weibo\n color: '#E6162D'\n
<!-- docs/overrides/partials/share.html -->\n{% if config.extra.social_share.enabled %}\n<div class=\"share-container\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n {% for platform in config.extra.social_share.platforms %}\n <button class=\"share-button\" \n data-platform=\"{{ platform.name }}\"\n style=\"--platform-color: {{ platform.color }}\"\n onclick=\"shareContent('{{ platform.name }}')\">\n <span class=\"share-icon\">\n {% include \".icons/\" ~ platform.icon ~ \".svg\" %}\n </span>\n <span class=\"share-text\">\u5206\u4eab\u5230 {{ platform.name|title }}</span>\n </button>\n {% endfor %}\n </div>\n</div>\n\n<style>\n.share-container {\n margin: 2rem 0;\n}\n\n.share-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n}\n\n.share-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n border: none;\n border-radius: 4px;\n background: var(--md-code-bg-color);\n color: var(--platform-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--platform-color);\n color: white;\n transform: translateY(-2px);\n}\n\n.share-icon {\n margin-right: 0.5rem;\n}\n</style>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#932","title":"9.3.2 \u5206\u4eab\u94fe\u63a5\u751f\u6210","text":"JavaScript// docs/javascripts/share.js\nclass ShareManager {\n constructor() {\n this.title = document.title;\n this.url = window.location.href;\n this.description = document\n .querySelector('meta[name=\"description\"]')\n ?.content || '';\n }\n\n generateShareUrl(platform) {\n const params = new URLSearchParams();\n switch (platform) {\n case 'twitter':\n return `https://twitter.com/intent/tweet?${\n params.set('text', this.title),\n params.set('url', this.url)\n }`;\n\n case 'facebook':\n return `https://www.facebook.com/sharer/sharer.php?${\n params.set('u', this.url)\n }`;\n\n case 'linkedin':\n return `https://www.linkedin.com/sharing/share-offsite/?${\n params.set('url', this.url)\n }`;\n\n case 'weibo':\n return `http://service.weibo.com/share/share.php?${\n params.set('title', this.title),\n params.set('url', this.url)\n }`;\n\n default:\n return null;\n }\n }\n\n async share(platform) {\n // \u68c0\u67e5\u662f\u5426\u652f\u6301\u539f\u751f\u5206\u4eab\n if (navigator.share && platform === 'native') {\n try {\n await navigator.share({\n title: this.title,\n text: this.description,\n url: this.url\n });\n return true;\n } catch (err) {\n console.warn('Native share failed:', err);\n return false;\n }\n }\n\n // \u4f7f\u7528\u5f39\u7a97\u5206\u4eab\n const url = this.generateShareUrl(platform);\n if (url) {\n window.open(url, '_blank', 'width=600,height=400');\n return true;\n }\n\n return false;\n }\n\n // \u81ea\u5b9a\u4e49\u5206\u4eab\u5185\u5bb9\n setContent(title, description) {\n this.title = title;\n this.description = description;\n }\n}\n\n// \u5168\u5c40\u5206\u4eab\u529f\u80fd\nwindow.shareContent = async function(platform) {\n const shareManager = new ShareManager();\n const success = await shareManager.share(platform);\n\n // \u8bb0\u5f55\u5206\u4eab\u4e8b\u4ef6\n if (success) {\n recordShare(platform);\n }\n};\n\n// \u5206\u4eab\u7edf\u8ba1\nfunction recordShare(platform) {\n // GA4 \u4e8b\u4ef6\u8ffd\u8e2a\n if (typeof gtag !== 'undefined') {\n gtag('event', 'share', {\n 'platform': platform,\n 'title': document.title,\n 'url': window.location.href\n });\n }\n\n // \u672c\u5730\u5b58\u50a8\u7edf\u8ba1\n const stats = JSON.parse(localStorage.getItem('share_stats') || '{}');\n stats[platform] = (stats[platform] || 0) + 1;\n localStorage.setItem('share_stats', JSON.stringify(stats));\n\n updateShareCount(platform);\n}\n\n// \u66f4\u65b0\u5206\u4eab\u8ba1\u6570\nfunction updateShareCount(platform) {\n const countElement = document.querySelector(\n `.share-count[data-platform=\"${platform}\"]`\n );\n if (countElement) {\n const stats = JSON.parse(localStorage.getItem('share_stats') || '{}');\n countElement.textContent = stats[platform] || 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#94","title":"9.4 \u7ad9\u5185\u641c\u7d22","text":""},{"location":"Tools/Blog/Mkdocs_Material/#941","title":"9.4.1 \u641c\u7d22\u4f18\u5316","text":"plugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,!\\?\uff0c\u3002\uff01\uff1f]+' # \u5206\u8bcd\u5206\u9694\u7b26\n prebuild_index: true\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n\n # \u9ad8\u7ea7\u641c\u7d22\u914d\u7f6e\n search_boost: true # \u542f\u7528\u641c\u7d22\u63d0\u5347\n search_threshold: 0.3 # \u641c\u7d22\u9608\u503c\n search_fields: # \u641c\u7d22\u5b57\u6bb5\u6743\u91cd\n title: 10\n tags: 8\n content: 5\n
\u641c\u7d22\u4f18\u5316\u5b9e\u73b0\uff1a
JavaScript// docs/javascripts/search-enhance.js\nclass SearchEnhancer {\n constructor() {\n this.searchIndex = null;\n this.searchResults = [];\n this.searchHistory = [];\n this.maxHistoryItems = 10;\n\n this.init();\n }\n\n async init() {\n // \u52a0\u8f7d\u641c\u7d22\u7d22\u5f15\n await this.loadSearchIndex();\n // \u52a0\u8f7d\u641c\u7d22\u5386\u53f2\n this.loadSearchHistory();\n // \u521d\u59cb\u5316\u641c\u7d22\u7ec4\u4ef6\n this.setupSearch();\n }\n\n async loadSearchIndex() {\n try {\n const response = await fetch('/search/search_index.json');\n const data = await response.json();\n\n // \u4f7f\u7528 Lunr.js \u6784\u5efa\u7d22\u5f15\n this.searchIndex = lunr(function() {\n this.use(lunr.multiLanguage('en', 'zh'));\n\n this.ref('location');\n this.field('title', { boost: 10 });\n this.field('tags', { boost: 8 });\n this.field('text', { boost: 5 });\n\n data.docs.forEach(function(doc) {\n this.add(doc);\n }, this);\n });\n } catch (error) {\n console.error('Failed to load search index:', error);\n }\n }\n\n setupSearch() {\n const searchInput = document.querySelector('.md-search__input');\n if (!searchInput) return;\n\n // \u9632\u6296\u5904\u7406\n searchInput.addEventListener('input', debounce((e) => {\n const query = e.target.value;\n if (query.length >= 2) {\n this.performSearch(query);\n } else {\n this.clearResults();\n }\n }, 200));\n\n // \u641c\u7d22\u5386\u53f2\n searchInput.addEventListener('focus', () => {\n this.showSearchHistory();\n });\n }\n\n performSearch(query) {\n if (!this.searchIndex) return;\n\n try {\n // \u6267\u884c\u641c\u7d22\n this.searchResults = this.searchIndex.search(query);\n\n // \u7ed3\u679c\u540e\u5904\u7406\n this.searchResults = this.postProcessResults(this.searchResults, query);\n\n // \u663e\u793a\u7ed3\u679c\n this.displayResults(this.searchResults);\n\n // \u663e\u793a\u641c\u7d22\u5efa\u8bae\n this.showSearchSuggestions(query);\n } catch (error) {\n console.error('Search failed:', error);\n }\n }\n\n postProcessResults(results, query) {\n return results\n .map(result => {\n // \u8ba1\u7b97\u76f8\u5173\u5ea6\u5206\u6570\n const score = this.calculateRelevanceScore(result, query);\n\n return {\n ...result,\n score: score,\n highlights: this.generateHighlights(result, query)\n };\n })\n // \u6309\u5206\u6570\u6392\u5e8f\n .sort((a, b) => b.score - a.score)\n // \u9650\u5236\u7ed3\u679c\u6570\u91cf\n .slice(0, 10);\n }\n\n calculateRelevanceScore(result, query) {\n let score = result.score;\n\n // \u6807\u9898\u5339\u914d\u52a0\u5206\n if (result.title?.toLowerCase().includes(query.toLowerCase())) {\n score *= 1.5;\n }\n\n // \u6807\u7b7e\u5339\u914d\u52a0\u5206\n if (result.tags?.some(tag => \n tag.toLowerCase().includes(query.toLowerCase())\n )) {\n score *= 1.2;\n }\n\n return score;\n }\n\n generateHighlights(result, query) {\n const text = result.text || '';\n const words = query.toLowerCase().split(/\\s+/);\n const context = 50; // \u4e0a\u4e0b\u6587\u957f\u5ea6\n\n let highlights = [];\n\n words.forEach(word => {\n let index = text.toLowerCase().indexOf(word);\n while (index > -1) {\n const start = Math.max(0, index - context);\n const end = Math.min(text.length, index + word.length + context);\n const highlight = text.slice(start, end);\n\n highlights.push({\n text: highlight,\n position: start\n });\n\n index = text.toLowerCase().indexOf(word, index + 1);\n }\n });\n\n // \u5408\u5e76\u91cd\u53e0\u7684\u9ad8\u4eae\u7247\u6bb5\n return this.mergeHighlights(highlights);\n }\n\n mergeHighlights(highlights) {\n if (highlights.length === 0) return [];\n\n highlights.sort((a, b) => a.position - b.position);\n\n let merged = [highlights[0]];\n for (let i = 1; i < highlights.length; i++) {\n let current = highlights[i];\n let last = merged[merged.length - 1];\n\n if (current.position <= last.position + last.text.length) {\n // \u5408\u5e76\u91cd\u53e0\u7684\u7247\u6bb5\n last.text = last.text.slice(0, current.position - last.position) +\n current.text;\n } else {\n merged.push(current);\n }\n }\n\n return merged;\n }\n\n loadSearchHistory() {\n try {\n this.searchHistory = JSON.parse(\n localStorage.getItem('search_history')\n ) || [];\n } catch (error) {\n this.searchHistory = [];\n }\n }\n\n saveSearchHistory(query) {\n if (!query) return;\n\n // \u79fb\u9664\u91cd\u590d\u9879\n this.searchHistory = this.searchHistory.filter(item => \n item.query !== query\n );\n\n // \u6dfb\u52a0\u65b0\u9879\n this.searchHistory.unshift({\n query: query,\n timestamp: Date.now()\n });\n\n // \u9650\u5236\u5386\u53f2\u8bb0\u5f55\u6570\u91cf\n if (this.searchHistory.length > this.maxHistoryItems) {\n this.searchHistory.pop();\n }\n\n // \u4fdd\u5b58\u5230\u672c\u5730\u5b58\u50a8\n localStorage.setItem(\n 'search_history',\n JSON.stringify(this.searchHistory)\n );\n }\n\n showSearchHistory() {\n const container = document.querySelector('.md-search__history');\n if (!container) return;\n\n // \u6e05\u7a7a\u5bb9\u5668\n container.innerHTML = '';\n\n // \u663e\u793a\u5386\u53f2\u8bb0\u5f55\n this.searchHistory.forEach(item => {\n const element = document.createElement('div');\n element.className = 'search-history-item';\n element.innerHTML = `\n <span class=\"history-icon\">\n {% include \".icons/material/history.svg\" %}\n </span>\n <span class=\"history-query\">${item.query}</span>\n <span class=\"history-time\">\n ${this.formatTime(item.timestamp)}\n </span>\n `;\n\n element.addEventListener('click', () => {\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.value = item.query;\n searchInput.dispatchEvent(new Event('input'));\n }\n });\n\n container.appendChild(element);\n });\n }\n\n formatTime(timestamp) {\n const now = Date.now();\n const diff = now - timestamp;\n\n if (diff < 60000) return '\u521a\u521a';\n if (diff < 3600000) return `${Math.floor(diff/60000)}\u5206\u949f\u524d`;\n if (diff < 86400000) return `${Math.floor(diff/3600000)}\u5c0f\u65f6\u524d`;\n return `${Math.floor(diff/86400000)}\u5929\u524d`;\n }\n}\n\n// \u521d\u59cb\u5316\u641c\u7d22\u589e\u5f3a\nnew SearchEnhancer();\n
\u641c\u7d22\u76f8\u5173\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search.css */\n/* \u641c\u7d22\u5386\u53f2 */\n.search-history-item {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.search-history-item:hover {\n background: var(--md-code-bg-color);\n}\n\n.history-icon {\n margin-right: 0.5rem;\n color: var(--md-default-fg-color--light);\n}\n\n.history-query {\n flex: 1;\n font-weight: 500;\n}\n\n.history-time {\n font-size: 0.8rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u641c\u7d22\u5efa\u8bae */\n.search-suggestions {\n padding: 1rem;\n}\n\n.suggestion-item {\n padding: 0.5rem;\n border-radius: 4px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.suggestion-item:hover {\n background: var(--md-code-bg-color);\n}\n\n/* \u9ad8\u4eae\u6587\u672c */\n.search-highlight {\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0 0.2rem;\n border-radius: 2px;\n}\n\n/* \u641c\u7d22\u7ed3\u679c */\n.search-result {\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.result-title {\n font-size: 1.1rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n}\n\n.result-excerpt {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-bottom: 0.5rem;\n}\n\n.result-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.8rem;\n color: var(--md-default-fg-color--lighter);\n}\n
\u4f7f\u7528\u8fd9\u4e9b\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5b8c\u5584\u7684\u641c\u7d22\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u8bb0\u5f97\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u5f15\u7528\uff1a
extra_css:\n - stylesheets/search.css\n\nextra_javascript:\n - https://unpkg.com/lunr/lunr.js\n - https://unpkg.com/lunr-languages/lunr.stemmer.support.js\n - https://unpkg.com/lunr-languages/lunr.zh.js\n - javascripts/search-enhance.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#10","title":"10 \u90e8\u7f72\u65b9\u6848","text":""},{"location":"Tools/Blog/Mkdocs_Material/#101","title":"10.1 \u672c\u5730\u90e8\u7f72","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1011","title":"10.1.1 \u6784\u5efa\u9759\u6001\u6587\u4ef6","text":"\u4f7f\u7528 MkDocs \u6784\u5efa\u9759\u6001\u6587\u4ef6\uff1a
Bash# \u6784\u5efa\u7ad9\u70b9\nmkdocs build\n\n# \u6307\u5b9a\u8f93\u51fa\u76ee\u5f55\nmkdocs build -d custom_site_dir\n\n# \u6e05\u7406\u5e76\u6784\u5efa\nmkdocs build --clean\n
\u6784\u5efa\u9009\u9879\u8bf4\u660e\uff1a
YAML# mkdocs.yml\nsite_dir: site # \u8f93\u51fa\u76ee\u5f55\ndocs_dir: docs # \u6587\u6863\u6e90\u76ee\u5f55\nstrict: true # \u4e25\u683c\u6a21\u5f0f\nuse_directory_urls: true # \u4f7f\u7528\u76ee\u5f55 URL\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1012","title":"10.1.2 \u672c\u5730\u670d\u52a1\u5668","text":"\u5f00\u53d1\u670d\u52a1\u5668\u914d\u7f6e\uff1a
Bash# \u542f\u52a8\u5f00\u53d1\u670d\u52a1\u5668\nmkdocs serve\n\n# \u6307\u5b9a\u7aef\u53e3\nmkdocs serve -a localhost:8080\n\n# \u81ea\u52a8\u91cd\u8f7d\nmkdocs serve --dirtyreload\n
\u5f00\u53d1\u670d\u52a1\u5668\u9ad8\u7ea7\u914d\u7f6e\uff1a
YAML# mkdocs.yml\ndev_addr: 127.0.0.1:8000 # \u5f00\u53d1\u670d\u52a1\u5668\u5730\u5740\nwatch: [docs, includes] # \u76d1\u89c6\u7684\u76ee\u5f55\n
"},{"location":"Tools/Blog/Mkdocs_Material/#102-github-pages","title":"10.2 GitHub Pages \u90e8\u7f72","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1021","title":"10.2.1 \u4ed3\u5e93\u914d\u7f6e","text":"\u521b\u5efa GitHub \u4ed3\u5e93\uff1a - \u521b\u5efa\u65b0\u4ed3\u5e93\u6216\u4f7f\u7528\u73b0\u6709\u4ed3\u5e93 - \u4ed3\u5e93\u540d\u683c\u5f0f\uff1a username.github.io
\u6216\u666e\u901a\u4ed3\u5e93\u540d
\u914d\u7f6e\u6587\u4ef6\uff1a
# mkdocs.yml\nsite_url: https://username.github.io/repository/\nrepo_url: https://github.com/username/repository\nedit_uri: edit/main/docs/\n
# \u521d\u59cb\u5316 Git \u4ed3\u5e93\ngit init\n\n# \u6dfb\u52a0\u8fdc\u7a0b\u4ed3\u5e93\ngit remote add origin https://github.com/username/repository.git\n\n# \u63d0\u4ea4\u521d\u59cb\u6587\u4ef6\ngit add .\ngit commit -m \"Initial commit\"\ngit push -u origin main\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1022-github-actions","title":"10.2.2 GitHub Actions","text":"\u521b\u5efa GitHub Actions \u5de5\u4f5c\u6d41\u6587\u4ef6\uff1a
YAML# .github/workflows/ci.yml\nname: ci \non:\n push:\n branches: \n - main\npermissions:\n contents: write\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Configure Git Credentials\n run: |\n git config user.name github-actions[bot]\n git config user.email 41898282+github-actions[bot]@users.noreply.github.com\n - uses: actions/setup-python@v4\n with:\n python-version: 3.x\n - run: echo \"cache_id=$(date --utc '+%V')\" >> $GITHUB_ENV \n - uses: actions/cache@v3\n with:\n key: mkdocs-material-${{ env.cache_id }}\n path: .cache\n restore-keys: |\n mkdocs-material-\n - name: Install dependencies\n run: |\n pip install mkdocs-material\n pip install mkdocs-glightbox\n pip install mkdocs-git-revision-date-localized-plugin\n - name: Deploy\n run: mkdocs gh-deploy --force\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1023","title":"10.2.3 \u81ea\u52a8\u90e8\u7f72","text":"\u914d\u7f6e\u81ea\u52a8\u90e8\u7f72\uff1a
\u542f\u7528 GitHub Pages\uff1a - \u8fdb\u5165\u4ed3\u5e93\u8bbe\u7f6e -> Pages - Source \u9009\u62e9 gh-pages
\u5206\u652f - \u4fdd\u5b58\u8bbe\u7f6e
\u914d\u7f6e\u90e8\u7f72\u5206\u652f\uff1a
# mkdocs.yml\nremote_branch: gh-pages # GitHub Pages \u5206\u652f\nremote_name: origin # \u8fdc\u7a0b\u4ed3\u5e93\u540d\n
# \u90e8\u7f72\u5230 GitHub Pages\nmkdocs gh-deploy\n\n# \u5f3a\u5236\u90e8\u7f72\nmkdocs gh-deploy --force\n\n# \u6307\u5b9a\u5206\u652f\nmkdocs gh-deploy --remote-branch custom-branch\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1024","title":"10.2.4 \u81ea\u5b9a\u4e49\u57df\u540d","text":"# docs/CNAME\ndocs.example.com\n
DNS \u914d\u7f6e\uff1a - \u6dfb\u52a0 CNAME \u8bb0\u5f55\u6307\u5411 username.github.io
- \u6216\u6dfb\u52a0 A \u8bb0\u5f55\u6307\u5411 GitHub Pages IP
\u914d\u7f6e\u6587\u4ef6\u66f4\u65b0\uff1a
# mkdocs.yml\nsite_url: https://docs.example.com/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#103","title":"10.3 \u6301\u7eed\u96c6\u6210","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1031-cicd","title":"10.3.1 CI/CD \u914d\u7f6e","text":"\u9ad8\u7ea7 GitHub Actions \u914d\u7f6e\uff1a
YAMLname: CI/CD Pipeline\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Set up Python\n uses: actions/setup-python@v4\n with:\n python-version: 3.x\n\n - name: Cache dependencies\n uses: actions/cache@v3\n with:\n path: ~/.cache/pip\n key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n restore-keys: |\n ${{ runner.os }}-pip-\n\n - name: Install dependencies\n run: |\n python -m pip install --upgrade pip\n pip install -r requirements.txt\n\n - name: Run tests\n run: |\n mkdocs build --strict\n\n deploy:\n needs: test\n if: github.ref == 'refs/heads/main'\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Deploy to GitHub Pages\n run: |\n mkdocs gh-deploy --force\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1032","title":"10.3.2 \u81ea\u52a8\u5316\u6d4b\u8bd5","text":"name: Link Check\non:\n schedule:\n - cron: '0 0 * * *' # \u6bcf\u5929\u8fd0\u884c\njobs:\n linkCheck:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Link Checker\n uses: lycheeverse/lychee-action@v1.8.0\n with:\n args: --verbose --no-progress 'docs/**/*.md'\n
name: HTML Validation\njobs:\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Build site\n run: mkdocs build\n - name: Validate HTML\n uses: Cyb3r-Jak3/html5validator-action@v7.2.0\n with:\n root: site/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1033","title":"10.3.3 \u90e8\u7f72\u7b56\u7565","text":"# \u4fdd\u62a4\u5206\u652f\u8bbe\u7f6e\nbranches:\n - name: main\n protection:\n required_status_checks:\n strict: true\n contexts: ['test', 'build']\n required_pull_request_reviews:\n required_approving_review_count: 1\n
# \u73af\u5883\u53d8\u91cf\u8bbe\u7f6e\nenv:\n production:\n url: https://docs.example.com\n branch: main\n staging:\n url: https://staging.docs.example.com\n branch: staging\n
name: Deployment\non:\n push:\n branches: [main, staging]\njobs:\n deploy:\n runs-on: ubuntu-latest\n environment:\n name: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}\n steps:\n - uses: actions/checkout@v4\n\n - name: Build and Deploy\n env:\n DEPLOY_URL: ${{ github.ref == 'refs/heads/main' && env.production.url || env.staging.url }}\n run: |\n mkdocs build\n # \u90e8\u7f72\u5230\u76f8\u5e94\u73af\u5883\n
"},{"location":"Tools/Blog/Mkdocs_Material/#11","title":"11 \u9644\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#111-a","title":"11.1 A. \u5e38\u7528\u914d\u7f6e\u793a\u4f8b","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1111-a1-mkdocs-yml","title":"11.1.1 A.1 mkdocs. yml \u5b8c\u6574\u793a\u4f8b","text":"YAML# \u7ad9\u70b9\u57fa\u672c\u4fe1\u606f\u914d\u7f6e\nsite_name: \u9879\u76ee\u6587\u6863 # \u7ad9\u70b9\u540d\u79f0\nsite_url: https://example.com # \u7ad9\u70b9URL\nsite_author: \u4f5c\u8005\u540d\u79f0 # \u4f5c\u8005\u4fe1\u606f\nsite_description: >- # \u7ad9\u70b9\u63cf\u8ff0\n \u8fd9\u662f\u4e00\u4e2a\u5b8c\u6574\u7684\u6587\u6863\u793a\u4f8b\uff0c\u5305\u542b\u4e86MkDocs Material\u4e3b\u9898\u7684\u6240\u6709\u4e3b\u8981\u529f\u80fd\u914d\u7f6e\u3002\n\n# \u4ee3\u7801\u4ed3\u5e93\u4fe1\u606f\nrepo_name: username/repo # \u4ed3\u5e93\u540d\u79f0\nrepo_url: https://github.com/username/repo # \u4ed3\u5e93\u5730\u5740\nedit_uri: edit/main/docs/ # \u7f16\u8f91\u94fe\u63a5\n\n# \u7248\u6743\u4fe1\u606f\ncopyright: Copyright © 2024 # \u7248\u6743\u58f0\u660e\n\n# \u4e3b\u9898\u914d\u7f6e\ntheme:\n name: material # \u4f7f\u7528Material\u4e3b\u9898\n custom_dir: overrides # \u81ea\u5b9a\u4e49\u76ee\u5f55\n\n # \u4e3b\u9898\u7279\u6027\u914d\u7f6e\n features:\n # \u5bfc\u822a\u76f8\u5173\n - navigation.tabs # \u9876\u90e8\u6807\u7b7e\u5bfc\u822a\n - navigation.sections # \u4fa7\u8fb9\u680f\u5206\u7ec4\n - navigation.expand # \u9ed8\u8ba4\u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u5bfc\u822a\u7d22\u5f15\u9875\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n - navigation.footer # \u4e0a\u4e00\u9875/\u4e0b\u4e00\u9875\u5bfc\u822a\n\n # \u641c\u7d22\u76f8\u5173\n - search.suggest # \u641c\u7d22\u5efa\u8bae\n - search.highlight # \u641c\u7d22\u9ad8\u4eae\n - search.share # \u641c\u7d22\u5206\u4eab\n\n # \u4ee3\u7801\u76f8\u5173\n - content.code.annotate # \u4ee3\u7801\u6ce8\u91ca\n - content.code.copy # \u4ee3\u7801\u590d\u5236\n\n # \u5176\u4ed6\u529f\u80fd\n - announce.dismiss # \u53ef\u5173\u95ed\u516c\u544a\n - header.autohide # \u81ea\u52a8\u9690\u85cf\u5934\u90e8\n\n # \u914d\u8272\u65b9\u6848\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo # \u4e3b\u8272\n accent: indigo # \u5f3a\u8c03\u8272\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n\n # \u56fe\u6807\u548c\u5b57\u4f53\n icon:\n logo: material/book-open-page-variant # Logo\u56fe\u6807\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n\n font:\n text: Roboto # \u6b63\u6587\u5b57\u4f53\n code: Roboto Mono # \u4ee3\u7801\u5b57\u4f53\n\n language: zh # \u754c\u9762\u8bed\u8a00\n\n# \u6269\u5c55\u914d\u7f6e\nmarkdown_extensions:\n # \u5185\u7f6e\u6269\u5c55\n - toc: # \u76ee\u5f55\n permalink: true # \u6c38\u4e45\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n - tables # \u8868\u683c\u652f\u6301\n - attr_list # \u5c5e\u6027\u5217\u8868\n - def_list # \u5b9a\u4e49\u5217\u8868\n - footnotes # \u811a\u6ce8\n - abbr # \u7f29\u5199\n\n # PyMdown Extensions\n - pymdownx.highlight: # \u4ee3\u7801\u9ad8\u4eae\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n - pymdownx.inlinehilite # \u884c\u5185\u4ee3\u7801\u9ad8\u4eae\n - pymdownx.snippets # \u4ee3\u7801\u7247\u6bb5\n - pymdownx.superfences: # \u8d85\u7ea7\u56f4\u680f\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n - pymdownx.tabbed: # \u6807\u7b7e\u9875\n alternate_style: true\n - pymdownx.tasklist: # \u4efb\u52a1\u5217\u8868\n custom_checkbox: true\n - pymdownx.emoji: # \u8868\u60c5\u652f\u6301\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n - pymdownx.details # \u8be6\u7ec6\u4fe1\u606f\n - pymdownx.caret # \u4e0a\u6807\n - pymdownx.mark # \u6807\u8bb0\n - pymdownx.tilde # \u4e0b\u6807\n - pymdownx.keys # \u952e\u76d8\u6309\u952e\n\n# \u63d2\u4ef6\u914d\u7f6e\nplugins:\n - search: # \u641c\u7d22\u63d2\u4ef6\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.,!\\?\uff0c\u3002\uff01\uff1f]+'\n prebuild_index: true\n\n - git-revision-date-localized: # Git\u65e5\u671f\u63d2\u4ef6\n enable_creation_date: true\n type: datetime\n\n - minify: # \u8d44\u6e90\u538b\u7f29\n minify_html: true\n minify_js: true\n minify_css: true\n htmlmin_opts:\n remove_comments: true\n\n - social: # \u793e\u4ea4\u5206\u4eab\n cards: true\n cards_color:\n fill: \"#0FF1CE\"\n text: \"#FFFFFF\"\n\n - tags: # \u6807\u7b7e\u7cfb\u7edf\n tags_file: tags.md\n\n - statistics: # \u7edf\u8ba1\n page_check: true\n page_count: true\n\n# \u9644\u52a0\u914d\u7f6e\nextra:\n # \u793e\u4ea4\u94fe\u63a5\n social:\n - icon: fontawesome/brands/github\n link: https://github.com/username\n - icon: fontawesome/brands/twitter\n link: https://twitter.com/username\n\n # \u8bc4\u8bba\u7cfb\u7edf\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your_repo_id\n category: Comments\n category_id: your_category_id\n\n # \u5206\u6790\u7edf\u8ba1\n analytics:\n provider: google\n property: G-XXXXXXXXXX\n feedback:\n title: \u8fd9\u7bc7\u6587\u6863\u5bf9\u60a8\u6709\u5e2e\u52a9\u5417\uff1f\n ratings:\n - icon: material/thumb-up-outline\n name: \u6709\u5e2e\u52a9\n data: 1\n note: >-\n \u611f\u8c22\u60a8\u7684\u53cd\u9988\uff01\n - icon: material/thumb-down-outline\n name: \u6ca1\u5e2e\u52a9\n data: 0\n note: >- \n \u611f\u8c22\u60a8\u7684\u53cd\u9988\uff0c\u8bf7\u544a\u8bc9\u6211\u4eec\u5982\u4f55\u6539\u8fdb\u3002\n\n# \u989d\u5916\u7684CSS\u548cJavaScript\nextra_css:\n - stylesheets/extra.css # \u81ea\u5b9a\u4e49\u6837\u5f0f\n - stylesheets/custom.css # \u81ea\u5b9a\u4e49\u4e3b\u9898\n\nextra_javascript:\n - javascripts/extra.js # \u81ea\u5b9a\u4e49\u811a\u672c\n - https://unpkg.com/mermaid/dist/mermaid.min.js # \u5916\u90e8\u5e93\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1112-a2-github-actions","title":"11.1.2 A.2 GitHub Actions \u5de5\u4f5c\u6d41\u793a\u4f8b","text":"YAML# .github/workflows/deploy.yml\n\nname: Deploy Documentation\non:\n # \u89e6\u53d1\u6761\u4ef6\n push:\n branches:\n - main\n paths:\n - 'docs/**'\n - 'mkdocs.yml'\n - '.github/workflows/deploy.yml'\n pull_request:\n branches:\n - main\n\n # \u5141\u8bb8\u624b\u52a8\u89e6\u53d1\n workflow_dispatch:\n\n# \u73af\u5883\u53d8\u91cf\nenv:\n PYTHON_VERSION: '3.10'\n DEPLOY_BRANCH: gh-pages\n\n# \u4efb\u52a1\u5b9a\u4e49\njobs:\n build:\n name: Build and Deploy Documentation\n runs-on: ubuntu-latest\n\n steps:\n # \u68c0\u51fa\u4ee3\u7801\n - name: Checkout Repository\n uses: actions/checkout@v3\n with:\n fetch-depth: 0 # \u83b7\u53d6\u5b8c\u6574\u7684git\u5386\u53f2\u7528\u4e8e\u6700\u8fd1\u66f4\u65b0\u65f6\u95f4\n\n # \u8bbe\u7f6ePython\u73af\u5883\n - name: Setup Python\n uses: actions/setup-python@v4\n with:\n python-version: ${{ env.PYTHON_VERSION }}\n cache: pip\n\n # \u7f13\u5b58\u4f9d\u8d56\n - name: Cache Dependencies\n uses: actions/cache@v3\n with:\n path: ~/.cache/pip\n key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n restore-keys: |\n ${{ runner.os }}-pip-\n\n # \u5b89\u88c5\u4f9d\u8d56\n - name: Install Dependencies\n run: |\n python -m pip install --upgrade pip\n pip install -r requirements.txt\n\n # \u914d\u7f6eGit\n - name: Configure Git\n run: |\n git config --global user.name \"${{ github.actor }}\"\n git config --global user.email \"${{ github.actor }}@users.noreply.github.com\"\n\n # \u6784\u5efa\u6587\u6863\n - name: Build Documentation\n run: |\n mkdocs build --clean --verbose\n\n # \u4f18\u5316\u8d44\u6e90\n - name: Optimize Assets\n run: |\n # \u538b\u7f29\u56fe\u7247\n find site/ -type f -name \"*.png\" -exec optipng -o5 {} \\;\n find site/ -type f -name \"*.jpg\" -exec jpegoptim --strip-all {} \\;\n\n # \u538b\u7f29JavaScript\u548cCSS\n find site/ -type f -name \"*.js\" -exec uglifyjs {} -o {} \\;\n find site/ -type f -name \"*.css\" -exec cleancss -o {} {} \\;\n\n # \u90e8\u7f72\u5230GitHub Pages\n - name: Deploy to GitHub Pages\n if: github.ref == 'refs/heads/main' # \u53ea\u5728main\u5206\u652f\u90e8\u7f72\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.GITHUB_TOKEN }}\n publish_dir: ./site\n publish_branch: ${{ env.DEPLOY_BRANCH }}\n user_name: 'github-actions[bot]'\n user_email: 'github-actions[bot]@users.noreply.github.com'\n commit_message: ${{ github.event.head_commit.message }}\n full_commit_message: |\n Deploy Documentation\n\n Commit: ${{ github.sha }}\n Workflow: ${{ github.workflow }}\n\n ${{ github.event.head_commit.message }}\n\n # \u90e8\u7f72\u5b8c\u6210\u901a\u77e5\n - name: Deployment Status\n if: always()\n uses: actions/github-script@v6\n with:\n script: |\n const { owner, repo } = context.repo;\n const run_id = context.runId;\n const run_url = `https://github.com/${owner}/${repo}/actions/runs/${run_id}`;\n\n if (context.job.status === 'success') {\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body: `\u2705 Documentation deployed successfully!\\nPreview: https://${owner}.github.io/${repo}/\\nWorkflow: ${run_url}`\n });\n } else {\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body: `\u274c Documentation deployment failed.\\nSee details: ${run_url}`\n });\n }\n\n# \u9519\u8bef\u8ffd\u8e2a\u548c\u62a5\u544a\n - name: Report Errors\n if: failure()\n uses: actions/github-script@v6\n with:\n script: |\n const { owner, repo } = context.repo;\n const run_id = context.runId;\n\n await github.rest.issues.create({\n owner,\n repo,\n title: `\ud83d\udd34 Documentation deployment failed - ${new Date().toISOString()}`,\n body: `Deployment failed for commit: ${context.sha}\\n\\nSee workflow run: https://github.com/${owner}/${repo}/actions/runs/${run_id}\\n\\nPlease check the logs for more details.`,\n labels: ['deployment', 'bug']\n });\n
"},{"location":"Tools/Environment/Ubuntu_setup/","title":"Ubuntu \u914d\u7f6e","text":""},{"location":"Tools/Environment/Ubuntu_setup/#ubuntu","title":"Ubuntu \u914d\u7f6e","text":"\u7ea6 77 \u4e2a\u5b57 14 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
visudo /etc/sudoers \n%sudo ALL=(ALL:ALL) NOPASSWD: ALL\n
Bashgit clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting\n\ngit clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions\n\ngit clone git://github.com/joelthelion/autojump.git\ncd autojump\n./install.py\n\n[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] && . ~/.autojump/etc/profile.d/autojump.sh\n
sudo apt-get install flameshot\nflameshot gui\n
\u7ea6 227 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u7ea6 1281 \u4e2a\u5b57 55 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Environment
#Obsidian
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#obsidian","title":"obsidian \u914d\u7f6e","text":"Note \u5982\u679c\u61d2\u5f97\u641e\uff0c\u53ef\u4ee5\u76f4\u63a5 clone \u6211\u7684\u914d\u7f6e\uff0c\u653e\u5230 .obsidian \u6587\u4ef6\u91cc\u3002 \u8fd9\u662f\u914d\u7f6e\u6587\u4ef6\u3002
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#1","title":"1 \u4f7f\u7528\u8bed\u8a00","text":"mk
\u5c31\u53ef\u4ee5\u81ea\u52a8\u66ff\u6362\u4e3a $\\displaystyle $
\u5982\u679c\u4f60\u7684 \\(\\displaystyle \\LaTeX\\) \u4e66\u5199\u901f\u5ea6\u6bd4\u8f83\u6162\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u4f7f\u7528 ocr \u8f6f\u4ef6\uff0c\u6bd4\u5982 simpleTex\uff0c\u4f46\u662f\u8fd9\u4e2a\u53ea\u6709 Windows \u5e73\u53f0\u652f\u6301\u3002\u5bf9\u4e8e Linux\uff0c\u6211\u6682\u65f6\u8fd8\u6ca1\u6709\u6bd4\u8f83\u597d\u7684\u8f6f\u4ef6\u3002
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#22","title":"2.2 \u7f16\u8f91\u589e\u5f3a","text":"\u5bf9\u4e8e\u56fe\u7247\uff0c\u4e00\u822c\u6709\u4e24\u79cd\u65b9\u6848\uff1a
\"obsidian-auto-link-title\",\n\"obsidian-latex-suite\",\n\"number-headings-obsidian\",\n\"mathlinks\",\n\"obsidian-outliner\",\n\"obsidian-completr\",\n\"calendar\",\n\"periodic-notes\",\n\"obsidian-wakatime\",\n\"obsidian-image-auto-upload-plugin\",\n\"obsidian-paste-image-rename\",\n\"dataview\",\n\"obsidian-export-image\",\n\"obsidian-day-planner\",\n\"templater-obsidian\",\n\"obsidian-git\",\n\"easy-typing-obsidian\",\n\"obsidian-linter\",\n\"obsidian-style-settings\",\n\"obsidian-image-toolkit\",\n\"tag-wrangler\",\n\"obsidian-tagfolder\"\n
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#_1","title":"\u6211\u7684\u6a21\u677f","text":"\u9700\u8981\u5b89\u88c5 dataview + periodic notes \u63d2\u4ef6\u3002
Note
\u7531\u4e8e markdown \u4ee3\u7801\u5757\u5d4c\u5957\u4e0d\u592a\u884c\uff0c\u6240\u4ee5\u8981\u624b\u52a8\u4fee\u590d\u3002\u6ce8\u610f\u4fee\u590d '' \u5e26\u6765\u7684\u4ee3\u7801\u5757\u95ee\u9898, \u8bb0\u5f97\u8865\u5168\u3002
dailyweekly Note Text Only---\ntitle: \"{{date}}\"\ntags:\n - \" #\u65e5\u8bb0 \"\ncategories: dairy\ndate: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\nmodify: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\ndir: dairy\nshare: false\ncdate: \" {{ date:YYYY-MM-DD }} \"\nmdate: \" {{ date:YYYY-MM-DD }} \"\n---\n\n# {{date}}\n\n## Daily Plan\n\n### Morning\n\n#### Plan\n\n### Afternoon\n\n#### Plan\n\n### Night\n\n#### Plan\n\n## NOTES\n\n```dataview\nLIST FROM \"\" \nWHERE cdate = this.cdate\n Or mdate = this.mdate\n``\n\n## LINKS\n\n## TODOs\n\n```dataview\nTASK FROM \"dairy\"\nWHERE !completed\n AND mdate >= (this.mdate - dur(7 days))\n AND mdate <= this.mdate\nSORT file.cday DESC\n``\n\n## THOUGHTS\n
Note Text Only ---\ntitle: \" {{date}} \"\ntags:\n - \" #\u5468\u8bb0 \"\ncategories: dairy\ndate: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\nmodify: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\ndir: dairy\nshare: false\ncdate: \" {{ date:YYYY-MM-DD }} \"\nmdate: \" {{ date:YYYY-MM-DD }} \"\n---\n\n# {{date:YYYY}} -W {{date:WW}} - {{date:MM}}\n\n## Review\n\n## Next Week Plan\n\n## Time Line\n\n## THOUGHTS\n\n## LINKS\n\n```dataviewjs\n// Configuration for collecting LINKS sections from daily notes\nconst tars = {\n 'LINKS': 2, // Collect second-level LINKS headings\n}\n\nawait dv.view('zob_config/js/dv-\u68c0\u7d22', {\n // Get only daily notes from dairy folder\n files: dv.pages('\"dairy\"')\n .where(p => {\n // Extract the week number from the current file name (weekly note)\n const weekMatch = dv.current().file.name.match(/(\\d{4})-W(\\d{1,2})/);\n if (!weekMatch) return false;\n\n const [_, weekYear, weekNum] = weekMatch;\n\n // Extract date components from daily note name (2024-49-12-08-7 format)\n const dateMatch = p.file.name.match(/(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})/);\n if (!dateMatch) return false;\n\n const [__, year, week, month, day] = dateMatch;\n\n // Check if the daily note belongs to the same week and year\n return year === weekYear && week === weekNum;\n })\n .sort(p => {\n // Create sortable date string from daily note format\n const [_, year, week, month, day] = p.file.name.match(/^(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})$/);\n // Sort by YYYYMMDD format (descending)\n return -1 * parseInt(`${year}${month.padStart(2, '0')}${day.padStart(2, '0')}`);\n }),\n\n kwd: false, // Don't filter by keywords\n showHead: false, // Don't include heading in output\n tars, // Target sections to collect (LINKS)\n obsidian, // Pass obsidian object\n scale: 0.8, // Scale of rendered content\n\n // List item configuration\n li: ([p, li]) => {\n const [_, year, week, month, day] = p.file.name.match(/^(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})$/);\n const formattedDate = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;\n // Create a header with date and file link, followed by the content\n return dv.paragraph(`### ${formattedDate} [[${p.file.path}|${p.file.name}]]\\n${li}`);\n },\n});\n``\n
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#3","title":"3 \u76f8\u5173\u94fe\u63a5","text":"\u7ea6 161 \u4e2a\u5b57 13 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Make/CMake/#1","title":"1 \u6784\u5efa\u6700\u5c0f\u9879\u76ee","text":"mkdir build\ncd build\ncmake -G\"MinGW Makefiles\" ..\ncmake --build .\n
\u4e4b\u540e\u4f1a\u751f\u6210\u53ef\u6267\u884c\u6587\u4ef6
Text Onlystep1/\n build/\n CMakeLists.txt\n tutorial.cpp\n
"},{"location":"Tools/Make/CMake/#2-cmakelists-txt","title":"2 \u4f18\u5316 CMakeLists. txt \u6587\u4ef6","text":"CMakecmake_minimum_required(VERSION 3.15)\n\n# set the project name\nproject(Tutorial)\n\nSET(SRC_LIST tutorial.cpp)\n\n# add the executable\nadd_executable(${PROJECT_NAME} ${SRC_LIST})\n
1.0.2 \u5206\u522b\u5bf9\u5e94 MAJOR MINOR PATCH
\u7ea6 220 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Make/Makeflie/#make_1","title":"\u4ec0\u4e48\u662f Make","text":"Make \u662f\u4e00\u4e2a\u81ea\u52a8\u5316\u6784\u5efa\u5de5\u5177\uff0c\u4f7f\u7528 Makefile \u6587\u4ef6\u6765\u5b9a\u4e49\u5982\u4f55\u7f16\u8bd1\u548c\u94fe\u63a5\u7a0b\u5e8f\u3002\u5b83\u901a\u8fc7\u68c0\u67e5\u6587\u4ef6\u7684\u65f6\u95f4\u6233\u6765\u51b3\u5b9a\u54ea\u4e9b\u6587\u4ef6\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u3002
"},{"location":"Tools/Make/Makeflie/#makefile","title":"Makefile \u7684\u57fa\u672c\u7ed3\u6784","text":"Makefile \u7684\u57fa\u672c\u7ed3\u6784\u7531\u76ee\u6807\u3001\u4f9d\u8d56\u548c\u547d\u4ee4\u7ec4\u6210\uff0c\u901a\u5e38\u5f62\u5f0f\u4e3a\uff1a
Text Onlytarget: dependencies \n command\n
"},{"location":"Tools/Make/Makeflie/#makefile_1","title":"Makefile \u793a\u4f8b","text":"\u8ba9\u6211\u4eec\u8003\u8651\u4e00\u4e2a\u7b80\u5355\u7684 C \u8bed\u8a00\u9879\u76ee\uff0c\u8be5\u793a\u4f8b\u5c06\u5c55\u793a\u5982\u4f55\u4f7f\u7528 Makefile \u6765\u7f16\u8bd1\u4e00\u4e2a\u5177\u6709\u591a\u4e2a\u6e90\u6587\u4ef6\u548c\u5934\u6587\u4ef6\u7684\u7a0b\u5e8f\uff0c\u5e76\u5c55\u793a Makefile \u76f8\u6bd4\u624b\u52a8\u547d\u4ee4\u884c\u7f16\u8bd1\u7684\u4f18\u52bf\u3002 \u7f16\u8bd1\u8fdb\u9636 - HPC\u5165\u95e8\u6307\u5357
"},{"location":"Tools/Make/Makeflie/#make_2","title":"Make \u7684\u5e38\u7528\u547d\u4ee4","text":"make
\uff1a\u6267\u884c\u9ed8\u8ba4\u76ee\u6807\uff0c\u4e0emake all
\u7b49\u6548\u3002make <target>
\uff1a\u6267\u884c\u5b9a\u4e49\u7684<target>
\u76ee\u6807\uff0c\u5982\u679c\u6ca1\u6709\u8fd9\u4e2a\u76ee\u6807\u5c06\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\u3002make -j
\uff1a\u5e76\u884c\u6267\u884c\u6784\u5efa\uff0c\u4f7f\u7528\u672c\u673a\u7684\u5168\u90e8\u7ebf\u7a0b\u7ea6 512 \u4e2a\u5b57 142 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u672c\u6307\u5357\u5c06\u5e2e\u52a9\u4f60\u4f7f\u7528 chezmoi \u7ba1\u7406\u4f60\u7684\u914d\u7f6e\u6587\u4ef6\uff08dotfiles\uff09\uff0c\u5e76\u4f7f\u7528\u5305\u7ba1\u7406\u5668\u7ef4\u62a4\u8f6f\u4ef6\u5217\u8868\u3002
"},{"location":"Tools/Others/Chezmoi/#_1","title":"\u524d\u671f\u51c6\u5907","text":""},{"location":"Tools/Others/Chezmoi/#1","title":"1. \u9700\u8981\u7684\u5de5\u5177","text":"Windows \u5e38\u7528\u914d\u7f6e\u6587\u4ef6:
Text Only%USERPROFILE%/\n\u251c\u2500\u2500 .gitconfig # Git\u914d\u7f6e\n\u251c\u2500\u2500 .ssh/ # SSH\u914d\u7f6e\n\u251c\u2500\u2500 Documents/\n\u2502 \u2514\u2500\u2500 PowerShell/\n\u2502 \u2514\u2500\u2500 Microsoft.PowerShell_profile.ps1 # PowerShell\u914d\u7f6e\n\u251c\u2500\u2500 AppData/\n\u2502 \u251c\u2500\u2500 Roaming/\n\u2502 \u2502 \u2514\u2500\u2500 Code/\n\u2502 \u2502 \u2514\u2500\u2500 User/\n\u2502 \u2502 \u2514\u2500\u2500 settings.json # VSCode\u914d\u7f6e\n\u2502 \u2514\u2500\u2500 Local/\n\u2514\u2500\u2500 .config/\n \u2514\u2500\u2500 scoop/\n \u2514\u2500\u2500 config.json # Scoop\u914d\u7f6e\n
Ubuntu \u5e38\u7528\u914d\u7f6e\u6587\u4ef6:
Text Only~/\n\u251c\u2500\u2500 .bashrc # Bash\u914d\u7f6e\n\u251c\u2500\u2500 .zshrc # Zsh\u914d\u7f6e\n\u251c\u2500\u2500 .gitconfig # Git\u914d\u7f6e\n\u251c\u2500\u2500 .ssh/ # SSH\u914d\u7f6e\n\u2514\u2500\u2500 .config/\n \u251c\u2500\u2500 Code/\n \u2502 \u2514\u2500\u2500 User/\n \u2502 \u2514\u2500\u2500 settings.json # VSCode\u914d\u7f6e\n \u2514\u2500\u2500 tabby/\n \u2514\u2500\u2500 config.yaml # Tabby\u7ec8\u7aef\u914d\u7f6e\n
"},{"location":"Tools/Others/Chezmoi/#github","title":"GitHub \u8bbe\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1-github","title":"1. \u521b\u5efa GitHub \u4ed3\u5e93","text":"dotfiles
# \u751f\u6210SSH\u5bc6\u94a5\nssh-keygen -t ed25519 -C \"your_email@example.com\"\n\n# \u5c06\u516c\u94a5\u6dfb\u52a0\u5230GitHub\n# 1. \u590d\u5236\u516c\u94a5\u5185\u5bb9\ncat ~/.ssh/id_ed25519.pub\n# 2. \u8bbf\u95ee GitHub \u2192 Settings \u2192 SSH and GPG keys \u2192 New SSH key\n# 3. \u7c98\u8d34\u516c\u94a5\u5185\u5bb9\u5e76\u4fdd\u5b58\n
"},{"location":"Tools/Others/Chezmoi/#windows","title":"Windows \u914d\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1_1","title":"1. \u5b89\u88c5\u5fc5\u8981\u5de5\u5177","text":"\u4f7f\u7528 PowerShell\uff08\u4ee5\u7ba1\u7406\u5458\u8eab\u4efd\u8fd0\u884c\uff09\uff1a
PowerShell# \u5b89\u88c5Scoop\nSet-ExecutionPolicy RemoteSigned -Scope CurrentUser\nirm get.scoop.sh | iex\n\n# \u5b89\u88c5Git\uff08\u5982\u679c\u8fd8\u6ca1\u6709\uff09\nscoop install git\n\n# \u5b89\u88c5chezmoi\nscoop install chezmoi\n
"},{"location":"Tools/Others/Chezmoi/#2-chezmoi","title":"2. \u521d\u59cb\u5316 chezmoi","text":"PowerShell# \u521d\u59cb\u5316chezmoi\u5e76\u514b\u9686\u4f60\u7684\u4ed3\u5e93\nchezmoi init --apply https://github.com/yourusername/dotfiles.git\n# \u7528 ssh \u4e5f\u53ef\u4ee5\n\n# \u67e5\u770bchezmoi\u5c06\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5c06\u73b0\u6709\u914d\u7f6e\u6587\u4ef6\u6dfb\u52a0\u5230chezmoi\nchezmoi add $HOME/.gitconfig\nchezmoi add $HOME/.ssh/config\nchezmoi add $HOME/Documents/PowerShell/Microsoft.PowerShell_profile.ps1\nchezmoi add $HOME/AppData/Roaming/Code/User/settings.json\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Initial Windows config\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#3","title":"3. \u5bfc\u51fa\u8f6f\u4ef6\u5305\u5217\u8868","text":"PowerShell# \u5bfc\u51faScoop\u5305\u5217\u8868\nscoop export > packages/scoop-packages.txt\n\n# \u63d0\u4ea4\u5305\u5217\u8868\nchezmoi cd\ngit add packages/scoop-packages.txt\ngit commit -m \"Add Windows package list\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#ubuntu","title":"Ubuntu \u914d\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1_2","title":"1. \u5b89\u88c5\u5fc5\u8981\u5de5\u5177","text":"Bash# \u5b89\u88c5Git\uff08\u5982\u679c\u8fd8\u6ca1\u6709\uff09\nsudo apt update\nsudo apt install git\n\n# \u5b89\u88c5chezmoi\nsh -c \"$(curl -fsLS get.chezmoi.io)\"\n
\u53c2\u8003\u8fd9\u4e2a\u7f51\u7ad9 Install - chezmoi \u8fdb\u884c\u4e0b\u8f7d\uff0c\u6211\u547d\u4ee4\u884c\u4e00\u76f4\u4e0d\u6210\u529f\uff0c\u76f4\u63a5\u9009\u62e9\u5bf9\u5e94\u7684\u5305\u5c31\u884c\u4e86\u3002
Text Onlysudo dpkg -i chezmoi_2.54.0_linux_amd64.deb\nchezmoi --version\n
"},{"location":"Tools/Others/Chezmoi/#2-chezmoi_1","title":"2. \u521d\u59cb\u5316 chezmoi","text":"Bash# \u521d\u59cb\u5316chezmoi\u5e76\u514b\u9686\u4f60\u7684\u4ed3\u5e93\nchezmoi init --apply https://github.com/yourusername/dotfiles.git\n\n# \u67e5\u770bchezmoi\u5c06\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5c06\u73b0\u6709\u914d\u7f6e\u6587\u4ef6\u6dfb\u52a0\u5230chezmoi\nchezmoi add ~/.bashrc\nchezmoi add ~/.zshrc\nchezmoi add ~/.gitconfig\nchezmoi add ~/.ssh/config\nchezmoi add ~/.config/Code/User/settings.json\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Initial Ubuntu config\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#3_1","title":"3. \u5bfc\u51fa\u8f6f\u4ef6\u5305\u5217\u8868","text":"Bashchezmoi cd\nmkdir packages\n# \u5bfc\u51faapt\u5305\u5217\u8868\ndpkg --get-selections | grep -v deinstall | awk '{print $1}' > packages/apt-packages.txt\n\n# \u5bfc\u51fasnap\u5305\u5217\u8868\nsnap list | awk '{if (NR>1) print $1}' > packages/snap-packages.txt\n\n# \u63d0\u4ea4\u5305\u5217\u8868\ngit add packages/apt-packages.txt packages/snap-packages.txt\ngit commit -m \"Add Ubuntu package lists\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#_2","title":"\u65e5\u5e38\u4f7f\u7528","text":""},{"location":"Tools/Others/Chezmoi/#1_3","title":"1. \u66f4\u65b0\u914d\u7f6e","text":"\u5f53\u4f60\u4fee\u6539\u4e86\u914d\u7f6e\u6587\u4ef6\u540e\uff1a
Bash# \u5c06\u66f4\u6539\u6dfb\u52a0\u5230chezmoi\nchezmoi add ~/.bashrc # \u6216\u5176\u4ed6\u4fee\u6539\u7684\u914d\u7f6e\u6587\u4ef6\n\n# \u67e5\u770b\u66f4\u6539\nchezmoi diff\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Update bashrc\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#2_1","title":"2. \u5728\u5176\u4ed6\u673a\u5668\u4e0a\u540c\u6b65","text":"Bash# \u62c9\u53d6\u5e76\u5e94\u7528\u6700\u65b0\u66f4\u6539\nchezmoi update\n
"},{"location":"Tools/Others/Chezmoi/#3_2","title":"3. \u66f4\u65b0\u8f6f\u4ef6\u5305\u5217\u8868","text":"Windows:
PowerShell# \u66f4\u65b0Scoop\u5305\u5217\u8868\nscoop export > packages/scoop-packages.txt\n
Ubuntu:
Bash# \u66f4\u65b0apt\u5305\u5217\u8868\ndpkg --get-selections | grep -v deinstall | awk '{print $1}' > packages/apt-packages.txt\n\n# \u66f4\u65b0snap\u5305\u5217\u8868\nsnap list | awk '{if (NR>1) print $1}' > packages/snap-packages.txt\n
"},{"location":"Tools/Others/Chezmoi/#4","title":"4. \u5728\u65b0\u673a\u5668\u4e0a\u8bbe\u7f6e","text":"Windows:
PowerShell# \u5b89\u88c5chezmoi\nscoop install chezmoi\n\n# \u521d\u59cb\u5316\u5e76\u5e94\u7528\u914d\u7f6e\nchezmoi init https://github.com/yourusername/dotfiles.git\nchezmoi apply\n
Ubuntu:
Bash# \u5b89\u88c5chezmoi\nsh -c \"$(curl -fsLS get.chezmoi.io)\"\n\n# \u521d\u59cb\u5316\u5e76\u5e94\u7528\u914d\u7f6e\nchezmoi init https://github.com/yourusername/dotfiles.git\nchezmoi apply\n
"},{"location":"Tools/Others/Chezmoi/#_3","title":"\u5e38\u89c1\u95ee\u9898","text":""},{"location":"Tools/Others/Chezmoi/#1_4","title":"1. \u5982\u4f55\u5904\u7406\u4e0d\u540c\u673a\u5668\u7684\u7279\u5b9a\u914d\u7f6e\uff1f","text":"\u4f7f\u7528\u6a21\u677f\u548c\u6761\u4ef6\u8bed\u53e5\u3002\u5728 .chezmoi.toml.tmpl
\u4e2d\uff1a
{{- $osid := .chezmoi.os -}}\n[data]\n name = \"Your Name\"\n email = \"your@email.com\"\n {{- if eq .chezmoi.os \"windows\" }}\n is_windows = true\n {{- else if eq .chezmoi.os \"linux\" }}\n is_linux = true\n {{- end }}\n
"},{"location":"Tools/Others/Chezmoi/#2_2","title":"2. \u5982\u4f55\u5904\u7406\u654f\u611f\u4fe1\u606f\uff1f","text":"\u5bf9\u4e8e\u654f\u611f\u4fe1\u606f\uff0c\u53ef\u4ee5\uff1a
# \u67e5\u770b\u5c06\u8981\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5982\u679c\u4e0d\u6ee1\u610f\uff0c\u53ef\u4ee5\u64a4\u9500\nchezmoi forget ~/.bashrc # \u79fb\u9664\u6587\u4ef6\u7684\u7ba1\u7406\n\n# \u6216\u8005\u91cd\u7f6e\u4e3a\u539f\u59cb\u72b6\u6001\nchezmoi apply --force\n
"},{"location":"Tools/Others/Chezmoi/#4_1","title":"4. \u914d\u7f6e\u6587\u4ef6\u6743\u9650\u95ee\u9898\uff1f","text":"chezmoi \u4f1a\u81ea\u52a8\u5904\u7406\u6587\u4ef6\u6743\u9650\u3002\u5bf9\u4e8e\u7279\u6b8a\u6743\u9650\u9700\u6c42\uff0c\u53ef\u4ee5\u5728\u6e90\u6587\u4ef6\u540d\u4e2d\u4f7f\u7528\u7279\u6b8a\u524d\u7f00\uff1a
private_
: \u521b\u5efa\u79c1\u6709\u6587\u4ef6 (chmod 600)executable_
: \u521b\u5efa\u53ef\u6267\u884c\u6587\u4ef6 (chmod 700)readonly_
: \u521b\u5efa\u53ea\u8bfb\u6587\u4ef6 (chmod 400)# \u5217\u51fa\u6240\u6709\u7ba1\u7406\u7684\u6587\u4ef6\nchezmoi managed\n\n# \u67e5\u770b\u6e90\u6587\u4ef6\nchezmoi cd\nls -la\n
"},{"location":"Tools/Others/Chezmoi/#6","title":"6. \u66f4\u65b0\u51fa\u9519\u600e\u4e48\u529e\uff1f","text":"Bash# \u5907\u4efd\u5f53\u524d\u72b6\u6001\nchezmoi archive --output=backup.tar.gz\n\n# \u91cd\u7f6e\u66f4\u6539\nchezmoi init --force\n\n# \u91cd\u65b0\u5e94\u7528\u914d\u7f6e\nchezmoi apply\n
"},{"location":"Tools/Others/SSH/","title":"SSH\u914d\u7f6e\u6307\u5357","text":""},{"location":"Tools/Others/SSH/#ssh","title":"SSH\u914d\u7f6e\u6307\u5357","text":"\u7ea6 641 \u4e2a\u5b57 195 \u884c\u4ee3\u7801 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Others/SSH/#ssh_1","title":"\u4e00\u3001SSH\u57fa\u7840\u6982\u5ff5","text":""},{"location":"Tools/Others/SSH/#1-ssh","title":"1. SSH\u5de5\u4f5c\u539f\u7406","text":"SSH(Secure Shell)\u662f\u4e00\u79cd\u52a0\u5bc6\u7684\u7f51\u7edc\u534f\u8bae\uff0c\u901a\u8fc7\u5728\u4e0d\u5b89\u5168\u7684\u7f51\u7edc\u4e0a\u4e3a\u7f51\u7edc\u670d\u52a1\u63d0\u4f9b\u5b89\u5168\u7684\u4f20\u8f93\u73af\u5883\u3002SSH\u901a\u8fc7\u4f7f\u7528\u52a0\u5bc6\u6280\u672f\uff0c\u80fd\u591f\u6709\u6548\u9632\u6b62\u4e2d\u95f4\u4eba\u653b\u51fb\uff0c\u4fdd\u62a4\u6570\u636e\u4f20\u8f93\u7684\u5b89\u5168\u3002
SSH\u5de5\u4f5c\u6d41\u7a0b\uff1a 1. TCP\u8fde\u63a5\u5efa\u7acb\uff1a\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u5efa\u7acbTCP\u8fde\u63a5\uff08\u9ed8\u8ba4\u7aef\u53e322\uff09 2. \u7248\u672c\u534f\u5546\uff1a\u53cc\u65b9\u4ea4\u6362\u7248\u672c\u4fe1\u606f\uff0c\u786e\u5b9a\u4f7f\u7528\u7684SSH\u534f\u8bae\u7248\u672c 3. \u5bc6\u94a5\u4ea4\u6362\uff1a\u4f7f\u7528Diffie-Hellman\u7b97\u6cd5\u4ea4\u6362\u4f1a\u8bdd\u5bc6\u94a5 4. \u8ba4\u8bc1\uff1a\u4f7f\u7528\u516c\u94a5\u6216\u5bc6\u7801\u8fdb\u884c\u8eab\u4efd\u9a8c\u8bc1 5. \u4f1a\u8bdd\uff1a\u5efa\u7acb\u52a0\u5bc6\u901a\u4fe1\u901a\u9053
"},{"location":"Tools/Others/SSH/#2","title":"2. \u8ba4\u8bc1\u65b9\u5f0f\u8be6\u89e3","text":""},{"location":"Tools/Others/SSH/#21","title":"2.1 \u5bc6\u7801\u8ba4\u8bc1","text":"\u8ba4\u8bc1\u6d41\u7a0b 1. \u5ba2\u6237\u7aef\u53d1\u9001\u516c\u94a5\u4fe1\u606f\u7ed9\u670d\u52a1\u5668 2. \u670d\u52a1\u5668\u68c0\u67e5authorized_keys\u6587\u4ef6 3. \u670d\u52a1\u5668\u751f\u6210\u968f\u673a\u5b57\u7b26\u4e32\uff0c\u7528\u516c\u94a5\u52a0\u5bc6\u540e\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef 4. \u5ba2\u6237\u7aef\u7528\u79c1\u94a5\u89e3\u5bc6\uff0c\u5c06\u7ed3\u679c\u8fd4\u56de\u670d\u52a1\u5668 5. \u670d\u52a1\u5668\u9a8c\u8bc1\u7ed3\u679c\uff0c\u5b8c\u6210\u8ba4\u8bc1
"},{"location":"Tools/Others/SSH/#3","title":"3. \u5b89\u5168\u5efa\u8bae","text":""},{"location":"Tools/Others/SSH/#31","title":"3.1 \u57fa\u672c\u5b89\u5168\u8bbe\u7f6e","text":"Bash# /etc/ssh/sshd_config \u5b89\u5168\u914d\u7f6e\nPermitRootLogin no # \u7981\u6b62root\u76f4\u63a5\u767b\u5f55\nPasswordAuthentication no # \u7981\u7528\u5bc6\u7801\u8ba4\u8bc1\nPubkeyAuthentication yes # \u542f\u7528\u516c\u94a5\u8ba4\u8bc1\nPermitEmptyPasswords no # \u7981\u6b62\u7a7a\u5bc6\u7801\nProtocol 2 # \u53ea\u4f7f\u7528SSH2\u534f\u8bae\nMaxAuthTries 3 # \u6700\u5927\u8ba4\u8bc1\u5c1d\u8bd5\u6b21\u6570\nLoginGraceTime 30 # \u767b\u5f55\u8d85\u65f6\u65f6\u95f4\nX11Forwarding no # \u7981\u7528X11\u8f6c\u53d1\uff08\u9664\u975e\u9700\u8981\uff09\nAllowUsers user1 user2 # \u9650\u5236\u5141\u8bb8\u767b\u5f55\u7684\u7528\u6237\n
"},{"location":"Tools/Others/SSH/#32","title":"3.2 \u5bc6\u94a5\u7ba1\u7406","text":"Bash# \u751f\u6210\u5f3a\u5bc6\u94a5\nssh-keygen -t ed25519 -C \"your_email@example.com\" -a 100\n\n# \u5bc6\u94a5\u6743\u9650\u8bbe\u7f6e\nchmod 700 ~/.ssh\nchmod 600 ~/.ssh/id_ed25519\nchmod 644 ~/.ssh/id_ed25519.pub\nchmod 600 ~/.ssh/authorized_keys\nchmod 600 ~/.ssh/known_hosts\n
"},{"location":"Tools/Others/SSH/#ssh_2","title":"\u5e38\u7528\u7684 SSH \u547d\u4ee4","text":"SSH \u6559\u7a0b \u83dc\u9e1f\u6559\u7a0b
"},{"location":"Tools/Others/SSH/#_1","title":"\u4e8c\u3001\u5b8c\u6574\u914d\u7f6e\u6307\u5357","text":""},{"location":"Tools/Others/SSH/#1-linux","title":"1. Linux\u670d\u52a1\u5668\u914d\u7f6e","text":"Bash# 1. \u5b89\u88c5SSH\u670d\u52a1\u5668\nsudo apt update\nsudo apt install openssh-server\n\n# 2. \u914d\u7f6eSSH\u670d\u52a1\nsudo nano /etc/ssh/sshd_config\n\n# 3. \u57fa\u672c\u5b89\u5168\u914d\u7f6e\nPort 22 # \u53ef\u4ee5\u4fee\u6539\u4e3a\u975e\u6807\u51c6\u7aef\u53e3\nListenAddress 0.0.0.0 # \u76d1\u542c\u5730\u5740\nProtocol 2\nPermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nAuthorizedKeysFile .ssh/authorized_keys\nUsePAM yes\nX11Forwarding no\nPrintMotd no\nAcceptEnv LANG LC_*\nSubsystem sftp /usr/lib/openssh/sftp-server\n\n# 4. \u91cd\u542fSSH\u670d\u52a1\nsudo systemctl restart sshd\n\n# 5. \u68c0\u67e5\u670d\u52a1\u72b6\u6001\nsudo systemctl status sshd\n
"},{"location":"Tools/Others/SSH/#2-windows-ssh","title":"2. Windows SSH\u914d\u7f6e","text":""},{"location":"Tools/Others/SSH/#21-openssh","title":"2.1 \u5b89\u88c5OpenSSH","text":"PowerShell# \u4f7f\u7528PowerShell\u5b89\u88c5OpenSSH\n# \u68c0\u67e5OpenSSH\u72b6\u6001\nGet-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'\n\n# \u5b89\u88c5\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\nAdd-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0\nAdd-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0\n\n# \u542f\u52a8SSH\u670d\u52a1\nStart-Service sshd\nSet-Service -Name sshd -StartupType 'Automatic'\n
\u5982\u679c\u6709\u7f51\u7edc\u95ee\u9898\u53ef\u4ee5\u4e0b\u8f7d\u5e76\u5b89\u88c5 OpenSSH \u7684\u79bb\u7ebf\u5b89\u88c5\u5305\uff1a powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
\u00a0\u6765\u5b89\u88c5 OpenSSH \u670d\u52a1\u3002 # \u7f16\u8f91SSH\u914d\u7f6e\u6587\u4ef6\nnotepad \"$env:ProgramData\\ssh\\sshd_config\"\n\n# \u57fa\u672c\u914d\u7f6e\u5185\u5bb9\u4e0eLinux\u7c7b\u4f3c\uff0c\u4f46\u8def\u5f84\u9700\u8981\u8c03\u6574\nPubkeyAuthentication yes\nPasswordAuthentication no\nSubsystem sftp sftp-server.exe\n
"},{"location":"Tools/Others/SSH/#3-ssh","title":"3. SSH\u5ba2\u6237\u7aef\u914d\u7f6e","text":""},{"location":"Tools/Others/SSH/#31-ssh","title":"3.1 \u521b\u5efaSSH\u914d\u7f6e\u6587\u4ef6","text":"Bash# ~/.ssh/config\n# \u5168\u5c40\u8bbe\u7f6e\nHost *\n ServerAliveInterval 60\n ServerAliveCountMax 3\n HashKnownHosts yes\n GSSAPIAuthentication no\n\n# GitHub\nHost github.com\n HostName github.com\n User git\n IdentityFile ~/.ssh/github_ed25519\n AddKeysToAgent yes\n\n# \u5f00\u53d1\u670d\u52a1\u5668\nHost dev\n HostName dev.example.com\n User developer\n Port 22\n IdentityFile ~/.ssh/dev_ed25519\n ForwardAgent yes\n\n# \u751f\u4ea7\u670d\u52a1\u5668\nHost prod\n HostName prod.example.com\n User deployer\n Port 22\n IdentityFile ~/.ssh/prod_ed25519\n ForwardAgent no\n
"},{"location":"Tools/Others/SSH/#_2","title":"\u4e09\u3001\u5177\u4f53\u5b9e\u8df5\uff0c\u7528\u7b14\u8bb0\u672c\u8fde\u53f0\u5f0f\u673a","text":""},{"location":"Tools/Others/SSH/#_3","title":"\u53f0\u5f0f\u7535\u8111\uff08\u670d\u52a1\u7aef\uff09\u914d\u7f6e\uff1a","text":"# Ubuntu/Debian\u7cfb\u7edf\nsudo apt install openssh-server\nsudo systemctl enable ssh\nsudo systemctl start ssh\n\n# \u68c0\u67e5SSH\u670d\u52a1\u72b6\u6001\nsudo systemctl status ssh\n
# \u7f16\u8f91SSH\u670d\u52a1\u5668\u914d\u7f6e\nsudo nano /etc/ssh/sshd_config\n\n# \u6dfb\u52a0\u6216\u4fee\u6539\u4ee5\u4e0b\u914d\u7f6e\nPermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nAllowUsers your_username # \u66ff\u6362\u4e3a\u60a8\u7684\u7528\u6237\u540d\n
# \u67e5\u770b\u5f53\u524dIP\nip addr show\n\n# \u5982\u679c\u662f\u52a8\u6001IP\uff0c\u5efa\u8bae\u8bbe\u7f6e\u9759\u6001IP\u6216\u4f7f\u7528\u52a8\u6001DNS\u670d\u52a1\n
"},{"location":"Tools/Others/SSH/#_4","title":"\u7b14\u8bb0\u672c\uff08\u5ba2\u6237\u7aef\uff09\u914d\u7f6e\uff1a","text":"ssh-keygen -t ed25519 -C \"your_laptop\"\n
# \u65b9\u6cd51\uff1a\u4f7f\u7528ssh-copy-id\nssh-copy-id -i ~/.ssh/id_ed25519.pub username@desktop_ip\n\n# \u65b9\u6cd52\uff1a\u624b\u52a8\u590d\u5236\ncat ~/.ssh/id_ed25519.pub | ssh username@desktop_ip \"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys\"\n
# \u7f16\u8f91 ~/.ssh/config\nnano ~/.ssh/config\n\n# \u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\nHost desktop\n HostName 192.168.1.xxx # \u66ff\u6362\u4e3a\u53f0\u5f0f\u673a\u7684IP\n User your_username # \u66ff\u6362\u4e3a\u60a8\u7684\u7528\u6237\u540d\n Port 22\n IdentityFile ~/.ssh/id_ed25519\n ForwardX11 yes # \u5982\u679c\u9700\u8981\u56fe\u5f62\u754c\u9762\u8f6c\u53d1\n ForwardAgent yes\n Compression yes\n ServerAliveInterval 60\n
"},{"location":"Tools/Others/SSH/#_5","title":"\u5e38\u7528\u8fde\u63a5\u547d\u4ee4\uff1a","text":"# \u4ece\u7b14\u8bb0\u672c\u8fde\u63a5\u5230\u53f0\u5f0f\u673a\nssh desktop\n\n# \u4f7f\u7528\u56fe\u5f62\u754c\u9762\u8f6c\u53d1\nssh -X desktop\n
# \u4ece\u7b14\u8bb0\u672c\u590d\u5236\u6587\u4ef6\u5230\u53f0\u5f0f\u673a\nscp /path/to/local/file desktop:/path/to/remote/\n\n# \u4ece\u53f0\u5f0f\u673a\u590d\u5236\u6587\u4ef6\u5230\u7b14\u8bb0\u672c\nscp desktop:/path/to/remote/file /path/to/local/\n
# \u672c\u5730\u7aef\u53e3\u8f6c\u53d1\nssh -L 8080:localhost:80 desktop\n\n# \u8fdc\u7a0b\u7aef\u53e3\u8f6c\u53d1\nssh -R 8080:localhost:80 desktop\n
"},{"location":"Tools/Others/SSH/#_6","title":"\u56db\u3001\u9ad8\u7ea7\u64cd\u4f5c","text":""},{"location":"Tools/Others/SSH/#1-ssh_1","title":"1. SSH\u7aef\u53e3\u8f6c\u53d1","text":""},{"location":"Tools/Others/SSH/#11","title":"1.1 \u672c\u5730\u7aef\u53e3\u8f6c\u53d1","text":"Bash# \u5c06\u672c\u57308080\u7aef\u53e3\u8f6c\u53d1\u5230\u8fdc\u7a0b80\u7aef\u53e3\nssh -L 8080:localhost:80 user@remote\n\n# \u4f7f\u7528\u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost tunnel\n HostName remote.example.com\n LocalForward 8080 localhost:80\n
"},{"location":"Tools/Others/SSH/#12","title":"1.2 \u8fdc\u7a0b\u7aef\u53e3\u8f6c\u53d1","text":"Bash# \u5c06\u8fdc\u7a0b3000\u7aef\u53e3\u8f6c\u53d1\u5230\u672c\u57303000\u7aef\u53e3\nssh -R 3000:localhost:3000 user@remote\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost remote-tunnel\n HostName remote.example.com\n RemoteForward 3000 localhost:3000\n
"},{"location":"Tools/Others/SSH/#2-ssh","title":"2. SSH\u4ee3\u7406\u8f6c\u53d1","text":"Bash# \u542f\u7528\u4ee3\u7406\u8f6c\u53d1\nssh -A user@remote\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost *\n ForwardAgent yes\n AddKeysToAgent yes\n
"},{"location":"Tools/Others/SSH/#3_1","title":"3. \u8df3\u677f\u673a\u914d\u7f6e","text":"Bash# \u901a\u8fc7\u8df3\u677f\u673a\u8fde\u63a5\nssh -J jumphost user@target\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost target\n HostName target.example.com\n ProxyJump jumphost\n
"},{"location":"Tools/Others/SSH/#_7","title":"\u4e94\u3001\u6545\u969c\u6392\u67e5","text":""},{"location":"Tools/Others/SSH/#1","title":"1. \u6700\u4f73\u5b9e\u8df5","text":"Bash# 1. \u4f7f\u7528SSH\u914d\u7f6e\u6587\u4ef6\u7ba1\u7406\u8fde\u63a5\n# 2. \u4e3a\u4e0d\u540c\u7528\u9014\u4f7f\u7528\u4e0d\u540c\u7684\u5bc6\u94a5\n# 3. \u5b9a\u671f\u8f6e\u6362\u5bc6\u94a5\n# 4. \u4f7f\u7528ssh-agent\u7ba1\u7406\u5bc6\u94a5\n# 5. \u5907\u4efdSSH\u914d\u7f6e\u548c\u5bc6\u94a5\n
"},{"location":"Tools/Others/SSH/#2_1","title":"2. \u5e38\u89c1\u95ee\u9898\u89e3\u51b3","text":"Bash# \u8fde\u63a5\u88ab\u62d2\u7edd\nssh -v user@host # \u67e5\u770b\u8be6\u7ec6\u8fde\u63a5\u4fe1\u606f\n\n# \u6743\u9650\u95ee\u9898\nls -la ~/.ssh # \u68c0\u67e5\u6743\u9650\nchmod 600 ~/.ssh/id_ed25519\n\n# \u5bc6\u94a5\u95ee\u9898\nssh-add -l # \u67e5\u770b\u5df2\u52a0\u8f7d\u7684\u5bc6\u94a5\nssh-add ~/.ssh/id_ed25519 # \u6dfb\u52a0\u5bc6\u94a5\u5230agent\n
"},{"location":"Tools/Others/SSH/#3_2","title":"3. \u65e5\u5fd7\u67e5\u770b","text":"Bash# \u670d\u52a1\u5668\u7aef\nsudo tail -f /var/log/auth.log # Debian/Ubuntu\nsudo tail -f /var/log/secure # CentOS/RHEL\n\n# \u5ba2\u6237\u7aef\u8c03\u8bd5\nssh -vvv user@host # \u6700\u8be6\u7ec6\u7684\u8c03\u8bd5\u4fe1\u606f\n
"},{"location":"Tools/Others/zotero_%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/","title":"zotero_\u4f7f\u7528\u6307\u5357","text":"\u7ea6 156 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Zotero
#Tools
","tags":["Zotero","Tools"]},{"location":"Tools/Others/zotero_%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#zotero","title":"zotero \u4f7f\u7528\u6307\u5357","text":"\u7ea6 236 \u4e2a\u5b57 789 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 11 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Terminal/Tabby_Zsh/#_1","title":"\u524d\u7f6e\u51c6\u5907","text":"\u7cfb\u7edf\u8981\u6c42
Bash# Ubuntu/Debian\nsudo apt update\nsudo apt install -y \\\n git \\\n curl \\\n wget \\\n build-essential \\\n cmake \\\n python3-pip \\\n pkg-config \\\n libssl-dev\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#zsh","title":"ZSH \u57fa\u7840\u914d\u7f6e","text":"ZSH \u5b89\u88c5
Bash# \u5b89\u88c5zsh\nsudo apt install zsh\n\n# \u8bbe\u7f6e\u4e3a\u9ed8\u8ba4shell\nchsh -s $(which zsh)\n\n# \u786e\u8ba4\u8bbe\u7f6e\necho $SHELL\n# \u5e94\u8be5\u8f93\u51fa: /usr/bin/zsh\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#1-oh-my-zsh","title":"1. Oh My Zsh \u5b89\u88c5","text":"Bash# \u5b89\u88c5Oh My Zsh\nsh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n\n# \u5907\u4efd\u9ed8\u8ba4\u914d\u7f6e\ncp ~/.zshrc ~/.zshrc.backup\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2","title":"2. \u63d2\u4ef6\u7ba1\u7406\u5668\u5b89\u88c5","text":"Bash# \u5b89\u88c5zinit\nbash -c \"$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/install.sh)\"\n\n# \u7b49\u5f85\u5b89\u88c5\u5b8c\u6210\u540e\u91cd\u542f\u7ec8\u7aef\nexec zsh\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3","title":"3. \u57fa\u7840\u914d\u7f6e\u6587\u4ef6","text":"Bash# \u521b\u5efa\u65b0\u7684\u914d\u7f6e\u6587\u4ef6\ncat << 'EOF' > ~/.zshrc\n# \u57fa\u7840\u8bbe\u7f6e\nexport ZSH=\"$HOME/.oh-my-zsh\"\nexport LANG=en_US.UTF-8\nexport EDITOR='nvim'\nexport VISUAL='nvim'\n\n# zinit\u914d\u7f6e\nsource \"$HOME/.local/share/zinit/zinit.git/zinit.zsh\"\nautoload -Uz _zinit\n(( ${+_comps} )) && _comps[zinit]=_zinit\n\n# \u52a0\u8f7d\u6838\u5fc3\u63d2\u4ef6\nzinit ice depth=1; zinit light romkatv/powerlevel10k # \u4e3b\u9898\nzinit light zsh-users/zsh-autosuggestions # \u547d\u4ee4\u5efa\u8bae\nzinit light zsh-users/zsh-syntax-highlighting # \u8bed\u6cd5\u9ad8\u4eae\nzinit light zsh-users/zsh-completions # \u8865\u5168\u589e\u5f3a\nzinit light agkozak/zsh-z # \u76ee\u5f55\u8df3\u8f6c\n\n# \u5386\u53f2\u8bb0\u5f55\u8bbe\u7f6e\nHISTFILE=\"$HOME/.zsh_history\"\nHISTSIZE=50000\nSAVEHIST=50000\nsetopt EXTENDED_HISTORY # \u8bb0\u5f55\u547d\u4ee4\u65f6\u95f4\u6233\nsetopt HIST_EXPIRE_DUPS_FIRST # \u4f18\u5148\u5220\u9664\u91cd\u590d\u547d\u4ee4\nsetopt HIST_IGNORE_DUPS # \u5ffd\u7565\u8fde\u7eed\u91cd\u590d\u547d\u4ee4\nsetopt HIST_IGNORE_SPACE # \u5ffd\u7565\u4ee5\u7a7a\u683c\u5f00\u5934\u7684\u547d\u4ee4\nsetopt HIST_VERIFY # \u6267\u884c\u5386\u53f2\u547d\u4ee4\u524d\u5c55\u793a\nsetopt INC_APPEND_HISTORY # \u5b9e\u65f6\u6dfb\u52a0\u5386\u53f2\u8bb0\u5f55\nsetopt SHARE_HISTORY # \u5171\u4eab\u5386\u53f2\u8bb0\u5f55\n\n# \u76ee\u5f55\u8bbe\u7f6e\nsetopt AUTO_CD \nsetopt AUTO_PUSHD \nsetopt PUSHD_IGNORE_DUPS \nsetopt PUSHD_MINUS \nDIRSTACKSIZE=20\n\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4","title":"4. \u5b9e\u7528\u522b\u540d\u8bbe\u7f6e","text":"Bash# \u6dfb\u52a0\u5230~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u57fa\u7840\u547d\u4ee4\u589e\u5f3a\nalias ls='ls --color=auto'\nalias ll='ls -lah'\nalias la='ls -A'\nalias l='ls -CF'\nalias grep='grep --color=auto'\nalias rm='rm -i'\nalias cp='cp -i'\nalias mv='mv -i'\nalias mkdir='mkdir -p'\nalias df='df -h'\nalias free='free -m'\nalias duf='du -sh *'\nalias ps='ps auxf'\nalias ping='ping -c 5'\nalias root='sudo -i'\nalias reboot='sudo reboot'\nalias poweroff='sudo poweroff'\n\n# Git\u5feb\u6377\u547d\u4ee4\nalias gs='git status'\nalias ga='git add'\nalias gaa='git add --all'\nalias gc='git commit -m'\nalias gp='git push'\nalias gl='git pull'\nalias gd='git diff'\nalias gco='git checkout'\nalias gb='git branch'\nalias gm='git merge'\nalias glog='git log --oneline --decorate --graph'\n\n# Docker\u5feb\u6377\u547d\u4ee4\nalias dk='docker'\nalias dkc='docker-compose'\nalias dkps='docker ps'\nalias dkst='docker stats'\nalias dktop='docker top'\nalias dkimg='docker images'\nalias dkpull='docker pull'\nalias dkex='docker exec -it'\n\n# \u5feb\u901f\u7f16\u8f91\nalias zshconfig=\"$EDITOR ~/.zshrc\"\nalias zshreload=\"source ~/.zshrc\"\nalias vimconfig=\"$EDITOR ~/.vimrc\"\nalias tmuxconfig=\"$EDITOR ~/.tmux.conf\"\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#5","title":"5. \u5b9e\u7528\u51fd\u6570","text":"Bash# \u6dfb\u52a0\u5230~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u521b\u5efa\u5e76\u8fdb\u5165\u76ee\u5f55\nmkcd() {\n mkdir -p \"$1\" && cd \"$1\"\n}\n\n# \u63d0\u53d6\u538b\u7f29\u6587\u4ef6\nextract() {\n if [ -f $1 ]; then\n case $1 in\n *.tar.bz2) tar xjf $1 ;;\n *.tar.gz) tar xzf $1 ;;\n *.bz2) bunzip2 $1 ;;\n *.rar) unrar e $1 ;;\n *.gz) gunzip $1 ;;\n *.tar) tar xf $1 ;;\n *.tbz2) tar xjf $1 ;;\n *.tgz) tar xzf $1 ;;\n *.zip) unzip $1 ;;\n *.Z) uncompress $1 ;;\n *.7z) 7z x $1 ;;\n *) echo \"'$1' cannot be extracted\" ;;\n esac\n else\n echo \"'$1' is not a valid file\"\n fi\n}\n\n# \u5feb\u901f\u67e5\u627e\u6587\u4ef6\nff() { find . -type f -iname \"*$1*\" ; }\nfd() { find . -type d -iname \"*$1*\" ; }\n\n# \u5feb\u901f\u67e5\u770b\u8fdb\u7a0b\npsg() { ps aux | grep -v grep | grep -i -e VSZ -e \"$1\"; }\n\n# \u7f51\u7edc\u5de5\u5177\nmyip() {\n curl -s http://ipecho.net/plain\n echo\n}\n\n# \u5feb\u901fHTTP\u670d\u52a1\u5668\nserve() {\n local port=\"${1:-8000}\"\n python3 -m http.server \"$port\"\n}\n\n# Git\u65e5\u5fd7\u7f8e\u5316\ngll() {\n git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit\n}\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_2","title":"\u4e3b\u9898\u7f8e\u5316\u4e0e\u63d2\u4ef6\u589e\u5f3a","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#powerlevel10k","title":"\u4e00\u3001Powerlevel10k \u4e3b\u9898\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1","title":"1. \u5b89\u88c5\u5fc5\u8981\u5b57\u4f53","text":"Bash# \u521b\u5efa\u5b57\u4f53\u76ee\u5f55\nmkdir -p ~/.local/share/fonts\n\n# \u4e0b\u8f7d\u63a8\u8350\u5b57\u4f53\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Italic.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold%20Italic.ttf\n\n# \u79fb\u52a8\u5b57\u4f53\u6587\u4ef6\nmv /tmp/MesloLGS*.ttf ~/.local/share/fonts/\n\n# \u66f4\u65b0\u5b57\u4f53\u7f13\u5b58\nfc-cache -f -v\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_1","title":"2. \u4e3b\u9898\u914d\u7f6e","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# Powerlevel10k \u914d\u7f6e\n# \u542f\u7528 Powerlevel10k \u5373\u65f6\u63d0\u793a\nif [[ -r \"${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh\" ]]; then\n source \"${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh\"\nfi\n\n# \u52a0\u8f7d\u4e3b\u9898\nsource ~/.oh-my-zsh/custom/themes/powerlevel10k/powerlevel10k.zsh-theme\n\n# \u4e3b\u9898\u4e2a\u6027\u5316\u8bbe\u7f6e\nPOWERLEVEL9K_MODE='nerdfont-complete'\nPOWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(\n os_icon # \u64cd\u4f5c\u7cfb\u7edf\u56fe\u6807\n dir # \u5f53\u524d\u76ee\u5f55\n vcs # git\u72b6\u6001\n newline # \u6362\u884c\n prompt_char # \u63d0\u793a\u7b26\n)\nPOWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(\n status # \u4e0a\u4e00\u4e2a\u547d\u4ee4\u7684\u72b6\u6001\n background_jobs # \u540e\u53f0\u4efb\u52a1\n load # \u7cfb\u7edf\u8d1f\u8f7d\n ram # \u5185\u5b58\u4f7f\u7528\n time # \u65f6\u95f4\n)\n\n# \u76ee\u5f55\u663e\u793a\u8bbe\u7f6e\nPOWERLEVEL9K_DIR_BACKGROUND='blue'\nPOWERLEVEL9K_DIR_FOREGROUND='black'\nPOWERLEVEL9K_SHORTEN_DIR_LENGTH=2\nPOWERLEVEL9K_SHORTEN_STRATEGY=\"truncate_middle\"\n\n# Git\u72b6\u6001\u8bbe\u7f6e\nPOWERLEVEL9K_VCS_CLEAN_BACKGROUND='green'\nPOWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='yellow'\nPOWERLEVEL9K_VCS_MODIFIED_BACKGROUND='red'\nEOF\n\n# \u8fd0\u884c\u914d\u7f6e\u5411\u5bfc\uff08\u9996\u6b21\u4f7f\u7528\uff09\np10k configure\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_3","title":"\u4e8c\u3001\u9ad8\u7ea7\u63d2\u4ef6\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_1","title":"1. \u9ad8\u7ea7\u8865\u5168\u7cfb\u7edf","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u8865\u5168\u7cfb\u7edf\u914d\u7f6e\nautoload -Uz compinit\ncompinit\n\n# \u8865\u5168\u83dc\u5355\u8bbe\u7f6e\nzstyle ':completion:*' menu select\nzstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # \u5ffd\u7565\u5927\u5c0f\u5199\nzstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} # \u8865\u5168\u83dc\u5355\u7740\u8272\nzstyle ':completion:*' verbose yes # \u8be6\u7ec6\u8865\u5168\u83dc\u5355\nzstyle ':completion:*:descriptions' format '%U%B%d%b%u' # \u8865\u5168\u83dc\u5355\u683c\u5f0f\nzstyle ':completion:*:warnings' format '%BSorry, no matches for: %d%b'\nzstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'\nzstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'\n\n# \u4f7f\u7528\u7f13\u5b58\u52a0\u901f\u8865\u5168\nzstyle ':completion:*' use-cache on\nzstyle ':completion:*' cache-path ~/.zsh/cache\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-fzf","title":"2. FZF \u96c6\u6210\u914d\u7f6e","text":"Bash# \u5b89\u88c5FZF\ngit clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf\n~/.fzf/install\n\n# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# FZF \u914d\u7f6e\nexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'\nexport FZF_DEFAULT_OPTS='--height 40% --layout=reverse --border --preview \"bat --style=numbers --color=always --line-range :500 {}\"'\n\n# FZF \u5feb\u6377\u952e\nbindkey '^T' fzf-file-widget\nbindkey '^R' fzf-history-widget\nbindkey '^[c' fzf-cd-widget\n\n# FZF \u51fd\u6570\n# \u5feb\u901f\u6253\u5f00\u6587\u4ef6\nfe() {\n local file\n file=$(fzf --query=\"$1\" --select-1 --exit-0)\n [ -n \"$file\" ] && ${EDITOR:-vim} \"$file\"\n}\n\n# \u5feb\u901f\u5207\u6362\u76ee\u5f55\nfd() {\n local dir\n dir=$(find ${1:-.} -path '*/\\.*' -prune -o -type d -print 2> /dev/null | fzf +m)\n [ -n \"$dir\" ] && cd \"$dir\"\n}\n\n# \u641c\u7d22\u5386\u53f2\u547d\u4ee4\nfh() {\n print -z $( ([ -n \"$ZSH_NAME\" ] && fc -l 1 || history) | fzf +s --tac | sed -E 's/ *[0-9]*\\*? *//' | sed -E 's/\\\\/\\\\\\\\/g')\n}\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3_1","title":"3. \u589e\u5f3a\u76ee\u5f55\u5bfc\u822a","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u76ee\u5f55\u4e66\u7b7e\nhash -d proj=~/projects\nhash -d docs=~/Documents\nhash -d dl=~/Downloads\nhash -d pics=~/Pictures\n\n# z \u63d2\u4ef6\u914d\u7f6e\nZSHZ_DATA=~/.local/share/z/data\nZSHZ_MAX_SCORE=5000\nZSHZ_CASE=smart\n\n# \u76ee\u5f55\u5806\u6808\u5bfc\u822a\nsetopt AUTO_PUSHD # \u81ea\u52a8\u5c06\u76ee\u5f55\u52a0\u5165\u5806\u6808\nsetopt PUSHD_IGNORE_DUPS # \u5ffd\u7565\u91cd\u590d\u76ee\u5f55\nsetopt PUSHD_SILENT # \u9759\u9ed8\u6a21\u5f0f\nsetopt PUSHD_TO_HOME # pushd \u4e0d\u5e26\u53c2\u6570\u65f6\u7b49\u540c\u4e8e pushd $HOME\n\n# \u76ee\u5f55\u522b\u540d\nalias -g ...='../..'\nalias -g ....='../../..'\nalias -g .....='../../../..'\nalias d='dirs -v'\nfor index ({1..9}) alias \"$index\"=\"cd +${index}\"; unset index\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4_1","title":"4. \u589e\u5f3a\u5386\u53f2\u8bb0\u5f55\u641c\u7d22","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u5386\u53f2\u8bb0\u5f55\u641c\u7d22\u914d\u7f6e\nbindkey '^[[A' history-substring-search-up\nbindkey '^[[B' history-substring-search-down\nbindkey '^P' history-substring-search-up\nbindkey '^N' history-substring-search-down\n\n# \u5386\u53f2\u8bb0\u5f55\u683c\u5f0f\u5316\nHIST_STAMPS=\"yyyy-mm-dd\"\nHISTORY_IGNORE=\"(ls|ls *|cd|cd *|pwd|exit|date|* --help)\"\n\n# \u547d\u4ee4\u6267\u884c\u65f6\u95f4\u663e\u793a\nREPORTTIME=10\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#tabby","title":"Tabby \u7ec8\u7aef\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#_4","title":"\u4e00\u3001\u5b89\u88c5\u548c\u521d\u59cb\u5316","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1-tabby","title":"1. \u5b89\u88c5 Tabby","text":"Bash# Ubuntu/Debian\nwget https://github.com/Eugeny/tabby/releases/latest/download/tabby-1.0.0-linux-x64.deb\nsudo dpkg -i tabby-*.deb\nsudo apt-get install -f\n\n# \u786e\u4fdd\u5b57\u4f53\u652f\u6301\nfc-cache -fv\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_2","title":"2. \u521d\u59cb\u914d\u7f6e","text":"YAML# ~/.config/tabby/config.yaml\nconfig:\n version: 3\n\nterminal:\n shell: zsh # \u4f7f\u7528\u524d\u9762\u914d\u7f6e\u7684zsh\n fontSize: 14\n lineHeight: 1.2\n bell: 'off'\n copyOnSelect: true\n rightClick: menu\n\n # \u57fa\u7840\u73af\u5883\u53d8\u91cf\n environment:\n TERM: xterm-256color\n COLORTERM: truecolor\n\n # \u6027\u80fd\u8bbe\u7f6e\n performanceMode: true\n gpuAcceleration: true\n webGL: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_5","title":"\u4e8c\u3001\u5916\u89c2\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_2","title":"1. \u5b57\u4f53\u8bbe\u7f6e","text":"YAMLterminal:\n font: JetBrainsMono Nerd Font # \u786e\u4fdd\u5df2\u5b89\u88c5\n fontSize: 14\n lineHeight: 1.2\n ligatures: true # \u8fde\u5b57\u652f\u6301\n\n # \u5b57\u4f53\u56de\u9000\n fallbackFont: 'Sarasa Mono SC' # \u4e2d\u6587\u652f\u6301\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-dracula","title":"2. Dracula \u4e3b\u9898\u914d\u7f6e","text":"YAMLprofiles:\n - name: Default\n theme:\n name: 'Dracula'\n\n colors:\n background: '#282a36'\n foreground: '#f8f8f2'\n cursor: '#f8f8f2'\n\n selection:\n background: '#44475a'\n foreground: '#f8f8f2'\n\n # ANSI Colors\n black: '#21222c'\n red: '#ff5555'\n green: '#50fa7b'\n yellow: '#f1fa8c'\n blue: '#bd93f9'\n magenta: '#ff79c6'\n cyan: '#8be9fd'\n white: '#f8f8f2'\n\n # Bright Colors\n brightBlack: '#6272a4'\n brightRed: '#ff6e6e'\n brightGreen: '#69ff94'\n brightYellow: '#ffffa5'\n brightBlue: '#d6acff'\n brightMagenta: '#ff92df'\n brightCyan: '#a4ffff'\n brightWhite: '#ffffff'\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3_2","title":"3. \u900f\u660e\u80cc\u666f\u914d\u7f6e","text":"YAMLterminal:\n background:\n type: 'image' # \u6216 'color'\n image: '~/.config/tabby/backgrounds/bg.jpg' # \u81ea\u5b9a\u4e49\u80cc\u666f\u56fe\u7247\n opacity: 0.85 # \u900f\u660e\u5ea6\n\n # \u4e9a\u514b\u529b\u6548\u679c\uff08Windows\uff09\n experimental:\n vibrancy: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_6","title":"\u4e09\u3001\u5feb\u6377\u952e\u914d\u7f6e","text":"YAMLhotkeys:\n # \u6807\u7b7e\u7ba1\u7406\n new-tab: ['Ctrl+T']\n close-tab: ['Ctrl+W']\n previous-tab: ['Ctrl+Shift+Tab']\n next-tab: ['Ctrl+Tab']\n\n # \u5206\u5c4f\u64cd\u4f5c\n split-right: ['Ctrl+Shift+E']\n split-bottom: ['Ctrl+Shift+O']\n split-nav-left: ['Alt+Left']\n split-nav-right: ['Alt+Right']\n split-nav-up: ['Alt+Up']\n split-nav-down: ['Alt+Down']\n\n # \u7ec8\u7aef\u64cd\u4f5c\n clear: ['Ctrl+L']\n copy: ['Ctrl+C']\n paste: ['Ctrl+V']\n search: ['Ctrl+Shift+F']\n\n # \u89c6\u56fe\u63a7\u5236\n zoom-in: ['Ctrl+Plus']\n zoom-out: ['Ctrl+Minus']\n reset-zoom: ['Ctrl+0']\n toggle-fullscreen: ['F11']\n\n # \u5feb\u901f\u547d\u4ee4\n command-palette: ['Ctrl+Shift+P']\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#ssh","title":"\u56db\u3001SSH \u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1-ssh","title":"1. \u57fa\u7840 SSH \u914d\u7f6e","text":"YAMLssh:\n auth:\n agent: true\n privateKeys:\n - ~/.ssh/id_ed25519\n - ~/.ssh/id_rsa\n\n # \u8fde\u63a5\u4fdd\u6301\n keepaliveInterval: 30\n keepaliveCountMax: 3\n\n # \u8f6c\u53d1\u8bbe\u7f6e\n forwardAgent: true\n x11: false\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-ssh","title":"2. SSH \u8fde\u63a5\u914d\u7f6e","text":"YAMLssh:\n profiles:\n - name: \"\u5f00\u53d1\u670d\u52a1\u5668\"\n group: \"\u5f00\u53d1\u73af\u5883\"\n host: dev.example.com\n port: 22\n user: username\n auth: publicKey\n privateKey: ~/.ssh/id_ed25519\n\n - name: \"\u751f\u4ea7\u670d\u52a1\u5668\"\n group: \"\u751f\u4ea7\u73af\u5883\"\n host: prod.example.com\n port: 22\n user: username\n auth: agent\n\n - name: \"\u8df3\u677f\u673a\"\n host: jump.example.com\n forwardAgent: true\n jumpHost: true # \u6807\u8bb0\u4e3a\u8df3\u677f\u673a\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_7","title":"\u4e94\u3001\u63d2\u4ef6\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_3","title":"1. \u6838\u5fc3\u63d2\u4ef6","text":"YAMLplugins:\n # SSH\u7ba1\u7406\n ssh:\n enabled: true\n\n # \u7ec8\u7aef\u5f55\u5236\n record:\n enabled: true\n directory: ~/terminal-records\n\n # \u547d\u4ee4\u9762\u677f\n commander:\n enabled: true\n\n # \u4e3b\u9898\u63d2\u4ef6\n community-color-schemes:\n enabled: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_3","title":"2. \u6269\u5c55\u529f\u80fd","text":"YAML# \u641c\u7d22\u589e\u5f3a\nsearch:\n enabled: true\n searchOptions:\n regex: true\n wholeWord: false\n caseSensitive: false\n\n# \u7ec8\u7aef\u5206\u5272\nsplit:\n autoRemove: true # \u81ea\u52a8\u5173\u95ed\u7a7a\u7ec8\u7aef\n copyOnSelect: true\n pasteOnMiddleClick: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_8","title":"\u516d\u3001\u6027\u80fd\u4f18\u5316","text":"YAML# \u6027\u80fd\u76f8\u5173\u914d\u7f6e\nterminal:\n # \u57fa\u7840\u4f18\u5316\n performanceMode: true\n gpuAcceleration: true\n webGL: true\n\n # \u5386\u53f2\u8bb0\u5f55\n scrollback: 5000\n\n # \u8fdb\u7a0b\u7ba1\u7406\n autoClose: true\n closeOnExit: true\n\n # \u6e32\u67d3\u4f18\u5316\n smoothScroll: false\n experimentalFontRendering: false\n\n # \u8d44\u6e90\u9650\u5236\n environment:\n LIMIT_MEMORY: 512 # MB\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_9","title":"\u5f00\u53d1\u5de5\u5177\u4e0e\u7ec8\u7aef\u5de5\u5177\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#_10","title":"\u4e00\u3001\u73b0\u4ee3\u547d\u4ee4\u884c\u5de5\u5177","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_4","title":"1. \u57fa\u7840\u5de5\u5177\u5b89\u88c5","text":"Bash# \u5b89\u88c5\u57fa\u7840\u5de5\u5177\nsudo apt install -y \\\n exa `# \u73b0\u4ee3ls\u66ff\u4ee3\u54c1` \\\n bat `# \u73b0\u4ee3cat\u66ff\u4ee3\u54c1` \\\n ripgrep `# \u73b0\u4ee3grep\u66ff\u4ee3\u54c1` \\\n fd-find `# \u73b0\u4ee3find\u66ff\u4ee3\u54c1` \\\n duf `# \u73b0\u4ee3df\u66ff\u4ee3\u54c1` \\\n ncdu `# \u78c1\u76d8\u4f7f\u7528\u5206\u6790` \\\n tldr `# \u547d\u4ee4\u7b80\u5316\u8bf4\u660e` \\\n jq `# JSON\u5904\u7406` \\\n fzf `# \u6a21\u7cca\u641c\u7d22`\n\n# \u521b\u5efa\u522b\u540d\ncat << 'EOF' >> ~/.zshrc\n# \u73b0\u4ee3\u547d\u4ee4\u884c\u5de5\u5177\u522b\u540d\nalias ls='exa --icons'\nalias ll='exa -l --icons --git'\nalias la='exa -la --icons --git'\nalias lt='exa -T --icons --git-ignore'\nalias cat='batcat'\nalias find='fd'\nalias du='ncdu'\nalias df='duf'\nalias help='tldr'\n\n# fzf \u914d\u7f6e\nexport FZF_DEFAULT_OPTS=\"--height 40% --layout=reverse --border \\\n --preview 'batcat --style=numbers --color=always --line-range :500 {}'\"\nexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'\nexport FZF_CTRL_T_COMMAND=\"$FZF_DEFAULT_COMMAND\"\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-ranger","title":"2. \u6587\u4ef6\u7ba1\u7406\u5668 - Ranger","text":"Bash# \u5b89\u88c5ranger\u548c\u4f9d\u8d56\nsudo apt install ranger python3-pillow ueberzug\n\n# \u751f\u6210\u914d\u7f6e\u6587\u4ef6\nranger --copy-config=all\n\n# \u914d\u7f6eRanger\ncat << 'EOF' > ~/.config/ranger/rc.conf\n# \u57fa\u7840\u8bbe\u7f6e\nset preview_images true\nset preview_images_method ueberzug\nset show_hidden true\nset hostname_in_titlebar false\nset tilde_in_titlebar true\nset line_numbers relative\nset mouse_enabled true\n\n# \u914d\u8272\u65b9\u6848\nset colorscheme solarized\n\n# \u6587\u4ef6\u9884\u89c8\nset use_preview_script true\nset preview_files true\nset preview_directories true\nset collapse_preview true\n\n# \u5feb\u6377\u952e\nmap <C-f> fzf_select\nmap <C-p> shell -w echo %d/%f | xsel -b\nmap <C-g> shell lazygit\nEOF\n\n# \u6dfb\u52a0FZF\u96c6\u6210\ncat << 'EOF' > ~/.config/ranger/commands.py\nfrom ranger.api.commands import Command\nclass fzf_select(Command):\n def execute(self):\n import subprocess\n import os.path\n command=\"find -L . \\( -path '*/\\.*' -o -fstype 'dev' -o -fstype 'proc' \\) -prune \\\n -o -print 2> /dev/null | sed 1d | cut -b3- | fzf +m\"\n fzf = self.fm.execute_command(command, universal_newlines=True, stdout=subprocess.PIPE)\n stdout, stderr = fzf.communicate()\n if fzf.returncode == 0:\n fzf_file = os.path.abspath(stdout.rstrip('\\n'))\n if os.path.isdir(fzf_file):\n self.fm.cd(fzf_file)\n else:\n self.fm.select_file(fzf_file)\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3-htopglances","title":"3. \u7cfb\u7edf\u76d1\u63a7 - htop/glances","text":"Bash# \u5b89\u88c5\u5de5\u5177\nsudo apt install htop glances\n\n# htop\u914d\u7f6e\nmkdir -p ~/.config/htop\ncat << 'EOF' > ~/.config/htop/htoprc\n# \u57fa\u7840\u663e\u793a\u8bbe\u7f6e\nshow_cpu_frequency=1\nshow_cpu_temperature=1\nshow_program_path=0\nhighlight_base_name=1\nhighlight_megabytes=1\nhighlight_threads=1\n\n# \u663e\u793a\u8bbe\u7f6e\nfields=0 48 17 18 38 39 40 2 46 47 49 1\nsort_key=46\nsort_direction=-1\ntree_view=1\ntree_view_always_by_pid=0\n\n# \u989c\u8272\u8bbe\u7f6e\ncolor_scheme=0\nEOF\n\n# glances\u914d\u7f6e\nmkdir -p ~/.config/glances\ncat << 'EOF' > ~/.config/glances/glances.conf\n[global]\n# \u5237\u65b0\u95f4\u9694\nrefresh=2\n# \u5386\u53f2\u5927\u5c0f\nhistory_size=1200\n\n[cpu]\n# CPU \u8b66\u544a\u9608\u503c\ncareful=50\nwarning=70\ncritical=90\n\n[memory]\n# \u5185\u5b58\u8b66\u544a\u9608\u503c\ncareful=50\nwarning=70\ncritical=90\n\n[network]\n# \u7f51\u7edc\u5e26\u5bbd\u663e\u793a\u5355\u4f4d (bit/sec)\nunit=bit\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4-git-lazygit","title":"4. Git \u5de5\u5177 - Lazygit","text":"Bash# \u5b89\u88c5Lazygit\nLAZYGIT_VERSION=$(curl -s \"https://api.github.com/repos/jesseduffield/lazygit/releases/latest\" | grep -Po '\"tag_name\": \"v\\K[^\"]*')\ncurl -Lo lazygit.tar.gz \"https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz\"\nsudo tar xf lazygit.tar.gz -C /usr/local/bin lazygit\n\n# \u914d\u7f6eLazygit\nmkdir -p ~/.config/lazygit\ncat << 'EOF' > ~/.config/lazygit/config.yml\ngui:\n # UI\u4e3b\u9898\n theme:\n lightTheme: false\n activeBorderColor:\n - green\n - bold\n inactiveBorderColor:\n - white\n selectedLineBgColor:\n - reverse\n # \u5e38\u7528\u8bbe\u7f6e \n showFileTree: true\n showRandomTip: false\n showCommandLog: false\n\ngit:\n # git\u8bbe\u7f6e\n paging:\n colorArg: always\n useConfig: true\n # commit\u8bbe\u7f6e\n commits:\n showGraph: always\n showWholeGraph: true\n # \u81ea\u52a8\u83b7\u53d6\n autoFetch: true\n # \u5206\u652f\u663e\u793a\n branchLogCmd: \"git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --\"\n\nkeybinding:\n # \u81ea\u5b9a\u4e49\u5feb\u6377\u952e\n universal:\n return: '<c-c>'\n quit: 'q'\n quit-alt1: '<esc>'\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#5_1","title":"5. \u4ee3\u7801\u641c\u7d22\u5de5\u5177","text":"Bash# ripgrep\u914d\u7f6e\ncat << 'EOF' >> ~/.zshrc\n# ripgrep \u914d\u7f6e\nexport RIPGREP_CONFIG_PATH=\"$HOME/.ripgreprc\"\n\n# ripgrep \u522b\u540d\nalias rg='rg --smart-case'\nalias rgf='rg --files | rg'\nalias rgh='rg --hidden'\nalias rgc='rg --count'\n\n# fzf + ripgrep \u96c6\u6210\nfif() {\n if [ ! \"$#\" -gt 0 ]; then echo \"Need a string to search for!\"; return 1; fi\n rg --files-with-matches --no-messages \"$1\" | fzf --preview \"highlight -O ansi -l {} 2> /dev/null | rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' || rg --ignore-case --pretty --context 10 '$1' {}\"\n}\nEOF\n\n# \u521b\u5efaripgrep\u914d\u7f6e\u6587\u4ef6\ncat << 'EOF' > ~/.ripgreprc\n# \u9ed8\u8ba4\u914d\u7f6e\n--smart-case\n--hidden\n--follow\n--glob=!.git/*\n\n# \u641c\u7d22\u914d\u7f6e\n--max-columns=150\n--max-columns-preview\n\n# \u989c\u8272\u914d\u7f6e\n--colors=line:fg:yellow\n--colors=line:style:bold\n--colors=path:fg:green\n--colors=path:style:bold\n--colors=match:fg:black\n--colors=match:bg:yellow\n--colors=match:style:nobold\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#6","title":"6. \u5b9e\u7528\u5f00\u53d1\u5de5\u5177","text":"Bash# \u5b89\u88c5\u5f00\u53d1\u8f85\u52a9\u5de5\u5177\nsudo apt install -y \\\n shellcheck `# shell\u811a\u672c\u68c0\u67e5` \\\n python3-pip `# Python\u5305\u7ba1\u7406` \\\n nodejs npm `# Node.js\u73af\u5883` \\\n golang `# Go\u8bed\u8a00\u73af\u5883` \\\n docker.io `# Docker\u652f\u6301` \\\n postgresql-client `# \u6570\u636e\u5e93\u5ba2\u6237\u7aef` \\\n redis-tools `# Redis\u5ba2\u6237\u7aef` \\\n mycli `# MySQL\u5ba2\u6237\u7aef` \\\n httpie `# HTTP\u5ba2\u6237\u7aef`\n\n# \u6dfb\u52a0\u5b9e\u7528\u522b\u540d\u548c\u51fd\u6570\ncat << 'EOF' >> ~/.zshrc\n# Docker\u522b\u540d\nalias dk='docker'\nalias dkc='docker-compose'\nalias dkps='docker ps'\nalias dkst='docker stats'\nalias dkimg='docker images'\nalias dkpull='docker pull'\nalias dkexec='docker exec -it'\n\n# \u5f00\u53d1\u8f85\u52a9\u51fd\u6570\n# \u5feb\u901fHTTP\u670d\u52a1\u5668\nserve() {\n local port=\"${1:-8000}\"\n python3 -m http.server \"$port\"\n}\n\n# JSON\u683c\u5f0f\u5316\njson() {\n if [ -t 0 ]; then # \u53c2\u6570\u8f93\u5165\n python -m json.tool <<< \"$*\" | pygmentize -l json\n else # \u7ba1\u9053\u8f93\u5165\n python -m json.tool | pygmentize -l json\n fi\n}\n\n# Git\u5206\u652f\u6e05\u7406\ngit-clean() {\n git branch --merged | egrep -v \"(^\\*|master|main|dev)\" | xargs git branch -d\n}\n\n# \u73af\u5883\u53d8\u91cf\u7ba1\u7406\nenvfile() {\n if [[ -f \"$1\" ]]; then\n set -a\n source \"$1\"\n set +a\n else\n echo \"Error: File $1 not found\"\n return 1\n fi\n}\nEOF\n
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"Welcome to wnc's note! My friends! / About Me
"},{"location":"Links/","title":"\u53cb\u94fe","text":""},{"location":"Links/#_1","title":"\u53cb\u94fe","text":"Abstract
My friends!
Wnc \u7684\u5496\u5561\u9986 \u6211\u81ea\u5df1\uff01 donotknow DoNotKnow Kinnari \u5f88\u5389\u5bb3\u7684\u5b66\u957f\uff01 MenGrey \u5f88\u5389\u5bb3\u7684\u540c\u5b66\uff01"},{"location":"AI/","title":"AI","text":""},{"location":"AI/#artificial-intelligence","title":"Artificial Intelligence","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
FFB6D \u590d\u73b0\u7ea6 1547 \u4e2a\u5b57 387 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 13 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/Dive_into_Deep_Learning/#1","title":"1 \u5f15\u8a00","text":""},{"location":"AI/Dive_into_Deep_Learning/#2","title":"2 \u9884\u5907\u77e5\u8bc6","text":""},{"location":"AI/Dive_into_Deep_Learning/#21","title":"2.1 \u6570\u636e\u64cd\u4f5c","text":"x = torch.arrange(12)\nx.shape\nx.numel()\nx.reshape(3, 4)\ntorch.zeros((2, 3, 4))\ntorch.ones((2, 3, 4))\ntorch.randn(3, 4)\n
torch.cat((X, Y), dim = 0) # \u7ad6\u7740\u52a0\ntorch.cat((X, Y), dim = 1) # \u6a2a\u7740\u52a0\nx.sum()\n
x.requires_grad_(True) # \u7b49\u4ef7\u4e8ex=torch.arange(4.0,requires_grad=True)\nx.grad # \u9ed8\u8ba4\u503c\u662fNone\ny = 2 * torch.dot(x, x)\ny.backward()\nx.grad\nx.grad == 4 * x\n
"},{"location":"AI/Dive_into_Deep_Learning/#251","title":"2.5.1 \u975e\u6807\u91cf\u53d8\u91cf\u7684\u53cd\u5411\u4f20\u64ad","text":"Python# \u5bf9\u975e\u6807\u91cf\u8c03\u7528backward\u9700\u8981\u4f20\u5165\u4e00\u4e2agradient\u53c2\u6570\uff0c\u8be5\u53c2\u6570\u6307\u5b9a\u5fae\u5206\u51fd\u6570\u5173\u4e8eself\u7684\u68af\u5ea6\u3002\n# \u672c\u4f8b\u53ea\u60f3\u6c42\u504f\u5bfc\u6570\u7684\u548c\uff0c\u6240\u4ee5\u4f20\u9012\u4e00\u4e2a1\u7684\u68af\u5ea6\u662f\u5408\u9002\u7684\nx.grad.zero_()\ny = x * x\n# \u7b49\u4ef7\u4e8ey.backward(torch.ones(len(x)))\ny.sum().backward()\nx.grad\n
"},{"location":"AI/Dive_into_Deep_Learning/#252","title":"2.5.2 \u5206\u79bb\u8ba1\u7b97","text":"Pythonx.grad.zero_()\ny = x * x\nu = y.detach()\nz = u * x\n\nz.sum().backward()\nx.grad == u\n
"},{"location":"AI/Dive_into_Deep_Learning/#26","title":"2.6 \u6982\u7387","text":""},{"location":"AI/Dive_into_Deep_Learning/#261","title":"2.6.1 \u57fa\u672c\u6982\u7387\u8bba","text":"fair_probs = torch.ones([6]) / 6\nmultinomial.Multinomial(10, fair_probs).sample() # \u591a\u4e2a\u6837\u672c\n
"},{"location":"AI/Dive_into_Deep_Learning/#262","title":"2.6.2 \u5904\u7406\u591a\u4e2a\u968f\u673a\u53d8\u91cf","text":"$$ P(A, B \\mid C) = P(A \\mid C)P(B \\mid C) $$
\\[ A \\perp B \\mid C \\]%matplotlib inline\nimport random\nimport torch\nfrom d2l import torch as d2l\ndef synthetic_data(w, b, num_examples): #@save\n \"\"\"\u751f\u6210y=Xw+b+\u566a\u58f0\"\"\"\n X = torch.normal(0, 1, (num_examples, len(w)))\n y = torch.matmul(X, w) + b\n y += torch.normal(0, 0.01, y.shape)\n return X, y.reshape((-1, 1))\n\ntrue_w = torch.tensor([2, -3.4])\ntrue_b = 4.2\nfeatures, labels = synthetic_data(true_w, true_b, 1000)\n\ndef data_iter(batch_size, features, labels):\n num_examples = len(features)\n indices = list(range(num_examples))\n # \u8fd9\u4e9b\u6837\u672c\u662f\u968f\u673a\u8bfb\u53d6\u7684\uff0c\u6ca1\u6709\u7279\u5b9a\u7684\u987a\u5e8f\n random.shuffle(indices)\n for i in range(0, num_examples, batch_size):\n batch_indices = torch.tensor(\n indices[i: min(i + batch_size, num_examples)])\n yield features[batch_indices], labels[batch_indices]\n\nw = torch.normal(0, 0.01, size=(2,1), requires_grad=True)\nb = torch.zeros(1, requires_grad=True)\n\ndef linreg(X, w, b): #@save\n \"\"\"\u7ebf\u6027\u56de\u5f52\u6a21\u578b\"\"\"\n return torch.matmul(X, w) + b\n\ndef squared_loss(y_hat, y): #@save\n \"\"\"\u5747\u65b9\u635f\u5931\"\"\"\n return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2\n\ndef sgd(params, lr, batch_size): #@save\n \"\"\"\u5c0f\u6279\u91cf\u968f\u673a\u68af\u5ea6\u4e0b\u964d\"\"\"\n with torch.no_grad():\n for param in params:\n param -= lr * param.grad / batch_size\n param.grad.zero_()\n\nlr = 0.03\nnum_epochs = 3\nnet = linreg\nloss = squared_loss\n\nfor epoch in range(num_epochs):\n for X, y in data_iter(batch_size, features, labels):\n l = loss(net(X, w, b), y) # X\u548cy\u7684\u5c0f\u6279\u91cf\u635f\u5931\n # \u56e0\u4e3al\u5f62\u72b6\u662f(batch_size,1)\uff0c\u800c\u4e0d\u662f\u4e00\u4e2a\u6807\u91cf\u3002l\u4e2d\u7684\u6240\u6709\u5143\u7d20\u88ab\u52a0\u5230\u4e00\u8d77\uff0c\n # \u5e76\u4ee5\u6b64\u8ba1\u7b97\u5173\u4e8e[w,b]\u7684\u68af\u5ea6\n l.sum().backward()\n sgd([w, b], lr, batch_size) # \u4f7f\u7528\u53c2\u6570\u7684\u68af\u5ea6\u66f4\u65b0\u53c2\u6570\n with torch.no_grad():\n train_l = loss(net(features, w, b), labels)\n print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')\n
"},{"location":"AI/Dive_into_Deep_Learning/#33","title":"3.3 \u7ebf\u6027\u56de\u5f52\u7684\u7b80\u6d01\u5b9e\u73b0","text":"Pythonimport numpy as np\nimport torch\nfrom torch.utils import data\nfrom d2l import torch as d2l\n\ntrue_w = torch.tensor([2, -3.4])\ntrue_b = 4.2\nfeatures, labels = d2l.synthetic_data(true_w, true_b, 1000) # \u751f\u6210\u6570\u636e\u96c6\n\ndef load_array(data_arrays, batch_size, is_train=True): #@save\n \"\"\"\u6784\u9020\u4e00\u4e2aPyTorch\u6570\u636e\u8fed\u4ee3\u5668\"\"\"\n dataset = data.TensorDataset(*data_arrays)\n return data.DataLoader(dataset, batch_size, shuffle=is_train)\n\nbatch_size = 10\ndata_iter = load_array((features, labels), batch_size) # \u8bfb\u53d6\u6570\u636e\u96c6\n\n# nn\u662f\u795e\u7ecf\u7f51\u7edc\u7684\u7f29\u5199\nfrom torch import nn\n\nnet = nn.Sequential(nn.Linear(2, 1)) # \u5b9a\u4e49\u6a21\u578b \uff08\u8f93\u5165\uff0c\u8f93\u51fa\uff09\u7279\u5f81\u5f62\u72b6\nnet[0].weight.data.normal_(0, 0.01)\nnet[0].bias.data.fill_(0) # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\nloss = nn.MSELoss() # \u5b9a\u4e49\u635f\u5931\u51fd\u6570\ntrainer = torch.optim.SGD(net.parameters(), lr=0.03) # \u5b9a\u4e49\u4f18\u5316\u7b97\u6cd5\n\n# \u8bad\u7ec3\nnum_epochs = 3\nfor epoch in range(num_epochs):\n for X, y in data_iter:\n l = loss(net(X) ,y)\n trainer.zero_grad()\n l.backward()\n trainer.step()\n l = loss(net(features), labels)\n print(f'epoch {epoch + 1}, loss {l:f}')\n\nw = net[0].weight.data\nprint('w\u7684\u4f30\u8ba1\u8bef\u5dee\uff1a', true_w - w.reshape(true_w.shape))\nb = net[0].bias.data\nprint('b\u7684\u4f30\u8ba1\u8bef\u5dee\uff1a', true_b - b)\n
"},{"location":"AI/Dive_into_Deep_Learning/#34-softmax","title":"3.4 softmax \u56de\u5f52","text":""},{"location":"AI/Dive_into_Deep_Learning/#341","title":"3.4.1 \u5206\u7c7b\u95ee\u9898","text":"%matplotlib inline\nimport torch\nimport torchvision\nfrom torch.utils import data\nfrom torchvision import transforms\nfrom d2l import torch as d2l\n\nd2l.use_svg_display()\n\n# \u901a\u8fc7ToTensor\u5b9e\u4f8b\u5c06\u56fe\u50cf\u6570\u636e\u4ecePIL\u7c7b\u578b\u53d8\u6362\u621032\u4f4d\u6d6e\u70b9\u6570\u683c\u5f0f\uff0c\n# \u5e76\u9664\u4ee5255\u4f7f\u5f97\u6240\u6709\u50cf\u7d20\u7684\u6570\u503c\u5747\u57280\uff5e1\u4e4b\u95f4\ntrans = transforms.ToTensor()\nmnist_train = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=True, transform=trans, download=True)\nmnist_test = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=False, transform=trans, download=True)\n\ndef get_fashion_mnist_labels(labels): #@save\n \"\"\"\u8fd4\u56deFashion-MNIST\u6570\u636e\u96c6\u7684\u6587\u672c\u6807\u7b7e\"\"\"\n text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',\n 'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']\n return [text_labels[int(i)] for i in labels]\n\ndef show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): #@save\n \"\"\"\u7ed8\u5236\u56fe\u50cf\u5217\u8868\"\"\"\n figsize = (num_cols * scale, num_rows * scale)\n _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)\n axes = axes.flatten()\n for i, (ax, img) in enumerate(zip(axes, imgs)):\n if torch.is_tensor(img):\n # \u56fe\u7247\u5f20\u91cf\n ax.imshow(img.numpy())\n else:\n # PIL\u56fe\u7247\n ax.imshow(img)\n ax.axes.get_xaxis().set_visible(False)\n ax.axes.get_yaxis().set_visible(False)\n if titles:\n ax.set_title(titles[i])\n return axes\n\nbatch_size = 256\n\ndef get_dataloader_workers(): #@save\n \"\"\"\u4f7f\u75284\u4e2a\u8fdb\u7a0b\u6765\u8bfb\u53d6\u6570\u636e\"\"\"\n return 4\n\ntrain_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,\n num_workers=get_dataloader_workers())\n\ndef load_data_fashion_mnist(batch_size, resize=None): #@save\n \"\"\"\u4e0b\u8f7dFashion-MNIST\u6570\u636e\u96c6\uff0c\u7136\u540e\u5c06\u5176\u52a0\u8f7d\u5230\u5185\u5b58\u4e2d\"\"\"\n trans = [transforms.ToTensor()]\n if resize:\n trans.insert(0, transforms.Resize(resize))\n trans = transforms.Compose(trans)\n mnist_train = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=True, transform=trans, download=True)\n mnist_test = torchvision.datasets.FashionMNIST(\n root=\"../data\", train=False, transform=trans, download=True)\n return (data.DataLoader(mnist_train, batch_size, shuffle=True,\n num_workers=get_dataloader_workers()),\n data.DataLoader(mnist_test, batch_size, shuffle=False,\n num_workers=get_dataloader_workers()))\n\ntrain_iter, test_iter = load_data_fashion_mnist(32, resize=64)\nfor X, y in train_iter:\n print(X.shape, X.dtype, y.shape, y.dtype)\n break\n
"},{"location":"AI/Dive_into_Deep_Learning/#36-softmax","title":"3.6 softmax \u56de\u5f52\u7684\u4ece\u96f6\u5f00\u59cb\u5b9e\u73b0","text":"Pythonimport torch\nfrom IPython import display\nfrom d2l import torch as d2l\n\nbatch_size = 256\ntrain_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)\n\nnum_inputs = 784\nnum_outputs = 10\n\nW = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)\nb = torch.zeros(num_outputs, requires_grad=True) # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\n\nX = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\nX.sum(0, keepdim=True), X.sum(1, keepdim=True) \n\ndef softmax(X):\n X_exp = torch.exp(X)\n partition = X_exp.sum(1, keepdim=True)\n return X_exp / partition # \u8fd9\u91cc\u5e94\u7528\u4e86\u5e7f\u64ad\u673a\u5236\n\nX = torch.normal(0, 1, (2, 5))\nX_prob = softmax(X)\nX_prob, X_prob.sum(1) # \u5b9a\u4e49softmax\u64cd\u4f5c\n\ndef net(X):\n return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b) # \u5b9a\u4e49\u6a21\u578b\n\ny = torch.tensor([0, 2])\ny_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])\ny_hat[[0, 1], y] \ndef cross_entropy(y_hat, y):\n return - torch.log(y_hat[range(len(y_hat)), y])\n\ncross_entropy(y_hat, y) # \u5b9a\u4e49\u635f\u5931\u51fd\u6570\n\ndef accuracy(y_hat, y): #@save\n \"\"\"\u8ba1\u7b97\u9884\u6d4b\u6b63\u786e\u7684\u6570\u91cf\"\"\"\n if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:\n y_hat = y_hat.argmax(axis=1)\n cmp = y_hat.type(y.dtype) == y\n return float(cmp.type(y.dtype).sum())\n\ndef evaluate_accuracy(net, data_iter): #@save\n \"\"\"\u8ba1\u7b97\u5728\u6307\u5b9a\u6570\u636e\u96c6\u4e0a\u6a21\u578b\u7684\u7cbe\u5ea6\"\"\"\n if isinstance(net, torch.nn.Module):\n net.eval() # \u5c06\u6a21\u578b\u8bbe\u7f6e\u4e3a\u8bc4\u4f30\u6a21\u5f0f\n metric = Accumulator(2) # \u6b63\u786e\u9884\u6d4b\u6570\u3001\u9884\u6d4b\u603b\u6570\n with torch.no_grad():\n for X, y in data_iter:\n metric.add(accuracy(net(X), y), y.numel())\n return metric[0] / metric[1]\n\nclass Accumulator: #@save\n \"\"\"\u5728n\u4e2a\u53d8\u91cf\u4e0a\u7d2f\u52a0\"\"\"\n def __init__(self, n):\n self.data = [0.0] * n\n\n def add(self, *args):\n self.data = [a + float(b) for a, b in zip(self.data, args)]\n\n def reset(self):\n self.data = [0.0] * len(self.data)\n\n def __getitem__(self, idx):\n return self.data[idx]\n\nevaluate_accuracy(net, test_iter) # \u5206\u7c7b\u7cbe\u5ea6\n\ndef train_epoch_ch3(net, train_iter, loss, updater): #@save\n \"\"\"\u8bad\u7ec3\u6a21\u578b\u4e00\u4e2a\u8fed\u4ee3\u5468\u671f\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n # \u5c06\u6a21\u578b\u8bbe\u7f6e\u4e3a\u8bad\u7ec3\u6a21\u5f0f\n if isinstance(net, torch.nn.Module):\n net.train()\n # \u8bad\u7ec3\u635f\u5931\u603b\u548c\u3001\u8bad\u7ec3\u51c6\u786e\u5ea6\u603b\u548c\u3001\u6837\u672c\u6570\n metric = Accumulator(3)\n for X, y in train_iter:\n # \u8ba1\u7b97\u68af\u5ea6\u5e76\u66f4\u65b0\u53c2\u6570\n y_hat = net(X)\n l = loss(y_hat, y)\n if isinstance(updater, torch.optim.Optimizer):\n # \u4f7f\u7528PyTorch\u5185\u7f6e\u7684\u4f18\u5316\u5668\u548c\u635f\u5931\u51fd\u6570\n updater.zero_grad()\n l.mean().backward()\n updater.step()\n else:\n # \u4f7f\u7528\u5b9a\u5236\u7684\u4f18\u5316\u5668\u548c\u635f\u5931\u51fd\u6570\n l.sum().backward()\n updater(X.shape[0])\n metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())\n # \u8fd4\u56de\u8bad\u7ec3\u635f\u5931\u548c\u8bad\u7ec3\u7cbe\u5ea6\n return metric[0] / metric[2], metric[1] / metric[2]\n\nclass Animator: #@save\n \"\"\"\u5728\u52a8\u753b\u4e2d\u7ed8\u5236\u6570\u636e\"\"\"\n def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,\n ylim=None, xscale='linear', yscale='linear',\n fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,\n figsize=(3.5, 2.5)):\n # \u589e\u91cf\u5730\u7ed8\u5236\u591a\u6761\u7ebf\n if legend is None:\n legend = []\n d2l.use_svg_display()\n self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)\n if nrows * ncols == 1:\n self.axes = [self.axes, ]\n # \u4f7f\u7528lambda\u51fd\u6570\u6355\u83b7\u53c2\u6570\n self.config_axes = lambda: d2l.set_axes(\n self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)\n self.X, self.Y, self.fmts = None, None, fmts\n\n def add(self, x, y):\n # \u5411\u56fe\u8868\u4e2d\u6dfb\u52a0\u591a\u4e2a\u6570\u636e\u70b9\n if not hasattr(y, \"__len__\"):\n y = [y]\n n = len(y)\n if not hasattr(x, \"__len__\"):\n x = [x] * n\n if not self.X:\n self.X = [[] for _ in range(n)]\n if not self.Y:\n self.Y = [[] for _ in range(n)]\n for i, (a, b) in enumerate(zip(x, y)):\n if a is not None and b is not None:\n self.X[i].append(a)\n self.Y[i].append(b)\n self.axes[0].cla()\n for x, y, fmt in zip(self.X, self.Y, self.fmts):\n self.axes[0].plot(x, y, fmt)\n self.config_axes()\n display.display(self.fig)\n display.clear_output(wait=True)\n\ndef train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save\n \"\"\"\u8bad\u7ec3\u6a21\u578b\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],\n legend=['train loss', 'train acc', 'test acc'])\n for epoch in range(num_epochs):\n train_metrics = train_epoch_ch3(net, train_iter, loss, updater)\n test_acc = evaluate_accuracy(net, test_iter)\n animator.add(epoch + 1, train_metrics + (test_acc,))\n train_loss, train_acc = train_metrics\n assert train_loss < 0.5, train_loss\n assert train_acc <= 1 and train_acc > 0.7, train_acc\n assert test_acc <= 1 and test_acc > 0.7, test_acc\n\nlr = 0.1\n\ndef updater(batch_size):\n return d2l.sgd([W, b], lr, batch_size)\n\nnum_epochs = 10\ntrain_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater) # \u8bad\u7ec3\n\ndef predict_ch3(net, test_iter, n=6): #@save\n \"\"\"\u9884\u6d4b\u6807\u7b7e\uff08\u5b9a\u4e49\u89c1\u7b2c3\u7ae0\uff09\"\"\"\n for X, y in test_iter:\n break\n trues = d2l.get_fashion_mnist_labels(y)\n preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))\n titles = [true +'\\n' + pred for true, pred in zip(trues, preds)]\n d2l.show_images(\n X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])\n\npredict_ch3(net, test_iter) # \u9884\u6d4b\n
"},{"location":"AI/Dive_into_Deep_Learning/#37-softmax","title":"3.7 softmax \u56de\u5f52\u7684\u7b80\u6d01\u5b9e\u73b0","text":"Pythonimport torch\nfrom torch import nn\nfrom d2l import torch as d2l\n\nbatch_size = 256\ntrain_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)\n\n# PyTorch\u4e0d\u4f1a\u9690\u5f0f\u5730\u8c03\u6574\u8f93\u5165\u7684\u5f62\u72b6\u3002\u56e0\u6b64\uff0c\n# \u6211\u4eec\u5728\u7ebf\u6027\u5c42\u524d\u5b9a\u4e49\u4e86\u5c55\u5e73\u5c42\uff08flatten\uff09\uff0c\u6765\u8c03\u6574\u7f51\u7edc\u8f93\u5165\u7684\u5f62\u72b6\nnet = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))\n\ndef init_weights(m):\n if type(m) == nn.Linear:\n nn.init.normal_(m.weight, std=0.01)\n\nnet.apply(init_weights); # \u521d\u59cb\u5316\u6a21\u578b\u53c2\u6570\n
\\[ \\begin{split}\\begin{aligned} \\hat y_j & = \\frac{\\exp(o_j - \\max(o_k))\\exp(\\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))\\exp(\\max(o_k))} \\\\ & = \\frac{\\exp(o_j - \\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))}. \\end{aligned}\\end{split} \\] \\[ \\begin{split}\\begin{aligned} \\log{(\\hat y_j)} & = \\log\\left( \\frac{\\exp(o_j - \\max(o_k))}{\\sum_k \\exp(o_k - \\max(o_k))}\\right) \\\\ & = \\log{(\\exp(o_j - \\max(o_k)))}-\\log{\\left( \\sum_k \\exp(o_k - \\max(o_k)) \\right)} \\\\ & = o_j - \\max(o_k) -\\log{\\left( \\sum_k \\exp(o_k - \\max(o_k)) \\right)}. \\end{aligned}\\end{split} \\] Pythonloss = nn.CrossEntropyLoss(reduction='none') # LogSumExp\u6280\u5de7\n\ntrainer = torch.optim.SGD(net.parameters(), lr=0.1) # \u4f18\u5316\u7b97\u6cd5\n\nnum_epochs = 10\nd2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer) # \u8bad\u7ec3\n
"},{"location":"AI/Dive_into_Deep_Learning/#_1","title":"\u591a\u5c42\u611f\u77e5\u673a","text":""},{"location":"AI/Dive_into_Deep_Learning/#_2","title":"\u8fc7\u62df\u5408\u548c\u6b20\u62df\u5408","text":""},{"location":"AI/Dive_into_Deep_Learning/#dropout","title":"dropout","text":""},{"location":"AI/Dive_into_Deep_Learning/#_3","title":"\u6df1\u5ea6\u5b66\u4e60\u8ba1\u7b97","text":""},{"location":"AI/Dive_into_Deep_Learning/#_4","title":"\u5377\u79ef\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#lenet","title":"LeNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#_5","title":"\u73b0\u4ee3\u5377\u79ef\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#alexnet","title":"AlexNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#vgg","title":"VGG","text":""},{"location":"AI/Dive_into_Deep_Learning/#nin","title":"NiN","text":""},{"location":"AI/Dive_into_Deep_Learning/#googlenet","title":"GoogLeNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#resnet","title":"ResNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#densenet","title":"DenseNet","text":""},{"location":"AI/Dive_into_Deep_Learning/#_6","title":"\u5faa\u73af\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#_7","title":"\u73b0\u4ee3\u5faa\u73af\u795e\u7ecf\u7f51\u7edc","text":""},{"location":"AI/Dive_into_Deep_Learning/#gru","title":"GRU","text":""},{"location":"AI/Dive_into_Deep_Learning/#lstm","title":"LSTM","text":""},{"location":"AI/Dive_into_Deep_Learning/#seq2seq","title":"seq2seq","text":""},{"location":"AI/Dive_into_Deep_Learning/#_8","title":"\u6ce8\u610f\u529b\u673a\u5236","text":""},{"location":"AI/Dive_into_Deep_Learning/#nadaraya-watson","title":"Nadaraya-Watson","text":""},{"location":"AI/Dive_into_Deep_Learning/#bahdanau","title":"Bahdanau","text":""},{"location":"AI/Dive_into_Deep_Learning/#multi-headed-attention","title":"Multi-headed attention","text":""},{"location":"AI/Dive_into_Deep_Learning/#transformer","title":"Transformer","text":""},{"location":"AI/Dive_into_Deep_Learning/#_9","title":"\u4f18\u5316\u7b97\u6cd5","text":""},{"location":"AI/Dive_into_Deep_Learning/#adagrad","title":"AdaGrad","text":""},{"location":"AI/Dive_into_Deep_Learning/#rmsprop","title":"RMSProp","text":""},{"location":"AI/Dive_into_Deep_Learning/#adadelta","title":"Adadelta","text":""},{"location":"AI/Dive_into_Deep_Learning/#adam","title":"Adam","text":""},{"location":"AI/Dive_into_Deep_Learning/#_10","title":"\u8ba1\u7b97\u6027\u80fd","text":""},{"location":"AI/Dive_into_Deep_Learning/#_11","title":"\u8ba1\u7b97\u673a\u89c6\u89c9","text":""},{"location":"AI/Dive_into_Deep_Learning/#ssd","title":"SSD","text":""},{"location":"AI/Dive_into_Deep_Learning/#r-cnn","title":"R-CNN","text":""},{"location":"AI/Dive_into_Deep_Learning/#_12","title":"\u81ea\u7136\u8bed\u8a00\u5904\u7406:\u9884\u8bad\u7ec3","text":""},{"location":"AI/Dive_into_Deep_Learning/#word2vec","title":"word2vec","text":""},{"location":"AI/Dive_into_Deep_Learning/#glove","title":"GloVe","text":""},{"location":"AI/Dive_into_Deep_Learning/#bert","title":"BERT","text":""},{"location":"AI/Dive_into_Deep_Learning/#_13","title":"\u81ea\u7136\u8bed\u8a00\u5904\u7406:\u5e94\u7528","text":""},{"location":"AI/SLAM14/","title":"\u89c6\u89c9SLAM\u5341\u56db\u8bb2","text":""},{"location":"AI/SLAM14/#slam","title":"\u89c6\u89c9SLAM\u5341\u56db\u8bb2","text":"\u7ea6 14110 \u4e2a\u5b57 72 \u884c\u4ee3\u7801 20 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 71 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/SLAM14/#1","title":"1 \u9884\u5907\u77e5\u8bc6","text":""},{"location":"AI/SLAM14/#11","title":"1.1 \u672c\u4e66\u8bb2\u4ec0\u4e48","text":"simultaneous localization and mapping
GitHub - gaoxiang12/slambook2: edition 2 of the slambook
"},{"location":"AI/SLAM14/#123","title":"1.2.3 \u9762\u5411\u7684\u8bfb\u8005","text":"apt
\u6765\u5b89\u88c5\u8f6f\u4ef6\u3002\u57fa\u672c\u547d\u4ee4\u4e3a sudo apt install [package-name]
\u3002/usr/
\u76ee\u5f55\u4e0b\uff0c\u4f46\u5177\u4f53\u7684\u6587\u4ef6\u53ef\u80fd\u5206\u5e03\u5728\u591a\u4e2a\u5b50\u76ee\u5f55\u4e2d\u3002apt search
\u547d\u4ee4\u6765\u641c\u7d22\u3002\u4f8b\u5982\uff0csudo apt search eigen
\u53ef\u4ee5\u5e2e\u52a9\u627e\u5230\u6240\u6709\u5305\u542b \"eigen\" \u7684\u8f6f\u4ef6\u5305\u3002cmake_minimum_required( VERSION 2.8)\n\nproject(HelloSLAM)\n\nadd_executable(helloSLAM helloSLAM.cpp)\n
\u5bf9\u4e2d\u95f4\u6587\u4ef6\u7684\u5904\u7406:
Text Onlymkdir build\ncd build\ncmake ..\nmake\n
"},{"location":"AI/SLAM14/#244","title":"2.4.4 \u4f7f\u7528\u5e93","text":"Text Onlyadd_library(hello libHelloSLAM.cpp)\n
add_library(hello_shared SHARED libHelloSLAM.cpp)\n
#ifndef LIBHELLOSLAM_H_\n#define LIBHELLOSLAM_H_\n\nvoid printHello()\n\n#endif\n
#include \"libHelloSLAM.h\"\n\nint main(int argc, char **argv) {\n printHello();\n return 0; \n}\n
add_executable(useHello useHello.cpp)\ntarget_link_libraries(useHello hello_shared)\n
"},{"location":"AI/SLAM14/#245-ide","title":"2.4.5 \u4f7f\u7528 IDE","text":"#include <iostream>\nusing namespace std;\n\n#include <ctime>\n\n#include <eigen3>\nusing namespace Eigen;\n\n#define MATRIX_SIZE 50\n\nint main(int argc, char **argv) {\n Matrix<float, 2, 3> matrix_23;\n// \u5982\u4e0b\u90fd\u662f\u4e09\u7ef4\u5411\u91cf\n Vector3d v_3d;\n Matrix<float, 3, 1> vd_3d;\n// \u5982\u4e0b\u662f3*3\u77e9\u9635\n Matrix3d matrix_33 = Matrix3d::Zero();\n// \u4e24\u4e2a\u52a8\u6001\u5206\u914d\n Matrix<double, Dynamic, Dynamic> matrix_dynamic;\n MatrixXd matrix_x;\n\n matrix_23 << 1, 2, 3, 4, 5, 6;\n cout<< \"matrix 2*3 from 1 to 6: \\n\" << matrix_23 << endl;\n\n cout << \"print matrix 2*3:\" << endl;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 3; j+) cout << matrix_23(i, j) << \"\\t\";\n cout << endl;\n }\n\n v_3d << 3, 2, 1;\n vd_3d << 4, 5, 6;\n\n Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;\n cout << \"[1, 2, 3; 4, 5, 6] * [3, 2, 1] =\" << result.transpose() << endl;\n\n matrix_22 = Matrix3d::Random();\n\n // \u4e00\u4e9b\u77e9\u9635\u7684\u64cd\u4f5c:\n // transpose()\n // sum()\n // trace()\n // inverse()\n // determinant()\n\n SelfAdjointEigenSolver<Matrix3d> eigen_solver(matrix_33.transpose() * matrix_33);\n cout << eigen_solver.eigenvalues() << endl;\n cout << eigen_solver.eigenvectors() << endl;\n\n // solve the equation\n Matrix<double, MATRIX_SIZE, MATRIX_SIZE> matrix_NN = MatrixXd::Random(MATRIX_SIZE, MATRIX_SIZE);\n matrix_NN = matrix_NN * matrix_NN.transpose()\n Matrix<double, MATRIX_SIZE, 1> v_Nd = MatrixXd::random(MATRIX_SIZE, 1);\n\n // \u7b2c\u4e00\u79cd:\u76f4\u63a5\u6c42\u9006\n Matrix<double, MATRIX_SIZE, 1> x = matrix_NN.inverse() * v_Nd;\n\n // \u7b2c\u4e8c\u79cd:\u77e9\u9635\u5206\u89e3\n x = matrix_NN.colPivHouseholderQr().solve(v_Nd);\n\n}\n
thus:
\\[ \\theta=\\arccos\\frac{\\mathrm{tr}(R)-1}{2}. \\] \\[ Rn=n. \\]\u5141\u8bb8\u7f29\u653e\uff0c\u76f8\u4f3c\u53d8\u6362\u7fa4: Sim (3) 2. \u4eff\u5c04\u53d8\u6362:
\\[ T_A=\\begin{bmatrix}A&t\\\\\\mathbf{0}^\\mathrm{T}&1\\end{bmatrix}. \\]\u53ea\u4fdd\u8bc1\u5e73\u884c\u5173\u7cfb 3. \u5c04\u5f71\u53d8\u6362
\\[ T_P=\\begin{bmatrix}A&t\\\\\\\\a^\\mathrm{T}&v\\end{bmatrix}. \\]\u603b\u7ed3\u4e00\u4e0b:
\\[ \\begin{array}{c|c|c|c}\\hline\\text{\u53d8\u6362\u540d\u79f0}&\\text{\u77e9\u9635\u5f62\u5f0f}&\\text{\u81ea\u7531\u5ea6}&\\text{\u4e0d\u53d8\u6027\u8d28}\\\\\\hline\\text{\u6b27\u6c0f\u53d8\u6362}&\\begin{bmatrix}R&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&6&\\text{\u957f\u5ea6\u3001\u5939\u89d2\u3001\u4f53\u79ef}\\\\\\text{\u76f8\u4f3c\u53d8\u6362}&\\begin{bmatrix}sR&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&7&\\text{\u4f53\u79ef\u6bd4}\\\\\\text{\u4eff\u5c04\u53d8\u6362}&\\begin{bmatrix}A&t\\\\0^\\mathrm{T}&1\\end{bmatrix}&12&\\text{\u5e73\u884c\u6027\u3001\u4f53\u79ef\u6bd4}\\\\\\text{\u5c04\u5f71\u53d8\u6362}&\\begin{bmatrix}A&t\\\\a^\\mathrm{T}&v\\end{bmatrix}&15&\\text{\u63a5\u89e6\u5e73\u9762\u7684\u76f8\u4ea4\u548c\u76f8\u5207}\\\\\\hline\\end{array} \\]"},{"location":"AI/SLAM14/#36-eigen","title":"3.6 \u5b9e\u8df5: Eigen \u51e0\u4f55\u6a21\u5757","text":""},{"location":"AI/SLAM14/#361-eigen","title":"3.6.1 Eigen \u51e0\u4f55\u6a21\u5757\u7684\u6570\u636e\u6f14\u793a","text":"\u518d\u8bf4\u5427\u3002
"},{"location":"AI/SLAM14/#362","title":"3.6.2 \u5b9e\u9645\u7684\u5750\u6807\u53d8\u6362\u4f8b\u5b50","text":"TODO
"},{"location":"AI/SLAM14/#37","title":"3.7 \u53ef\u89c6\u5316\u6f14\u793a","text":""},{"location":"AI/SLAM14/#371","title":"3.7.1 \u663e\u793a\u8fd0\u52a8\u8f68\u8ff9","text":"TODO
"},{"location":"AI/SLAM14/#4","title":"4 \u674e\u7fa4\u548c\u674e\u4ee3\u6570","text":"\u4e8e\u662f\u6c42\u5bfc->\u4e00\u4e2a\u7b97\u7b26 \\(\\displaystyle \\phi\\) \uff0c\u88ab\u79f0\u4e3a \\(\\displaystyle \\boldsymbol{SO}(3)\\) \u539f\u70b9\u9644\u8fd1\u7684\u6b63\u5207\u7a7a\u95f4\uff08Tangent Space\uff09 \u8bbe\u5728 \\(\\displaystyle t_{0}\\) \u9644\u8fd1\uff0c\\(\\displaystyle \\phi\\) \u4fdd\u6301\u5e38\u6570 \\(\\displaystyle \\phi(t_{0})=\\phi_{0}\\)\uff0c
\\[ \\dot{\\boldsymbol{R}}(t)=\\boldsymbol{\\phi}(t_0)^\\wedge\\boldsymbol{R}(t)=\\boldsymbol{\\phi}_0^\\wedge\\boldsymbol{R}(t). \\]\u518d\u6709 \\(\\displaystyle \\boldsymbol{R}(0) = \\boldsymbol{I}\\)\uff0c\u89e3\u7684:
\\[ \\boldsymbol{R}(t)=\\exp\\left(\\boldsymbol{\\phi}_{0}^{\\wedge}t\\right). \\]\u674e\u4ee3\u6570\u7531\u4e00\u4e2a\u96c6\u5408 \\(\\displaystyle \\mathbb{V}\\)\u3001\u4e00\u4e2a\u6570\u57df \\(\\displaystyle \\mathbb{F}\\) \u548c\u4e00\u4e2a\u4e8c\u5143\u8fd0\u7b97 \\(\\displaystyle [,]\\) \u7ec4\u6210\u3002\u5982\u679c\u6ee1\u8db3\u4ee5\u4e0b\u51e0\u6761\u6027\u8d28\uff0c\u5219\u79f0 ( \\(\\displaystyle \\mathbb{V},\\mathbb{F},[,]\\)) \u4e3a\u4e00\u4e2a\u674e\u4ee3\u6570\uff0c\u8bb0\u4f5c \\(\\displaystyle \\mathfrak{g}\\)\u3002
\\(\\displaystyle \\boldsymbol{\\Phi}=\\boldsymbol{\\phi}^{\\wedge}=\\begin{bmatrix}0&-\\phi_3&\\phi_2\\\\\\\\\\phi_3&0&-\\phi_1\\\\\\\\-\\phi_2&\\phi_1&0\\end{bmatrix}\\in\\mathbb{R}^{3\\times3}.\\) \u6240\u4ee5\u4e24\u4e2a\u5411\u91cf \\(\\displaystyle \\phi_{1},\\phi_{2}\\) \u7684\u674e\u62ec\u53f7\u4e3a:
\\[ [\\phi_1,\\phi_2]=(\\boldsymbol{\\Phi}_1\\boldsymbol{\\Phi}_2-\\boldsymbol{\\Phi}_2\\boldsymbol{\\Phi}_1)^\\vee. \\] \\[ \\mathfrak{so}(3)=\\left\\{\\phi\\in\\mathbb{R}^3,\\boldsymbol{\\Phi}=\\phi^\\wedge\\in\\mathbb{R}^{3\\times3}\\right\\}. \\] \\[ R=\\exp(\\phi^{\\wedge}). \\]"},{"location":"AI/SLAM14/#415-displaystyle-mathfrakse3","title":"4.1.5 \u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{se}(3)\\)","text":"\\[ \\mathfrak{se}(3)=\\left\\{\\boldsymbol{\\xi}=\\begin{bmatrix}\\boldsymbol{\\rho}\\\\\\boldsymbol{\\phi}\\end{bmatrix}\\in\\mathbb{R}^6,\\boldsymbol{\\rho}\\in\\mathbb{R}^3,\\boldsymbol{\\phi}\\in\\mathfrak{so}(3),\\boldsymbol{\\xi}^\\wedge=\\begin{bmatrix}\\boldsymbol{\\phi}^\\wedge&\\boldsymbol{\\rho}\\\\\\boldsymbol{0}^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\]\u524d\u4e09\u7ef4\u4e3a\u5e73\u79fb\uff0c\u540e\u4e09\u7ef4\u4e3a\u65cb\u8f6c\uff08\u5b9e\u8d28\u4e0a\u662f \\(\\displaystyle \\mathfrak{so}(3)\\) \u5143\u7d20\uff09
\\[ \\xi^\\wedge=\\begin{bmatrix}\\phi^\\wedge&\\rho\\\\0^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}. \\]\u540c\u6837\u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{se}(3)\\) \u4e5f\u6709\u7c7b\u4f3c\u4e8e \\(\\displaystyle \\mathfrak{so}(3)\\) \u7684\u674e\u62ec\u53f7:
\\[ [\\xi_1,\\xi_2]=\\left(\\xi_1^\\wedge\\xi_2^\\wedge-\\xi_2^\\wedge\\xi_1^\\wedge\\right)^\\vee. \\]"},{"location":"AI/SLAM14/#42","title":"4.2 \u6307\u6570\u4e0e\u5bf9\u6570\u6620\u5c04","text":""},{"location":"AI/SLAM14/#421-so3","title":"4.2.1 SO(3)\u4e0a\u7684\u6307\u6570\u6620\u5c04","text":"\u548c
\\[ a^{\\wedge}a^{\\wedge}a^{\\wedge}=a^{\\wedge}(aa^{\\mathrm{T}}-I)=-a^{\\wedge}. \\]\u4e8e\u662f\u6211\u4eec\u53ef\u4ee5\u5316\u7b80:
\\[ \\begin{aligned} \\exp\\left(\\phi^\\wedge\\right)& =\\exp\\left(\\theta\\boldsymbol{a}^\\wedge\\right)=\\sum_{n=0}^\\infty\\frac1{n!}\\left(\\theta\\boldsymbol{a}^\\wedge\\right)^n \\\\ &=I+\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{2!}\\theta^{2}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\frac{1}{3!}\\theta^{3}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\frac{1}{4!}\\theta^{4}(\\boldsymbol{a}^{\\wedge})^{4}+\\cdots \\\\ &=\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}+\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{2!}\\theta^{2}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge}-\\frac{1}{3!}\\theta^{3}\\boldsymbol{a}^{\\wedge}-\\frac{1}{4!}\\theta^{4}(\\boldsymbol{a}^{\\wedge})^{2}+\\cdots \\\\ &=\\boldsymbol{a}\\boldsymbol{a}^{\\mathsf{T}}+\\underbrace{\\left(\\theta-\\frac{1}{3!}\\theta^{3}+\\frac{1}{5!}\\theta^{5}-\\cdots\\right)}_{\\sin\\theta}\\boldsymbol{a}^{\\wedge}-\\underbrace{\\left(1-\\frac{1}{2!}\\theta^{2}+\\frac{1}{4!}\\theta^{4}-\\cdots\\right)}_{\\cos\\theta}\\boldsymbol{a}^{\\wedge}\\boldsymbol{a}^{\\wedge} \\\\ &=a^\\wedge a^\\wedge+I+\\sin\\theta a^\\wedge-\\cos\\theta a^\\wedge a^\\wedge \\\\ &=(1-\\cos\\theta)\\boldsymbol{a}^\\wedge\\boldsymbol{a}^\\wedge+\\boldsymbol{I}+\\sin\\theta\\boldsymbol{a}^\\wedge \\\\ &=\\cos\\theta\\boldsymbol{I}+(1-\\cos\\theta)\\boldsymbol{aa}^\\mathrm{T}+\\sin\\theta\\boldsymbol{a}^\\mathrm{\\wedge}. \\end{aligned} \\]\u6700\u540e\u5f97\u5230:
\\[ \\exp(\\theta\\boldsymbol{a}^\\wedge)=\\cos\\theta\\boldsymbol{I}+(1-\\cos\\theta)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\sin\\theta\\boldsymbol{a}^\\wedge. \\]\u6240\u4ee5 \\(\\displaystyle \\mathfrak{so}(3)\\) \u5c31\u662f\u65cb\u91cf\u5411\u91cf\u7ec4\u6210\u7684\u7a7a\u95f4\uff0c\u800c\u6307\u6570\u6620\u5c04\u5373\u7f57\u5fb7\u91cc\u683c\u65af\u516c\u5f0f\u3002
\u540c\u6837\u7684\u63a8\u5bfc\u65b9\u5f0f:
\\[ \\begin{aligned} \\exp\\left(\\xi^{\\wedge}\\right)& =\\begin{bmatrix}\\sum_{n=0}^{\\infty}\\frac{1}{n!}(\\phi^{\\wedge})^{n}&\\sum_{n=0}^{\\infty}\\frac{1}{(n+1)!}(\\phi^{\\wedge})^{n}\\rho\\\\\\\\\\mathbf{0}^{\\mathrm{T}}&1\\end{bmatrix} \\\\ &\\stackrel{\\Delta}{=}\\begin{bmatrix}R&J\\rho\\\\\\\\0^\\mathrm{T}&1\\end{bmatrix}=T. \\end{aligned} \\] \\[ \\begin{aligned} \\sum_{n=0}^{\\infty}\\frac{1}{(n+1)!}(\\phi^{\\wedge})^{n}& =\\boldsymbol{I}+\\frac{1}{2!}\\theta\\boldsymbol{a}^{\\wedge}+\\frac{1}{3!}\\theta^{2}{(\\boldsymbol{a}^{\\wedge})}^{2}+\\frac{1}{4!}\\theta^{3}{(\\boldsymbol{a}^{\\wedge})}^{3}+\\frac{1}{5!}\\theta^{4}{(\\boldsymbol{a}^{\\wedge})}^{4}\\cdots \\\\ &=\\frac{1}{\\theta}\\left(\\frac{1}{2!}\\theta^{2}-\\frac{1}{4!}\\theta^{4}+\\cdots\\right)(\\boldsymbol{a}^{\\wedge})+\\frac{1}{\\theta}\\left(\\frac{1}{3!}\\theta^{3}-\\frac{1}{5}\\theta^{5}+\\cdots\\right)(\\boldsymbol{a}^{\\wedge})^{2}+\\boldsymbol{I} \\\\ &=\\frac1\\theta\\left(1-\\cos\\theta\\right)\\left(\\boldsymbol{a}^{\\wedge}\\right)+\\frac{\\theta-\\sin\\theta}\\theta\\left(\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\boldsymbol{I}\\right)+\\boldsymbol{I} \\\\ &=\\frac{\\sin\\theta}\\theta\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}\\theta\\right)\\boldsymbol{aa}^\\mathrm{T}+\\frac{1-\\cos\\theta}\\theta\\boldsymbol{a}^\\mathrm{\\wedge}\\overset{\\mathrm{def}}{\\operatorname*{=}}\\boldsymbol{J}. \\end{aligned} \\] \\[ \\boldsymbol{J}=\\frac{\\sin\\theta}{\\theta}\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}{\\theta}\\right)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\frac{1-\\cos\\theta}{\\theta}\\boldsymbol{a}^\\mathrm{\\wedge}. \\]4.28 \u6ca1\u770b\u61c2
"},{"location":"AI/SLAM14/#43","title":"4.3 \u674e\u4ee3\u6570\u6c42\u5bfc\u4e0e\u6270\u52a8\u6a21\u578b","text":""},{"location":"AI/SLAM14/#431-bch","title":"4.3.1 BCH \u516c\u5f0f\u4e0e\u8fd1\u4f3c\u5f62\u5f0f","text":"\u63a2\u7a76\u5982\u4e0b\u5f0f\u5b50\u662f\u5426\u6210\u7acb:
\\[ \\ln\\left(\\exp\\left(A\\right)\\exp\\left(B\\right)\\right)=A+B ? \\]\u4f46\u5b83\u5e76\u4e0d\u6210\u7acb\u3002\u4e24\u4e2a\u674e\u4ee3\u6570\u6307\u6570\u6620\u5c04\u4e58\u79ef\u7684\u5b8c\u6574\u5f62\u5f0f\uff0c\u7531 Baker-Campbell-Hausdorff \u7ed9\u51fa:
\\[ \\ln\\left(\\exp\\left(A\\right)\\exp\\left(B\\right)\\right)=A+B+\\frac{1}{2}\\left[A,B\\right]+\\frac{1}{12}\\left[A,\\left[A,B\\right]\\right]-\\frac{1}{12}\\left[B,\\left[A,B\\right]\\right]+\\cdots \\]\u7279\u522b\u7684\uff0c\u5f53 \\(\\displaystyle \\phi_{1}\\) \u6216 \\(\\displaystyle \\phi_{2}\\) \u4e3a\u5c0f\u91cf\u65f6\uff0c\u5c0f\u91cf\u4e8c\u6b21\u4ee5\u4e0a\u7684\u9879\u90fd\u53ef\u4ee5\u88ab\u5ffd\u7565\uff0c\u6b64\u65f6\u7684\u7ebf\u6027\u8fd1\u4f3c\u8868\u8fbe:
\\[ \\ln\\left(\\exp\\left(\\phi_1^\\wedge\\right)\\exp\\left(\\phi_2^\\wedge\\right)\\right)^\\vee\\approx\\begin{cases}J_l(\\phi_2)^{-1}\\phi_1+\\phi_2&\\text{\u5f53}\\phi_1\\text{\u4e3a\u5c0f\u91cf},\\\\J_r(\\phi_1)^{-1}\\phi_2+\\phi_1&\\text{\u5f53}\\phi_2\\text{\u4e3a\u5c0f\u91cf}.\\end{cases} \\] \\[ \\boldsymbol{J}_{l}=\\frac{\\sin\\theta}{\\theta}\\boldsymbol{I}+\\left(1-\\frac{\\sin\\theta}{\\theta}\\right)\\boldsymbol{a}\\boldsymbol{a}^\\mathrm{T}+\\frac{1-\\cos\\theta}{\\theta}\\boldsymbol{a}^\\mathrm{\\wedge}. \\] \\[ \\boldsymbol{J}_{\\ell}^{-1}=\\frac{\\theta}{2}\\cot\\frac{\\theta}{2}\\boldsymbol{I}+\\left(1-\\frac{\\theta}{2}\\cot\\frac{\\theta}{2}\\right)\\boldsymbol{a}\\boldsymbol{a}^{\\mathrm{T}}-\\frac{\\theta}{2}\\boldsymbol{a}^{\\wedge}. \\] \\[ J_{r}(\\phi)=J_{l}(-\\phi). \\]\u4e8e\u662f\u6211\u4eec\u5c31\u53ef\u4ee5\u8c08\u8bba\u674e\u7fa4\u4e58\u6cd5\u4e0e\u674e\u4ee3\u6570\u52a0\u6cd5\u7684\u5173\u7cfb\u4e86\u3002 \\(\\displaystyle \\boldsymbol{R}\\) \u5bf9\u5e94 \\(\\displaystyle \\phi\\)\uff0c\u6211\u4eec\u7ed9\u5b83\u5de6\u4e58\u4e00\u4e2a\u5fae\u5c0f\u65cb\u8f6c\uff0c\u8bb0\u4f5c \\(\\displaystyle \\Delta \\boldsymbol{R}\\)
\\[ \\exp\\left(\\Delta\\phi^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)=\\exp\\left(\\left(\\phi+J_{l}^{-1}\\left(\\phi\\right)\\Delta\\phi\\right)^{\\wedge}\\right). \\] \\[ \\exp\\left(\\left(\\phi+\\Delta\\phi\\right)^{\\wedge}\\right)=\\exp\\left(\\left(J_{l}\\Delta\\phi\\right)^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)=\\exp\\left(\\phi^{\\wedge}\\right)\\exp\\left(\\left(J_{r}\\Delta\\phi\\right)^{\\wedge}\\right). \\]\u5bf9\u4e8e SE (3) \u6211\u4eec\u4e5f\u6709:
\\[ \\exp\\left(\\Delta\\xi^{\\wedge}\\right)\\exp\\left(\\xi^{\\wedge}\\right)\\approx\\exp\\left(\\left(\\mathcal{J}_{l}^{-1}\\Delta\\xi+\\xi\\right)^{\\wedge}\\right) \\] \\[ exp\\left(\\xi^{\\wedge}\\right)\\exp\\left(\\Delta\\xi^{\\wedge}\\right)\\approx\\exp\\left(\\left(\\mathcal{J}_{r}^{-1}\\Delta\\xi+\\xi\\right)^{\\wedge}\\right). \\]\u552f\u4e00\u4e0d\u540c\u7684\u662f\u8fd9\u91cc\u7684 \\(\\displaystyle J_{l}\\) \u6bd4\u8f83\u590d\u6742\u3002
"},{"location":"AI/SLAM14/#432-so-3","title":"4.3.2 SO (3) \u4e0a\u7684\u674e\u4ee3\u6570\u6c42\u5bfc","text":"\\[ z=T\\boldsymbol{p}+\\boldsymbol{w}. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{w}\\) \u662f\u968f\u673a\u566a\u58f0\u3002
\\[ e=z-Tp. \\]\u5047\u8bbe\u4e00\u5171\u6709 N \u4e2a\u8fd9\u6837\u7684\u8def\u6807\u70b9\u548c\u89c2\u6d4b:
\\[ \\min_{\\boldsymbol{T}}J(\\boldsymbol{T})=\\sum_{i=1}^N\\left\\|\\boldsymbol{z}_i-\\boldsymbol{T}\\boldsymbol{p}_i\\right\\|_2^2. \\]most importantly\uff0c\u6211\u4eec\u4f1a\u6784\u5efa\u4e0e\u4f4d\u59ff\u6709\u5173\u7684\u51fd\u6570\uff0c\u5e76\u8ba8\u8bba\u8be5\u51fd\u6570\u5173\u4e8e\u4f4d\u59ff\u7684\u5bfc\u6570\uff0c\u4ee5\u8c03\u6574\u5f53\u524d\u7684\u4f30\u8ba1\u503c\u3002 \u4f7f\u7528\u674e\u4ee3\u6570\u89e3\u51b3\u6c42\u5bfc\u95ee\u9898\u7684\u601d\u8def\u5206\u4e3a\u4e24\u79cd:
\u8981\u8ba1\u7b97 \\(\\displaystyle \\frac{\\partial\\left(Rp\\right)}{\\partial R}\\), \u7531\u4e8eSO\uff083\uff09\u6ca1\u6709\u52a0\u6cd5\uff0c\u6211\u4eec\u8f6c\u800c\u8ba1\u7b97: \\(\\displaystyle \\frac{\\partial\\left(\\exp\\left(\\phi^{\\wedge}\\right)\\boldsymbol{p}\\right)}{\\partial\\boldsymbol{\\phi}}.\\)
\\[ \\begin{aligned} \\frac{\\partial\\left(\\exp\\left(\\phi^{\\wedge}\\right)\\boldsymbol{p}\\right)}{\\partial\\phi}& =\\lim_{\\delta\\boldsymbol{\\phi}\\to0}\\frac{\\exp\\left(\\left(\\boldsymbol{\\phi}+\\delta\\boldsymbol{\\phi}\\right)^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\phi}} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\exp\\left(\\left(\\boldsymbol{J}_i\\delta\\boldsymbol{\\phi}\\right)^\\wedge\\right)\\exp\\left(\\boldsymbol{\\phi}^\\wedge\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^\\wedge\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\phi}} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\left(\\boldsymbol{I}+\\left(\\boldsymbol{J}_{l}\\delta\\boldsymbol{\\phi}\\right)^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\phi} \\\\ &=\\lim_{\\delta\\phi\\to0}\\frac{\\left(\\boldsymbol{J}_{l}\\delta\\phi\\right)^{\\wedge}\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\phi} \\\\ &=\\lim_{\\delta\\boldsymbol{\\phi}\\to0}\\frac{-(\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p})^{\\wedge}\\boldsymbol{J}_{l}\\delta\\boldsymbol{\\phi}}{\\delta\\boldsymbol{\\phi}}=-(\\boldsymbol{R}\\boldsymbol{p})^{\\wedge}\\boldsymbol{J}_{l}. \\end{aligned} \\]BCH \u7ebf\u6027\u8fd1\u4f3c+\u6cf0\u52d2\u5c55\u5f00\u53d6\u7ebf\u6027\u9879:
\\[ \\frac{\\partial\\left(\\boldsymbol{Rp}\\right)}{\\partial\\boldsymbol{\\phi}}=\\left(-\\boldsymbol{Rp}\\right)^{\\wedge}\\boldsymbol{J}_{l}. \\]\u4f46\u662f\u8fd9\u91cc\u4ecd\u7136\u6709 \\(\\displaystyle \\boldsymbol{J}_{l}\\)
"},{"location":"AI/SLAM14/#441","title":"4.4.1 \u6270\u52a8\u6a21\u578b\uff08\u5de6\u4e58\uff09","text":"\\(\\displaystyle \\varphi\\) \u5bf9\u5e94\u5de6\u6270\u52a8 \\(\\displaystyle \\Delta \\boldsymbol{R}\\)
\\[ \\begin{aligned} \\frac{\\partial\\left(Rp\\right)}{\\partial\\varphi}& =\\lim_{\\varphi\\to0}\\frac{\\exp\\left(\\varphi^{\\wedge}\\right)\\exp\\left(\\phi^{\\wedge}\\right)p-\\exp\\left(\\phi^{\\wedge}\\right)p}{\\varphi} \\\\ &=\\lim_{\\varphi\\to0}\\frac{(\\boldsymbol{I}+\\boldsymbol{\\varphi}^{\\wedge})\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\phi}^{\\wedge}\\right)\\boldsymbol{p}}{\\varphi} \\\\ &=\\lim_{\\varphi\\to0}\\frac{\\varphi^\\wedge Rp}\\varphi=\\lim_{\\varphi\\to0}\\frac{-\\left(Rp\\right)^\\wedge\\varphi}\\varphi=-\\left(Rp\\right)^\\wedge. \\end{aligned} \\]"},{"location":"AI/SLAM14/#442-se-3","title":"4.4.2 SE (3) \u4e0a\u7684\u674e\u4ee3\u6570\u6c42\u5bfc","text":"\\[ \\begin{aligned} \\frac{\\partial\\left(\\boldsymbol{T}\\boldsymbol{p}\\right)}{\\partial\\delta\\boldsymbol{\\xi}}&=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\boldsymbol{0}}\\frac{\\exp\\left(\\delta\\boldsymbol{\\xi}^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\xi} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\mathbf{0}}\\frac{\\left(\\boldsymbol{I}+\\delta\\boldsymbol{\\xi}^{\\wedge}\\right)\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}-\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to0}\\frac{\\delta\\boldsymbol{\\xi}^{\\wedge}\\exp\\left(\\boldsymbol{\\xi}^{\\wedge}\\right)\\boldsymbol{p}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\mathbf{0}}\\frac{\\begin{bmatrix}\\delta\\boldsymbol{\\phi}^\\wedge&\\delta\\boldsymbol{\\rho}\\\\\\\\\\mathbf{0}^\\mathrm{T}&0\\end{bmatrix}\\begin{bmatrix}\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}\\\\\\\\1\\end{bmatrix}}{\\delta\\boldsymbol{\\xi}} \\\\ &=\\lim_{\\delta\\boldsymbol{\\xi}\\to\\boldsymbol{0}}\\frac{\\begin{bmatrix}\\delta\\boldsymbol{\\phi}^{\\wedge}\\left(\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}\\right)+\\delta\\boldsymbol{\\rho}\\\\\\boldsymbol{0}^{\\mathrm{T}}\\end{bmatrix}}{[\\delta\\boldsymbol{\\rho},\\delta\\boldsymbol{\\phi}]^{\\mathrm{T}}}=\\begin{bmatrix}\\boldsymbol{I}&-(\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t})^{\\wedge}\\\\\\boldsymbol{0}^{\\mathrm{T}}&\\boldsymbol{0}^{\\mathrm{T}}\\end{bmatrix}\\stackrel{\\mathrm{def}}{=}(\\boldsymbol{T}\\boldsymbol{p})^{\\odot}. \\end{aligned} \\] \\[ \\frac{\\mathrm{d}\\begin{bmatrix}a\\\\b\\end{bmatrix}}{\\mathrm{d}\\begin{bmatrix}x\\\\y\\end{bmatrix}}=\\left(\\frac{\\mathrm{d}[a,b]^\\mathrm{T}}{\\mathrm{d}\\begin{bmatrix}x\\\\y\\end{bmatrix}}\\right)^\\mathrm{T}=\\begin{bmatrix}\\frac{\\mathrm{d}a}{\\mathrm{d}x}&\\frac{\\mathrm{d}b}{\\mathrm{d}x}\\\\\\frac{\\mathrm{d}a}{\\mathrm{d}y}&\\frac{\\mathrm{d}b}{\\mathrm{d}y}\\end{bmatrix}^\\mathrm{T}=\\begin{bmatrix}\\frac{\\mathrm{d}a}{\\mathrm{d}x}&\\frac{\\mathrm{d}a}{\\mathrm{d}y}\\\\\\frac{\\mathrm{d}b}{\\mathrm{d}x}&\\frac{\\mathrm{d}b}{\\mathrm{d}y}\\end{bmatrix} \\]"},{"location":"AI/SLAM14/#45-sophus","title":"4.5 \u5b9e\u8df5:Sophus","text":""},{"location":"AI/SLAM14/#451-sophus","title":"4.5.1 Sophus \u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5","text":""},{"location":"AI/SLAM14/#452","title":"4.5.2 \u4f8b\u5b50: \u8bc4\u4f30\u8f68\u8ff9\u7684\u8bef\u5dee","text":"\u5373\u5747\u65b9\u6839\u8bef\u5dee\uff08Root-Mean-Squared Error, RMSE\uff09
\u4ee3\u7801\u8ba1\u7b97:
Text OnlyTODO\n
"},{"location":"AI/SLAM14/#46","title":"4.6 \u76f8\u4f3c\u53d8\u6362\u4e0e\u674e\u4ee3\u6570","text":"\u5728\u8fd9\u91cc\u6211\u4eec\u8ba8\u8bba Sim (3) \u548c\u5bf9\u5e94\u7684\u674e\u4ee3\u6570 \\(\\displaystyle \\mathfrak{sim}(3)\\)\u3002 \u5bf9\u4e8e\u4f4d\u4e8e\u7a7a\u95f4\u7684\u70b9 \\(\\displaystyle \\boldsymbol{p}\\)\uff0c\u5728\u76f8\u673a\u5750\u6807\u7cfb\u4e0b\u8981\u7ecf\u8fc7\u4e00\u4e2a\u76f8\u4f3c\u53d8\u6362\uff0c\u800c\u975e\u6b27\u6c0f\u53d8\u6362:
\\[ \\boldsymbol{p}'=\\begin{bmatrix}s\\boldsymbol{R}&\\boldsymbol{t}\\\\\\boldsymbol{0}^\\mathrm{T}&1\\end{bmatrix}\\boldsymbol{p}=s\\boldsymbol{R}\\boldsymbol{p}+\\boldsymbol{t}. \\] \\[ \\mathrm{Sim}(3)=\\left\\{S=\\begin{bmatrix}sR&t\\\\\\\\\\mathbf{0}^\\mathrm{T}&1\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\] \\[ \\sin(3)=\\left\\{\\zeta|\\zeta=\\begin{bmatrix}\\rho\\\\\\\\\\phi\\\\\\\\\\sigma\\end{bmatrix}\\in\\mathbb{R}^7,\\zeta^\\wedge=\\begin{bmatrix}\\sigma\\boldsymbol{I}+\\phi^\\wedge&\\rho\\\\\\\\\\mathbf{0}^\\mathrm{T}&0\\end{bmatrix}\\in\\mathbb{R}^{4\\times4}\\right\\}. \\] \\[ \\exp\\left(\\zeta^{\\wedge}\\right)=\\begin{bmatrix}\\mathrm{e}^{\\sigma}\\exp\\left(\\phi^{\\wedge}\\right)&J_{s}\\rho\\\\0^{\\mathrm{T}}&1\\end{bmatrix}. \\]\u5176\u4e2d\uff0c\\(\\displaystyle \\boldsymbol{J}_{S}\\) \u7684\u5f62\u5f0f\u662f:
\\[ \\begin{aligned} \\text{J}& =\\frac{\\mathrm{e}^{\\sigma}-1}{\\sigma}I+\\frac{\\sigma\\mathrm{e}^{\\sigma}\\sin\\theta+\\left(1-\\mathrm{e}^{\\sigma}\\cos\\theta\\right)\\theta}{\\sigma^{2}+\\theta^{2}}\\boldsymbol{a}^{\\wedge} \\\\ &+\\left(\\frac{\\mathrm{e}^\\sigma-1}{\\sigma}-\\frac{\\left(\\mathrm{e}^\\sigma\\cos\\theta-1\\right)\\sigma+\\left(\\mathrm{e}^\\sigma\\sin\\theta\\right)\\theta}{\\sigma^2+\\theta^2}\\right)\\boldsymbol{a}^\\wedge\\boldsymbol{a}^\\wedge. \\end{aligned} \\]\u4e8e\u662f\uff0c\u674e\u4ee3\u6570\u4e0e\u674e\u7fa4\u7684\u5173\u7cfb:
\\[ s=\\mathrm{e}^\\sigma, R=\\exp(\\phi^\\wedge), t=J_s\\rho. \\] \\[ \\frac{\\partial\\boldsymbol{Sp}}{\\partial\\boldsymbol{\\zeta}}=\\begin{bmatrix}\\boldsymbol{I}&-\\boldsymbol{q}^\\wedge&\\boldsymbol{q}\\\\\\boldsymbol{0}^\\mathrm{T}&\\boldsymbol{0}^\\mathrm{T}&0\\end{bmatrix}. \\]"},{"location":"AI/SLAM14/#47","title":"4.7 \u4e60\u9898","text":"TODO
"},{"location":"AI/SLAM14/#5","title":"5 \u76f8\u673a\u4e0e\u56fe\u50cf","text":"\u53bb\u6389\u8d1f\u53f7:
\\[ \\frac Zf=\\frac X{X^{\\prime}}=\\frac Y{Y^{\\prime}}. \\] \\[ \\begin{aligned}X'&=f\\frac{X}{Z}\\\\Y'&=f\\frac{Y}{Z}\\end{aligned}. \\]\u8fd8\u6709\u4e00\u4e2a\u50cf\u7d20\u5750\u6807\u7cfb\uff0cu \u8f74\u4e0e x \u8f74\u5e73\u884c\uff0cv \u8f74\u4e0e y \u8f74\u5e73\u884c:
\\[ \\begin{cases}u=\\alpha X'+c_x\\\\[2ex]v=\\beta Y'+c_y\\end{cases}. \\] \\[ \\begin{cases}u=f_x\\frac{X}{Z}+c_x\\\\\\\\v=f_y\\frac{Y}{Z}+c_y\\end{cases}. \\] \\[ Z\\begin{pmatrix}u\\\\\\\\v\\\\\\\\1\\end{pmatrix}=\\begin{pmatrix}f_x&0&c_x\\\\0&f_y&c_y\\\\\\\\0&0&1\\end{pmatrix}\\begin{pmatrix}X\\\\\\\\Y\\\\\\\\Z\\end{pmatrix}\\overset{\\text{def}}{=}\\boldsymbol{KP}. \\]\u6700\u4e2d\u95f4\u7684\u77e9\u9635\u79f0\u4e3a\u76f8\u673a\u7684\u5185\u53c2\u6570\uff08Camera Inrinsics\uff09\u77e9\u9635 \\(\\displaystyle \\boldsymbol{K}\\)\u3002 \u6807\u5b9a: \u786e\u5b9a\u76f8\u673a\u7684\u5185\u53c2
\\[ Z\\boldsymbol{P}_{uv}=Z\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}=\\boldsymbol{K}\\left(\\boldsymbol{R}\\boldsymbol{P}_\\mathrm{w}+\\boldsymbol{t}\\right)=\\boldsymbol{K}\\boldsymbol{T}\\boldsymbol{P}_\\mathrm{w}. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{R},\\boldsymbol{t}\\) \u53c8\u79f0\u4e3a\u76f8\u673a\u7684\u5916\u53c2\u6570\uff08Camera Extrinsics\uff09
\\[ (\\boldsymbol{RP_\\mathrm{w}}+\\boldsymbol{t})=\\underbrace{[X,Y,Z]^\\mathrm{T}}_{\\text{\u76f8\u673a\u5750\u6807}}\\to\\underbrace{[X/Z,Y/Z,1]^\\mathrm{T}}_{\\text{\u5f52\u4e00\u5316\u5750\u6807}} . \\]\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u627e\u5230\u4e00\u4e2a\u70b9\u5728\u50cf\u7d20\u5e73\u9762\u4e0a\u7684\u6b63\u786e\u4f4d\u7f6e:
\u8fd8\u6709\u5f88\u591a\u7684\u76f8\u673a\u6a21\u578b\u6bd4\u5982: \u4eff\u5c04\u6a21\u578b\uff0c\u900f\u89c6\u6a21\u578b\u3002
\u603b\u7ed3\u4e00\u4e0b\u5355\u76ee\u76f8\u673a\u7684\u6210\u50cf\u8fc7\u7a0b:
\u4e24\u8005\u4e4b\u95f4\u7684\u8ddd\u79bb\u79f0\u4e3a\u53cc\u76ee\u76f8\u673a\u7684\u57fa\u7ebf
\\[ z=\\frac{fb}{d},\\quad d\\stackrel{\\mathrm{def}}{=}u_{\\mathrm{L}}-u_{\\mathrm{R}}. \\]TODO
"},{"location":"AI/SLAM14/#532","title":"5.3.2 \u56fe\u50cf\u53bb\u7578\u53d8","text":"TODO
"},{"location":"AI/SLAM14/#54-3-d","title":"5.4 \u5b9e\u8df5: 3 D \u89c6\u89c9","text":""},{"location":"AI/SLAM14/#541","title":"5.4.1 \u53cc\u76ee\u89c6\u89c9","text":"TODO
"},{"location":"AI/SLAM14/#542-rgb-d","title":"5.4.2 RGB-D \u89c6\u89c9","text":""},{"location":"AI/SLAM14/#55","title":"5.5 \u4e60\u9898","text":""},{"location":"AI/SLAM14/#6","title":"6 \u975e\u7ebf\u6027\u4f18\u5316","text":"\u524d\u9762\u6211\u4eec\u5df2\u7ecf\u641e\u6e05\u695a\u4e86\u8fd0\u52a8\u65b9\u7a0b\u548c\u89c2\u6d4b\u65b9\u7a0b\u7684\u6765\u6e90\uff0c\u73b0\u5728\u6211\u4eec\u5f00\u59cb\u8ba8\u8bba\u566a\u58f0\u3002
"},{"location":"AI/SLAM14/#61","title":"6.1 \u72b6\u6001\u4f30\u8ba1\u95ee\u9898","text":""},{"location":"AI/SLAM14/#611","title":"6.1.1 \u6279\u91cf\u72b6\u6001\u4f30\u8ba1\u4e0e\u6700\u5927\u540e\u9a8c\u4f30\u8ba1","text":"\\[ \\begin{cases}\\boldsymbol{x}_k=f\\left(\\boldsymbol{x}_{k-1},\\boldsymbol{u}_k\\right)+\\boldsymbol{w}_k\\\\\\boldsymbol{z}_{k,j}=h\\left(\\boldsymbol{y}_j,\\boldsymbol{x}_k\\right)+\\boldsymbol{v}_{k,j}\\end{cases}. \\] \\[ s\\boldsymbol{z}_{k,j}=\\boldsymbol{K}(R_k\\boldsymbol{y}_j+\\boldsymbol{t}_k). \\]\u5176\u4e2d \\(\\displaystyle s\\) \u4e3a\u50cf\u7d20\u70b9\u7684\u8ddd\u79bb\u3002 \u6211\u4eec\u901a\u5e38\u5047\u8bbe\u566a\u58f0\u9879\u6ee1\u8db3\u96f6\u5747\u503c\u7684\u9ad8\u65af\u5206\u5e03:
\\[ \\boldsymbol{w}_k\\sim\\mathcal{N}\\left(\\boldsymbol{0},\\boldsymbol{R}_k\\right),\\boldsymbol{v}_k\\sim\\mathcal{N}\\left(\\boldsymbol{0},\\boldsymbol{Q}_{k,j}\\right). \\]\u6709\u4e24\u79cd\u65b9\u6cd5\u6765\u89e3\u51b3\u72b6\u6001\u4f30\u8ba1\u95ee\u9898:
\u53ef\u4ee5\u5148\u6c42\u4e00\u4e2a\u72b6\u6001\u6700\u4f18\u4f30\u8ba1:
\\[ (\\boldsymbol{x},\\boldsymbol{y})^*_{\\mathrm{MAP}}=\\arg\\max P(\\boldsymbol{x},\\boldsymbol{y}|\\boldsymbol{z},\\boldsymbol{u})=\\arg\\max P(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y})P(\\boldsymbol{x},\\boldsymbol{y}). \\]\u6c42\u89e3\u6700\u5927\u540e\u9a8c\u6982\u7387\u7b49\u4ef7\u4e8e\u6700\u5927\u5316\u4f3c\u7136\u548c\u5148\u9a8c\u7684\u4e58\u79ef\u3002 \u4f46\u5982\u679c\u6ca1\u6709\u7684\u5148\u9a8c\uff0c\u90a3\u4e48\u53ef\u4ee5\u6c42\u89e3\u6700\u5927\u4f3c\u7136\u4f30\u8ba1 (Maximize Likelihood Estimation\uff0c MLE):
\\[ (\\boldsymbol{x},\\boldsymbol{y})^*{}_{\\mathrm{MLE}}=\\arg\\max P(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y}). \\]\u6700\u5927\u4f3c\u7136\u4f30\u8ba1: \u5728\u4ec0\u4e48\u6837\u7684\u72b6\u6001\u4e0b\uff0c\u6700\u53ef\u80fd\u4ea7\u751f\u73b0\u5728\u89c2\u6d4b\u5230\u7684\u6570\u636e\u3002
"},{"location":"AI/SLAM14/#612","title":"6.1.2 \u6700\u5c0f\u4e8c\u4e58\u7684\u5f15\u51fa","text":"\u5bf9\u4e8e\u67d0\u4e00\u6b21\u89c2\u6d4b:
\\[ z_{k,j}=h\\left(y_{j},x_{k}\\right)+v_{k,j}, \\] \\[ P(\\boldsymbol{z}_{j,k}|\\boldsymbol{x}_k,\\boldsymbol{y}_j)=N\\left(h(\\boldsymbol{y}_j,\\boldsymbol{x}_k),\\boldsymbol{Q}_{k,j}\\right). \\]\u53ef\u4ee5\u4f7f\u7528\u6700\u5c0f\u5316\u8d1f\u5bf9\u6570\u6765\u6c42\u4e00\u4e2a\u9ad8\u65af\u5206\u5e03\u7684\u6700\u5927\u4f3c\u7136\u3002
\\[ P\\left(\\boldsymbol{x}\\right)=\\frac{1}{\\sqrt{\\left(2\\pi\\right)^{N}\\det\\left(\\boldsymbol{\\Sigma}\\right)}}\\exp\\left(-\\frac{1}{2}(\\boldsymbol{x}-\\boldsymbol{\\mu})^{\\mathrm{T}}\\boldsymbol{\\Sigma}^{-1}\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right)\\right). \\] \\[ -\\ln\\left(P\\left(\\boldsymbol{x}\\right)\\right)=\\frac12\\ln\\left(\\left(2\\pi\\right)^N\\det\\left(\\boldsymbol{\\Sigma}\\right)\\right)+\\frac12\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right)^\\mathrm{T}\\boldsymbol{\\Sigma}^{-1}\\left(\\boldsymbol{x}-\\boldsymbol{\\mu}\\right). \\] \\[ \\begin{aligned} (x_{k},y_{j})^{*}& =\\arg\\max\\mathcal{N}(h(\\boldsymbol{y}_{j},\\boldsymbol{x}_{k}),\\boldsymbol{Q}_{k,j}) \\\\ &=\\arg\\min\\left(\\left(\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right)\\right)^\\mathrm{T}\\boldsymbol{Q}_{k,j}^{-1}\\left(\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right)\\right)\\right). \\end{aligned} \\]\u8be5\u5f0f\u7b49\u4ef7\u4e8e\u6700\u5c0f\u5316\u566a\u58f0\u9879\u7684\u4e00\u4e2a\u4e8c\u6b21\u578b\uff0c\u9a6c\u54c8\u62c9\u8bfa\u6bd4\u65af\u8ddd\u79bb (Mahalanobis distance)\u3002\u5176\u4e2d \\(\\displaystyle \\boldsymbol{Q}_{k,j}^{-1}\\) \u53eb\u4fe1\u606f\u77e9\u9635\uff0c\u5373\u9ad8\u65af\u5206\u5e03\u534f\u65b9\u5dee\u77e9\u9635\u4e4b\u9006\u3002 \u5047\u8bbe\u5404\u4e2a\u65f6\u523b\u7684\u8f93\u5165\u548c\u89c2\u6d4b\u90fd\u662f\u72ec\u7acb\u7684\uff0c\u90a3\u4e48:
\\[ P\\left(\\boldsymbol{z},\\boldsymbol{u}|\\boldsymbol{x},\\boldsymbol{y}\\right)=\\prod_kP\\left(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k\\right)\\prod_{k,j}P\\left(\\boldsymbol{z}_{k,j}|\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right), \\] \\[ \\begin{align} e_{u,k} &=\\boldsymbol{x}_k-f\\left(\\boldsymbol{x}_{k-1},\\boldsymbol{u}_k\\right) \\\\ e_{z,j,k} &=\\boldsymbol{z}_{k,j}-h\\left(\\boldsymbol{x}_k,\\boldsymbol{y}_j\\right), \\end{align} \\] \\[ \\min J(\\boldsymbol{x},\\boldsymbol{y})=\\sum_{k}\\boldsymbol{e}_{\\boldsymbol{u},k}^{\\mathrm{T}}\\boldsymbol{R}_{k}^{-1}\\boldsymbol{e}_{\\boldsymbol{u},k}+\\sum_{k}\\sum_{j}\\boldsymbol{e}_{\\boldsymbol{z},k,j}^{\\mathrm{T}}\\boldsymbol{Q}_{k,j}^{-1}\\boldsymbol{e}_{\\boldsymbol{z},k,j}. \\]\u8fd9\u6837\u5c31\u5f97\u5230\u4e86\u4e00\u4e2a\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898 (Least Square Problem)
\u8003\u8651\u4e00\u4e2a\u975e\u5e38\u7b80\u5355\u7684\u79bb\u6563\u65f6\u95f4\u7cfb\u7edf:
\\[ \\begin{aligned}&x_{k}=x_{k-1}+u_{k}+w_{k},&&\\boldsymbol{w}_{k}\\sim\\mathcal{N}\\left(0,\\boldsymbol{Q}_{k}\\right)\\\\&\\boldsymbol{z}_{k}=\\boldsymbol{x}_{k}+\\boldsymbol{n}_{k},&&\\boldsymbol{n}_{k}\\sim\\mathcal{N}\\left(0,\\boldsymbol{R}_{k}\\right)\\end{aligned} \\] \\[ \\begin{gathered} x_{map}^{*} =\\arg\\max P(\\boldsymbol{x}|\\boldsymbol{u},\\boldsymbol{z})=\\arg\\max P(\\boldsymbol{u},\\boldsymbol{z}|\\boldsymbol{x}) \\\\ =\\prod_{k=1}^3P(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k)\\prod_{k=1}^3P(\\boldsymbol{z}_k|\\boldsymbol{x}_k), \\end{gathered} \\]\u800c\u5bf9\u4e8e\u5177\u4f53\u7684\u6bcf\u4e00\u9879\uff0c\u6211\u4eec\u6709:
\\[ P(\\boldsymbol{u}_k|\\boldsymbol{x}_{k-1},\\boldsymbol{x}_k)=\\mathcal{N}(\\boldsymbol{x}_k-\\boldsymbol{x}_{k-1},\\boldsymbol{Q}_k), \\] \\[ P\\left(\\boldsymbol{z}_{k}|\\boldsymbol{x}_{k}\\right)=\\mathcal{N}\\left(\\boldsymbol{x}_{k},\\boldsymbol{R}_{k}\\right). \\]\u4e8e\u662f\uff0c\u6211\u4eec\u53ef\u4ee5\u6784\u5efa\u8bef\u5dee\u53d8\u91cf:
\\[ e_{\\boldsymbol{u},k}=\\boldsymbol{x}_k-\\boldsymbol{x}_{k-1}-\\boldsymbol{u}_k,\\quad\\boldsymbol{e}_{z,k}=\\boldsymbol{z}_k-\\boldsymbol{x}_k, \\]\u4e8e\u662f\u6700\u5c0f\u4e8c\u4e58\u7684\u76ee\u6807\u51fd\u6570\u4e3a:
\\[ \\min\\sum_{k=1}^{3}e_{u,k}^{\\mathrm{T}}Q_{k}^{-1}e_{u,k}+\\sum_{k=1}^{3}e_{z,k}^{\\mathrm{T}}R_{k}^{-1}e_{z,k}. \\]\u5b9a\u4e49\u5411\u91cf \\(\\displaystyle \\boldsymbol{y} = [\\boldsymbol{u},\\boldsymbol{z}]^\\mathrm{T}\\)
\\[ y-Hx=e\\sim\\mathcal{N}(\\mathbf{0},\\boldsymbol{\\Sigma}). \\] \\[ H=\\begin{bmatrix}1&-1&0&0\\\\0&1&-1&0\\\\0&0&1&-1\\\\\\hline0&1&0&0\\\\0&0&1&0\\\\0&0&0&1\\end{bmatrix}, \\]\u4e14 \\(\\displaystyle \\Sigma = diag(\\boldsymbol{Q_{1}},\\boldsymbol{Q_{2}},\\boldsymbol{Q_{3}},\\boldsymbol{R_{1}},\\boldsymbol{R_{2}},\\boldsymbol{R_{3}})\\)\u3002 \u95ee\u9898\u5c31\u8f6c\u5316\u6210:
\\[ x_{\\mathrm{map}}^*=\\arg\\min e^{\\mathrm{T}}\\Sigma^{-1}e, \\]\u5b83\u7684\u552f\u4e00\u89e3\u662f:
\\[ x_{\\mathrm{map}}^{*}=(H^{\\mathrm{T}}\\Sigma^{-1}H)^{-1}H^{\\mathrm{T}}\\Sigma^{-1}y. \\]"},{"location":"AI/SLAM14/#62","title":"6.2 \u975e\u7ebf\u6027\u6700\u5c0f\u4e8c\u4e58","text":"\u5148\u8003\u8651\u4e00\u4e2a\u7b80\u5355\u7684\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898:
\\[ \\min_{x}F(x)=\\frac12\\|f\\left(x\\right)\\|_{2}^{2}.` \\]\u5bf9\u4e8e\u4e0d\u65b9\u4fbf\u76f4\u63a5\u6c42\u89e3\u7684\u6700\u5c0f\u4e8c\u4e58\u95ee\u9898\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fed\u4ee3\u7684\u65b9\u5f0f\uff0c\u4ece\u4e00\u4e2a\u521d\u59cb\u503c\u51fa\u53d1\uff0c\u4e0d\u65ad\u5730\u66f4\u65b0\u5f53\u524d\u7684\u4f18\u5316\u53d8\u91cf\uff0c\u4f7f\u76ee\u6807\u51fd\u6570\u4e0b\u964d:
\u4e0b\u9762\u662f\u4e00\u4e9b\u5e7f\u6cdb\u4f7f\u7528\u7684\u7ed3\u679c\u3002
"},{"location":"AI/SLAM14/#621","title":"6.2.1 \u4e00\u9636\u548c\u4e8c\u9636\u68af\u5ea6\u6cd5","text":"\u4f7f\u7528\u6cf0\u52d2\u5c55\u5f00:
\\[ F(\\boldsymbol{x}_k+\\Delta\\boldsymbol{x}_k)\\approx F(\\boldsymbol{x}_k)+\\boldsymbol{J}\\left(\\boldsymbol{x}_k\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}_k+\\frac{1}{2}\\Delta\\boldsymbol{x}_k^\\mathrm{T}\\boldsymbol{H}(\\boldsymbol{x}_k)\\Delta\\boldsymbol{x}_k. \\]\u5176\u4e2d \\(\\displaystyle \\boldsymbol{J}(x_{k})\\) \u662f \\(\\displaystyle F(x)\\) \u5173\u4e8e \\(\\displaystyle x\\) \u7684\u4e00\u9636\u5bfc\u6570\uff08\u68af\u5ea6\u3001\u96c5\u53ef\u6bd4\u77e9\u9635\uff09\uff0c\\(\\displaystyle \\boldsymbol{H}\\) \u662f\u4e8c\u9636\u5bfc\u6570\uff08\u6d77\u585e\u77e9\u9635\uff09\u3002
\\[ \\Delta\\boldsymbol{x}^*=-\\boldsymbol{J}(\\boldsymbol{x}_k). \\] \\[ \\Delta\\boldsymbol{x}^*=\\arg\\min\\left(F\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}+\\frac{1}{2}\\Delta\\boldsymbol{x}^\\mathrm{T}\\boldsymbol{H}\\Delta\\boldsymbol{x}\\right). \\]\u5bf9 \\(\\displaystyle \\Delta x\\) \u6c42\u5bfc\uff0c\u5e76\u4ee4\u5b83\u7b49\u4e8e\u96f6\uff0c\u5f97\u5230:
\\[ J+H\\Delta x=\\mathbf{0}\\Rightarrow H\\Delta x=-J. \\]\u8fd9\u4e2a\u65b9\u6cd5\u53c8\u53eb\u725b\u987f\u6cd5\u3002
"},{"location":"AI/SLAM14/#622","title":"6.2.2 \u9ad8\u65af\u725b\u987f\u6cd5","text":"\u6362\u4e00\u4e2a\u51fd\u6570\u5c55\u5f00:
\\[ f\\left(x+\\Delta x\\right)\\approx f\\left(x\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}. \\] \\[ \\Delta x^{*}=\\arg\\min_{\\Delta x}\\frac{1}{2}\\Big\\|f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}\\Big\\|^{2}. \\] \\[ \\begin{aligned} \\frac12\\left\\|f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\right\\|^2& =\\frac12\\Big(f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\Big)^\\mathrm{T}\\Big(f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^\\mathrm{T}\\Delta\\boldsymbol{x}\\Big) \\\\ &=\\frac12\\left(\\|f(\\boldsymbol{x})\\|_2^2+2f\\left(\\boldsymbol{x}\\right)\\boldsymbol{J}(\\boldsymbol{x})^\\intercal\\Delta\\boldsymbol{x}+\\Delta\\boldsymbol{x}^\\intercal\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}(\\boldsymbol{x})^\\intercal\\Delta\\boldsymbol{x}\\right). \\end{aligned} \\] \\[ \\boldsymbol{J}(\\boldsymbol{x})f\\left(\\boldsymbol{x}\\right)+\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}^\\mathrm{T}\\left(\\boldsymbol{x}\\right)\\Delta\\boldsymbol{x}=\\boldsymbol{0}. \\] \\[ \\underbrace{\\boldsymbol{J}(\\boldsymbol{x})\\boldsymbol{J}^{\\intercal}}_{\\boldsymbol{H}(\\boldsymbol{x})}\\left(\\boldsymbol{x}\\right)\\Delta\\boldsymbol{x}=\\underbrace{-\\boldsymbol{J}(\\boldsymbol{x})f\\left(\\boldsymbol{x}\\right)}_{\\boldsymbol{g}(\\boldsymbol{x})}. \\]\u589e\u91cf\u65b9\u7a0b or Gauss-Newton equation or Normal equation
\\[ H\\Delta x=g. \\]\u6c42\u89e3\u589e\u91cf\u65b9\u7a0b\u662f\u6574\u4e2a\u4f18\u5316\u95ee\u9898\u7684\u6838\u5fc3\u6240\u5728 \u603b\u7ed3\u4e00\u4e0b:
Damped Newton Method Trust Region Trust Region Method
\\[ \\rho=\\frac{f\\left(\\boldsymbol{x}+\\Delta\\boldsymbol{x}\\right)-f\\left(\\boldsymbol{x}\\right)}{\\boldsymbol{J}\\left(\\boldsymbol{x}\\right)^{\\intercal}\\Delta\\boldsymbol{x}}. \\]\u6846\u67b6:
\u8fd9\u662f\u5e26\u4e0d\u7b49\u5f0f\u7ea6\u675f\u7684\u4f18\u5316\u95ee\u9898:
\\[ \\mathcal{L}(\\Delta\\boldsymbol{x}_{k},\\lambda)=\\frac{1}{2}\\left\\|f\\left(\\boldsymbol{x}_{k}\\right)+\\boldsymbol{J}\\left(\\boldsymbol{x}_{k}\\right)^{\\mathrm{T}}\\Delta\\boldsymbol{x}_{k}\\right\\|^{2}+\\frac{\\lambda}{2}\\left(\\left\\|\\boldsymbol{D}\\Delta\\boldsymbol{x}_{k}\\right\\|^{2}-\\mu\\right). \\] \\[ (H+\\lambda D^\\mathrm{T}D) \\Delta x_k=g. \\]"},{"location":"AI/SLAM14/#63","title":"6.3 \u5b9e\u8df5: \u66f2\u7ebf\u62df\u5408\u95ee\u9898","text":""},{"location":"AI/SLAM14/#631","title":"6.3.1 \u624b\u5199\u9ad8\u65af\u725b\u987f\u6cd5","text":"TODO
"},{"location":"AI/SLAM14/#632-ceres","title":"6.3.2 \u4f7f\u7528 Ceres \u8fdb\u884c\u66f2\u7ebf\u62df\u5408","text":"TODO
"},{"location":"AI/SLAM14/#633-g2o","title":"6.3.3 \u4f7f\u7528 g2o\u8fdb\u884c\u66f2\u7ebf\u62df\u5408","text":"TODO
"},{"location":"AI/SLAM14/#7-1","title":"7 \u89c6\u89c9\u91cc\u7a0b\u8ba1 1","text":""},{"location":"AI/SLAM14/#71","title":"7.1 \u7279\u5f81\u70b9\u6cd5","text":"data association Brute-Force Matcher
TODO
"},{"location":"AI/SLAM14/#722-orb","title":"7.2.2 \u624b\u5199 ORB \u7279\u5f81","text":""},{"location":"AI/SLAM14/#723","title":"7.2.3 \u8ba1\u7b97\u76f8\u673a\u8fd0\u52a8","text":"\u6210\u6295\u5f71\u5173\u7cfb:\u5c3a\u5ea6\u610f\u4e49\u4e0b\u76f8\u7b49 (equal up to scale)
\\[ sp\\simeq p. \\] \\[ p_1\\simeq KP,\\quad p_2\\simeq K\\left(RP+t\\right). \\] \\[ x_1=K^{-1}p_1,\\quad x_2=K^{-1}p_2. \\] \\[ x_2\\simeq Rx_1+t. \\] \\[ t^{\\wedge}x_{2}\\simeq t^{\\wedge}Rx_{1}. \\] \\[ x_2^\\mathrm{T}t^\\wedge x_2\\simeq x_2^\\mathrm{T}t^\\wedge Rx_1. \\] \\[ x_2^\\mathrm{T}t^\\wedge Rx_1=0. \\] \\[ p_2^\\mathrm{T}K^{-\\mathrm{T}}t^\\wedge RK^{-1}p_1=0. \\]\u5bf9\u6781\u7ea6\u675f
\\[ E=t^{\\wedge}R,\\quad F=K^{-\\mathrm{T}}EK^{-1},\\quad x_{2}^{\\mathrm{T}}Ex_{1}=p_{2}^{\\mathrm{T}}Fp_{1}=0. \\]\u672c\u8d28\u77e9\u9635: \\(\\displaystyle E=t^{\\wedge}R\\)
\u6211\u4eec\u628a\u6240\u6709\u70b9\u90fd\u653e\u5230\u4e00\u4e2a\u65b9\u7a0b\u4e2d\uff0c\u53d8\u6210\u7ebf\u6027\u65b9\u7a0b\u7ec4:
\\[ \\begin{pmatrix}u_2^1u_1^1&u_2^1v_1^1&u_2^1&v_2^1u_1^1&v_2^1v_1^1&v_2^1&u_1^1&v_1^1&1\\\\u_2^2u_1^2&u_2^2v_1^2&u_2^2&v_2^2u_1^2&v_2^2v_1^2&v_2^2&u_1^2&v_1^2&1\\\\\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots&\\vdots\\\\u_2^8u_1^8&u_2^8v_1^8&u_2^8&v_2^8u_1^8&v_2^8u_1^8&u_1^8&v_1^8&1\\end{pmatrix}\\begin{pmatrix}e_1\\\\e_2\\\\e_3\\\\e_4\\\\e_5\\\\e_6\\\\e_7\\\\e_8\\\\e_9\\end{pmatrix}=0. \\] \\[ E=U\\Sigma V^{\\mathrm{T}}, \\] \\[ \\begin{aligned}&t_{1}^{\\wedge}=UR_{Z}(\\frac{\\pi}{2})\\Sigma U^{\\mathrm{T}},\\quad R_{1}=UR_{Z}^{\\mathrm{T}}(\\frac{\\pi}{2})V^{\\mathrm{T}}\\\\&t_{2}^{\\wedge}=UR_{Z}(-\\frac{\\pi}{2})\\Sigma U^{\\mathrm{T}},\\quad R_{2}=UR_{Z}^{\\mathrm{T}}(-\\frac{\\pi}{2})V^{\\mathrm{T}}.\\end{aligned} \\] \\[ \\boldsymbol{E}=\\boldsymbol{U}\\mathrm{diag}(\\frac{\\sigma_1+\\sigma_2}2,\\frac{\\sigma_1+\\sigma_2}2,0)\\boldsymbol{V}^\\mathrm{T}. \\]"},{"location":"AI/SLAM14/#733","title":"7.3.3 \u5355\u5e94\u77e9\u9635","text":"Homography
"},{"location":"AI/SLAM14/#8-2","title":"8 \u89c6\u89c9\u91cc\u7a0b\u8ba1 2","text":""},{"location":"AI/SLAM14/#81","title":"8.1 \u76f4\u63a5\u6cd5\u7684\u5f15\u51fa","text":"vector<Point2f> pt1, pt2;\nfor (auto &kp: kp1) pt1.push_back(kp.pt);\nvector<uchar> status;\nvector<float> error;\ncv::calcOpticalFlowPyrLK(img1, img2, pt1, pt2, status, error);\n
"},{"location":"AI/SLAM14/#832","title":"8.3.2 \u7528\u9ad8\u65af\u725b\u987f\u6cd5\u5b9e\u73b0\u5149\u6d41","text":"\u5355\u5c42\u5149\u6d41 TODO
\\[ \\min_{\\Delta x,\\Delta y}\\left\\|\\boldsymbol{I}_1\\left(x,y\\right)-\\boldsymbol{I}_2\\left(x+\\Delta x,y+\\Delta y\\right)\\right\\|_2^2. \\]\u591a\u5c42\u5149\u6d41 - \u7531\u7c97\u81f3\u7cbe\uff08Coarse-to-fine\uff09
"},{"location":"AI/SLAM14/#833","title":"8.3.3 \u5149\u6d41\u5b9e\u8df5\u5c0f\u7ed3","text":""},{"location":"AI/SLAM14/#84","title":"8.4 \u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#841","title":"8.4.1 \u76f4\u63a5\u6cd5\u7684\u63a8\u5bfc","text":"\\[ \\boldsymbol{p}_1=\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}_1=\\frac{1}{Z_1}\\boldsymbol{K}\\boldsymbol{P}, \\] \\[ \\boldsymbol{p}_{2}=\\begin{bmatrix}u\\\\\\\\v\\\\\\\\1\\end{bmatrix}_{2}=\\frac{1}{Z_{2}}\\boldsymbol{K}\\left(\\boldsymbol{R}\\boldsymbol{P}+\\boldsymbol{t}\\right)=\\frac{1}{Z_{2}}\\boldsymbol{K}\\left(\\boldsymbol{T}\\boldsymbol{P}\\right)_{1:3}. \\] \\[ e=\\boldsymbol{I}_1\\left(\\boldsymbol{p}_1\\right)-\\boldsymbol{I}_2\\left(\\boldsymbol{p}_2\\right). \\] \\[ \\min_{T}J\\left(T\\right)=\\left\\|e\\right\\|^{2}. \\] \\[ \\min_{\\boldsymbol{T}}J\\left(\\boldsymbol{T}\\right)=\\sum_{i=1}^{N}e_{i}^{\\mathrm{T}}e_{i},\\quad e_{i}=\\boldsymbol{I}_{1}\\left(\\boldsymbol{p}_{1,i}\\right)-\\boldsymbol{I}_{2}\\left(\\boldsymbol{p}_{2,i}\\right). \\] \\[ \\begin{aligned}&q=TP,\\\\&\\boldsymbol{u}=\\frac{1}{Z_{2}}Kq.\\end{aligned} \\] \\[ e(T)=I_1(p_1)-I_2(u), \\] \\[ \\frac{\\partial e}{\\partial\\boldsymbol{T}}=\\frac{\\partial\\boldsymbol{I}_{2}}{\\partial\\boldsymbol{u}}\\frac{\\partial\\boldsymbol{u}}{\\partial\\boldsymbol{q}}\\frac{\\partial\\boldsymbol{q}}{\\partial\\delta\\boldsymbol{\\xi}}\\delta\\boldsymbol{\\xi}, \\] \\[ \\frac{\\partial\\boldsymbol{u}}{\\partial\\boldsymbol{q}}=\\begin{bmatrix}\\frac{\\partial u}{\\partial X}&\\frac{\\partial u}{\\partial Y}&\\frac{\\partial u}{\\partial Z}\\\\\\frac{\\partial v}{\\partial X}&\\frac{\\partial v}{\\partial Y}&\\frac{\\partial v}{\\partial Z}\\end{bmatrix}=\\begin{bmatrix}\\frac{f_x}{Z}&0&-\\frac{f_xX}{Z^2}\\\\0&\\frac{f_y}{Z}&-\\frac{f_yY}{Z^2}\\end{bmatrix}. \\] \\[ \\frac{\\partial\\boldsymbol{q}}{\\partial\\delta\\boldsymbol{\\xi}}=\\left[I,-\\boldsymbol{q}^{\\wedge}\\right]. \\] \\[ \\frac{\\partial\\boldsymbol{u}}{\\partial\\delta\\boldsymbol{\\xi}}=\\begin{bmatrix}\\frac{f_x}{Z}&0&-\\frac{f_xX}{Z^2}&-\\frac{f_xXY}{Z^2}&f_x+\\frac{f_xX^2}{Z^2}&-\\frac{f_xY}{Z}\\\\0&\\frac{f_y}{Z}&-\\frac{f_yY}{Z^2}&-f_y-\\frac{f_yY^2}{Z^2}&\\frac{f_yXY}{Z^2}&\\frac{f_yX}{Z}\\end{bmatrix}. \\] \\[ J=-\\frac{\\partial I_2}{\\partial u}\\frac{\\partial u}{\\partial\\delta\\xi}. \\]"},{"location":"AI/SLAM14/#842","title":"8.4.2 \u76f4\u63a5\u6cd5\u7684\u8ba8\u8bba","text":""},{"location":"AI/SLAM14/#85","title":"8.5 \u5b9e\u8df5: \u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#851","title":"8.5.1 \u5355\u5c42\u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#852","title":"8.5.2 \u591a\u5c42\u76f4\u63a5\u6cd5","text":""},{"location":"AI/SLAM14/#853","title":"8.5.3 \u7ed3\u679c\u8ba8\u8bba","text":"\u7ea6 3356 \u4e2a\u5b57 43 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 17 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/%E7%BB%9F%E8%AE%A1%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/#1","title":"1 \u7edf\u8ba1\u5b66\u4e60\u65b9\u6cd5\u6982\u8bba","text":""},{"location":"AI/%E7%BB%9F%E8%AE%A1%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/#11","title":"1.1 \u7edf\u8ba1\u5b66\u4e60","text":"\u7ea6 8852 \u4e2a\u5b57 167 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 44 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
This note is based on GitHub - DaizeDong/Stanford-CS231n-2021-and-2022: Notes and slides for Stanford CS231n 2021 & 2022 in English. I merged the contents together to get a better version. Assignments are not included. \u65af\u5766\u798fcs231n\u7684\u8bfe\u7a0b\u7b14\u8bb0(\u82f1\u6587\u7248\u672c\uff0c\u4e0d\u542b\u5b9e\u9a8c\u4ee3\u7801)\uff0c\u5c062021\u4e0e2022\u4e24\u5e74\u7684\u8bfe\u7a0b\u8fdb\u884c\u4e86\u5408\u5e76\uff0c\u5206\u4eab\u4ee5\u4f9b\u4ea4\u6d41\u3002 And I will add some blogs, articles and other understanding.
Topic Chapter Deep Learning Basics 2 - 4 Perceiving and Understanding the Visual World 5 - 12 Reconstructing and Interacting with the Visual World 13 - 16 Human-Centered Applications and Implications 17 - 18"},{"location":"AI/CS231n/CS231n_notes/#1-introduction","title":"1 - Introduction","text":"A brief history of computer vision & deep learning...
"},{"location":"AI/CS231n/CS231n_notes/#2-image-classification","title":"2 - Image Classification","text":"Image Classification: A core task in Computer Vision. The main drive to the progress of CV.
Challenges: Viewpoint variation, background clutter, illumination, occlusion, deformation, intra-class variation...
"},{"location":"AI/CS231n/CS231n_notes/#k-nearest-neighbor","title":"K Nearest Neighbor","text":"Hyperparameters: Distance metric (\\(p\\) norm), \\(k\\) number.
Choose hyperparameters using validation set.
Never use k-Nearest Neighbor with pixel distance.
"},{"location":"AI/CS231n/CS231n_notes/#linear-classifier","title":"Linear Classifier","text":"Pass...
"},{"location":"AI/CS231n/CS231n_notes/#3-loss-functions-and-optimization","title":"3 - Loss Functions and Optimization","text":""},{"location":"AI/CS231n/CS231n_notes/#loss-functions","title":"Loss Functions","text":"Dataset \\(\\big\\{(x_i,y_i)\\big\\}_{i=1}^N\\\\\\) Loss Function \\(L=\\frac{1}{N}\\sum_{i=1}^NL_i\\big(f(x_i,W),y_i\\big)\\\\\\) Loss Function with Regularization \\(L=\\frac{1}{N}\\sum_{i=1}^NL_i\\big(f(x_i,W),y_i\\big)+\\lambda R(W)\\\\\\)Motivation: Want to interpret raw classifier scores as probabilities.
Softmax Classifier \\(p_i=Softmax(y_i)=\\frac{\\exp(y_i)}{\\sum_{j=1}^N\\exp(y_j)}\\\\\\) Cross Entropy Loss \\(L_i=-y_i\\log p_i\\\\\\) Cross Entropy Loss with Regularization \\(L=-\\frac{1}{N}\\sum_{i=1}^Ny_i\\log p_i+\\lambda R(W)\\\\\\) "},{"location":"AI/CS231n/CS231n_notes/#optimization","title":"Optimization","text":""},{"location":"AI/CS231n/CS231n_notes/#sgd-with-momentum","title":"SGD with Momentum","text":"Problems that SGD can't handle:
Momentum: Build up \u201cvelocity\u201d \\(v_t\\) as a running mean of gradients.
SGD SGD + Momentum \\(x_{t+1}=x_t-\\alpha\\nabla f(x_t)\\) \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) Naive gradient descent. \\(\\rho\\) gives \"friction\", typically \\(\\rho=0.9,0.99,0.999,...\\)Nesterov Momentum: Use the derivative on point \\(x_t+\\rho v_t\\) as gradient instead point \\(x_t\\).
Momentum Nesterov Momentum \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) \\(\\begin{align}&v_{t+1}=\\rho v_t+\\nabla f(x_t+\\rho v_t)\\\\&x_{t+1}=x_t-\\alpha v_{t+1}\\end{align}\\) Use gradient at current point. Look ahead for the gradient in velocity direction. "},{"location":"AI/CS231n/CS231n_notes/#adagrad-and-rmsprop","title":"AdaGrad and RMSProp","text":"AdaGrad: Accumulate squared gradient, and gradually decrease the step size.
RMSProp: Accumulate squared gradient while decaying former ones, and gradually decrease the step size. (\"Leaky AdaGrad\")
AdaGrad RMSProp \\(\\begin{align}\\text{Initialize:}&\\\\&r:=0\\\\\\text{Update:}&\\\\&r:=r+\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{\\nabla f(x_t)}{\\sqrt{r}}\\end{align}\\) \\(\\begin{align}\\text{Initialize:}&\\\\&r:=0\\\\\\text{Update:}&\\\\&r:=\\rho r+(1-\\rho)\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{\\nabla f(x_t)}{\\sqrt{r}}\\end{align}\\) Continually accumulate squared gradients. \\(\\rho\\) gives \"decay rate\", typically \\(\\rho=0.9,0.99,0.999,...\\)"},{"location":"AI/CS231n/CS231n_notes/#adam","title":"Adam","text":"Sort of like \"RMSProp + Momentum\".
Adam (simple version) Adam (full version) \\(\\begin{align}\\text{Initialize:}&\\\\&r_1:=0\\\\&r_2:=0\\\\\\text{Update:}&\\\\&r_1:=\\beta_1r_1+(1-\\beta_1)\\nabla f(x_t)\\\\&r_2:=\\beta_2r_2+(1-\\beta_2)\\Big[\\nabla f(x_t)\\Big]^2\\\\&x_{t+1}=x_t-\\alpha\\frac{r_1}{\\sqrt{r_2}}\\end{align}\\) \\(\\begin{align}\\text{Initialize:}\\\\&r_1:=0\\\\&r_2:=0\\\\\\text{For }i\\text{:}\\\\&r_1:=\\beta_1r_1+(1-\\beta_1)\\nabla f(x_t)\\\\&r_2:=\\beta_2r_2+(1-\\beta_2)\\Big[\\nabla f(x_t)\\Big]^2\\\\&r_1'=\\frac{r_1}{1-\\beta_1^i}\\\\&r_2'=\\frac{r_2}{1-\\beta_2^i}\\\\&x_{t+1}=x_t-\\alpha\\frac{r_1'}{\\sqrt{r_2'}}\\end{align}\\) Build up \u201cvelocity\u201d for both gradient and squared gradient. Correct the \"bias\" that \\(r_1=r_2=0\\) for the first few iterations."},{"location":"AI/CS231n/CS231n_notes/#overview","title":"Overview","text":""},{"location":"AI/CS231n/CS231n_notes/#learning-rate-decay","title":"Learning Rate Decay","text":"Reduce learning rate at a few fixed points to get a better convergence over time.
\\(\\alpha_0\\) : Initial learning rate.
\\(\\alpha_t\\) : Learning rate in epoch \\(t\\).
\\(T\\) : Total number of epochs.
Method Equation Picture Step Reduce \\(\\alpha_t\\) constantly in a fixed step. Cosine \\(\\begin{align}\\alpha_t=\\frac{1}{2}\\alpha_0\\Bigg[1+\\cos(\\frac{t\\pi}{T})\\Bigg]\\end{align}\\) Linear \\(\\begin{align}\\alpha_t=\\alpha_0\\Big(1-\\frac{t}{T}\\Big)\\end{align}\\) Inverse Sqrt \\(\\begin{align}\\alpha_t=\\frac{\\alpha_0}{\\sqrt{t}}\\end{align}\\)High initial learning rates can make loss explode, linearly increasing learning rate in the first few iterations can prevent this.
Learning rate warm up:
Empirical rule of thumb: If you increase the batch size by \\(N\\), also scale the initial learning rate by \\(N\\) .
"},{"location":"AI/CS231n/CS231n_notes/#second-order-optimization","title":"Second-Order Optimization","text":"Picture Time Complexity Space Complexity First Order \\(O(n)\\) \\(O(n)\\) Second Order \\(O(n^2)\\) with BGFS optimization \\(O(n)\\) with L-BGFS optimizationL-BGFS : Limited memory BGFS.
Motivation: Inducted bias can appear to be high when using human-designed features.
Activation: Sigmoid, tanh, ReLU, LeakyReLU...
Architecture: Input layer, hidden layer, output layer.
Do not use the size of a neural network as the regularizer. Use regularization instead!
Gradient Calculation: Computational Graph + Backpropagation.
"},{"location":"AI/CS231n/CS231n_notes/#backpropagation","title":"Backpropagation","text":"Using Jacobian matrix to calculate the gradient of each node in a computation graph.
Suppose that we have a computation flow like this:
Input X Input W Output Y \\(X=\\begin{bmatrix}x_1\\\\x_2\\\\\\vdots\\\\x_n\\end{bmatrix}\\) \\(W=\\begin{bmatrix}w_{11}&w_{12}&\\cdots&w_{1n}\\\\w_{21}&w_{22}&\\cdots&w_{2n}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\w_{m1}&w_{m2}&\\cdots&w_{mn}\\end{bmatrix}\\) \\(Y=\\begin{bmatrix}y_1\\\\y_2\\\\\\vdots\\\\y_m\\end{bmatrix}\\) \\(n\\times 1\\) \\(m\\times n\\) \\(m\\times 1\\)After applying feed forward, we can calculate gradients like this:
Derivative Matrix of X Jacobian Matrix of X Derivative Matrix of Y \\(D_X=\\begin{bmatrix}\\frac{\\partial L}{\\partial x_1}\\\\\\frac{\\partial L}{\\partial x_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial x_n}\\end{bmatrix}\\) \\(J_X=\\begin{bmatrix}\\frac{\\partial y_1}{\\partial x_1}&\\frac{\\partial y_1}{\\partial x_2}&\\cdots&\\frac{\\partial y_1}{\\partial x_n}\\\\\\frac{\\partial y_2}{\\partial x_1}&\\frac{\\partial y_2}{\\partial x_2}&\\cdots&\\frac{\\partial y_2}{\\partial x_n}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial y_m}{\\partial x_1}&\\frac{\\partial y_m}{\\partial x_2}&\\cdots&\\frac{\\partial y_m}{\\partial x_n}\\end{bmatrix}\\) \\(D_Y=\\begin{bmatrix}\\frac{\\partial L}{\\partial y_1}\\\\\\frac{\\partial L}{\\partial y_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial y_m}\\end{bmatrix}\\) \\(n\\times 1\\) \\(m\\times n\\) \\(m\\times 1\\) Derivative Matrix of W Jacobian Matrix of W Derivative Matrix of Y \\(W=\\begin{bmatrix}\\frac{\\partial L}{\\partial w_{11}}&\\frac{\\partial L}{\\partial w_{12}}&\\cdots&\\frac{\\partial L}{\\partial w_{1n}}\\\\\\frac{\\partial L}{\\partial w_{21}}&\\frac{\\partial L}{\\partial w_{22}}&\\cdots&\\frac{\\partial L}{\\partial w_{2n}}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial L}{\\partial w_{m1}}&\\frac{\\partial L}{\\partial w_{m2}}&\\cdots&\\frac{\\partial L}{\\partial w_{mn}}\\end{bmatrix}\\) \\(J_W^{(k)}=\\begin{bmatrix}\\frac{\\partial y_k}{\\partial w_{11}}&\\frac{\\partial y_k}{\\partial w_{12}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{1n}}\\\\\\frac{\\partial y_k}{\\partial w_{21}}&\\frac{\\partial y_k}{\\partial w_{22}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{2n}}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial y_k}{\\partial w_{m1}}&\\frac{\\partial y_k}{\\partial w_{m2}}&\\cdots&\\frac{\\partial y_k}{\\partial w_{mn}}\\end{bmatrix}\\)\\(J_W=\\begin{bmatrix}J_W^{(1)}&J_W^{(2)}&\\cdots&J_W^{(m)}\\end{bmatrix}\\) \\(D_Y=\\begin{bmatrix}\\frac{\\partial L}{\\partial y_1}\\\\\\frac{\\partial L}{\\partial y_2}\\\\\\vdots\\\\\\frac{\\partial L}{\\partial y_m}\\end{bmatrix}\\) \\(m\\times n\\) \\(m\\times m\\times n\\) $ m\\times 1$For each element in \\(D_X\\) , we have:
\\(D_{Xi}=\\frac{\\partial L}{\\partial x_i}=\\sum_{j=1}^m\\frac{\\partial L}{\\partial y_j}\\frac{\\partial y_j}{\\partial x_i}\\\\\\)
"},{"location":"AI/CS231n/CS231n_notes/#5-convolutional-neural-networks","title":"5 - Convolutional Neural Networks","text":""},{"location":"AI/CS231n/CS231n_notes/#convolution-layer","title":"Convolution Layer","text":""},{"location":"AI/CS231n/CS231n_notes/#introduction","title":"Introduction","text":"Convolve a filter with an image: Slide the filter spatially within the image, computing dot products in each region.
Giving a \\(32\\times32\\times3\\) image and a \\(5\\times5\\times3\\) filter, a convolution looks like:
Convolve six \\(5\\times5\\times3\\) filters to a \\(32\\times32\\times3\\) image with step size \\(1\\), we can get a \\(28\\times28\\times6\\) feature:
With an activation function after each convolution layer, we can build the ConvNet with a sequence of convolution layers:
By changing the step size between each move for filters, or adding zero-padding around the image, we can modify the size of the output:
"},{"location":"AI/CS231n/CS231n_notes/#1times1-convolution-layer","title":"\\(1\\times1\\) Convolution Layer","text":"This kind of layer makes perfect sense. It is usually used to change the dimension (channel) of features.
A \\(1\\times1\\) convolution layer can also be treated as a full-connected linear layer.
"},{"location":"AI/CS231n/CS231n_notes/#summary_1","title":"Summary","text":"Input image size \\(W_1\\times H_1\\times C\\) filter size \\(F\\times F\\times C\\) filter number \\(K\\) stride \\(S\\) zero padding \\(P\\) Output output size \\(W_2\\times H_2\\times K\\) output width \\(W_2=\\frac{W_1-F+2P}{S}+1\\\\\\) output height \\(H_2=\\frac{H_1-F+2P}{S}+1\\\\\\) Parameters parameter number (weight) \\(F^2CK\\) parameter number (bias) \\(K\\)"},{"location":"AI/CS231n/CS231n_notes/#pooling-layer","title":"Pooling layer","text":"Make the representations smaller and more manageable.
An example of max pooling:
Input image size \\(W_1\\times H_1\\times C\\) spatial extent \\(F\\times F\\) stride \\(S\\) Output output size \\(W_2\\times H_2\\times C\\) output width \\(W_2=\\frac{W_1-F}{S}+1\\\\\\) output height \\(H_2=\\frac{H_1-F}{S}+1\\\\\\)"},{"location":"AI/CS231n/CS231n_notes/#convolutional-neural-networks-cnn","title":"Convolutional Neural Networks (CNN)","text":"CNN stack CONV, POOL, FC layers.
CNN Trends:
Historically architectures of CNN looked like:
where usually \\(m\\) is large, \\(0\\le n\\le5\\), \\(0\\le k\\le2\\).
Recent advances such as ResNet / GoogLeNet have challenged this paradigm.
"},{"location":"AI/CS231n/CS231n_notes/#6-cnn-architectures","title":"6 - CNN Architectures","text":"Best model in ImageNet competition:
"},{"location":"AI/CS231n/CS231n_notes/#alexnet","title":"AlexNet","text":"8 layers.
First use of ConvNet in image classification problem.
Filter size decreases in deeper layer.
Channel number increases in deeper layer.
"},{"location":"AI/CS231n/CS231n_notes/#vgg","title":"VGG","text":"19 layers. (also provide 16 layers edition)
Static filter size (\\(3\\times3\\)) in all layers:
Most memory is in early convolution layers.
Most parameter is in late FC layers.
"},{"location":"AI/CS231n/CS231n_notes/#googlenet","title":"GoogLeNet","text":"22 layers.
No FC layers, only 5M parameters. ( \\(8.3\\%\\) of AlexNet, \\(3.7\\%\\) of VGG )
Devise efficient \"inception module\".
"},{"location":"AI/CS231n/CS231n_notes/#inception-module","title":"Inception Module","text":"Design a good local network topology (network within a network) and then stack these modules on top of each other.
Naive Inception Module:
Inception Module with Dimension Reduction:
152 layers for ImageNet.
Devise \"residual connections\".
Use BN in place of dropout.
"},{"location":"AI/CS231n/CS231n_notes/#residual-connections","title":"Residual Connections","text":"Hypothesis: Deeper models have more representation power than shallow ones. But they are harder to optimize.
Solution: Use network layers to fit a residual mapping instead of directly trying to fit a desired underlying mapping.
It is necessary to use ReLU as activation function, in order to apply identity mapping when \\(F(x)=0\\) .
"},{"location":"AI/CS231n/CS231n_notes/#architecture_1","title":"Architecture","text":""},{"location":"AI/CS231n/CS231n_notes/#senet","title":"SENet","text":"Using ResNeXt-152 as a base architecture.
Add a \u201cfeature recalibration\u201d module. (adjust weights of each channel)
Using the global avg-pooling layer + FC layers to determine feature map weights.
"},{"location":"AI/CS231n/CS231n_notes/#improvements-of-resnet","title":"Improvements of ResNet","text":"Wide Residual Networks, ResNeXt, DenseNet, MobileNets...
"},{"location":"AI/CS231n/CS231n_notes/#other-interesting-networks","title":"Other Interesting Networks","text":"NASNet: Neural Architecture Search with Reinforcement Learning.
EfficientNet: Smart Compound Scaling.
"},{"location":"AI/CS231n/CS231n_notes/#7-training-neural-networks","title":"7 - Training Neural Networks","text":""},{"location":"AI/CS231n/CS231n_notes/#activation-functions","title":"Activation Functions","text":"Activation Usage Sigmoid, tanh Do not use. ReLU Use as default. Leaky ReLU, Maxout, ELU, SELU Replace ReLU to squeeze out some marginal gains. Swish No clear usage."},{"location":"AI/CS231n/CS231n_notes/#data-processing","title":"Data Processing","text":"Apply centralization and normalization before training.
In practice for pictures, usually we apply channel-wise centralization only.
"},{"location":"AI/CS231n/CS231n_notes/#weight-initialization","title":"Weight Initialization","text":"Assume that we have 6 layers in a network.
\\(D_i\\) : input size of layer \\(i\\)
\\(W_i\\) : weights in layer \\(i\\)
\\(X_i\\) : output after activation of layer \\(i\\), we have \\(X_i=g(Z_i)=g(W_iX_{i-1}+B_i)\\)
We initialize each parameter in \\(W_i\\) randomly in \\([-k_i,k_i]\\) .
Tanh Activation Output Distribution \\(k_i=0.01\\) \\(k_i=0.05\\) Xavier Initialization \\(k_i=\\frac{1}{\\sqrt{D_i}\\\\}\\)When \\(k_i=0.01\\), the variance keeps decreasing as the layer gets deeper. As a result, the output of each neuron in deep layer will all be 0. The partial derivative \\(\\frac{\\partial Z_i}{\\partial W_i}=X_{i-1}=0\\\\\\). (no gradient)
When \\(k_i=0.05\\), most neurons is saturated. The partial derivative \\(\\frac{\\partial X_i}{\\partial Z_i}=g'(Z_i)=0\\\\\\). (no gradient)
To solve this problem, We need to keep the variance same in each layer.
Assuming that \\(Var\\big(X_{i-1}^{(1)}\\big)=Var\\big(X_{i-1}^{(2)}\\big)=\\dots=Var\\big(X_{i-1}^{(D_i)}\\big)\\)
We have \\(Z_i=X_{i-1}^{(1)}W_i^{(:,1)}+X_{i-1}^{(2)}W_i^{(:,2)}+\\dots+X_{i-1}^{(D_i)}W_i^{(:,D_i)}=\\sum_{n=1}^{D_i}X_{i-1}^{(n)}W_i^{(:,n)}\\\\\\)
We want \\(Var\\big(Z_i\\big)=Var\\big(X_{i-1}^{(n)}\\big)\\)
Let's do some conduction:
\\(\\begin{aligned}Var\\big(Z_i\\big)&=Var\\Bigg(\\sum_{n=1}^{D_i}X_{i-1}^{(n)}W_i^{(:,n)}\\Bigg)\\\\&=D_i\\ Var\\Big(X_{i-1}^{(n)}W_i^{(:,n)}\\Big)\\\\&=D_i\\ Var\\Big(X_{i-1}^{(n)}\\Big)\\ Var\\Big(W_i^{(:,n)}\\Big)\\end{aligned}\\)
So \\(Var\\big(Z_i\\big)=Var\\big(X_{i-1}^{(n)}\\big)\\) only when \\(Var\\Big(W_i^{(:,n)}\\Big)=\\frac{1}{D_i}\\\\\\), that is to say \\(k_i=\\frac{1}{\\sqrt{D_i}}\\\\\\)
ReLU Activation Output Distribution Xavier Initialization \\(k_i=\\frac{1}{\\sqrt{D_i}\\\\}\\) Kaiming Initialization \\(k_i=\\sqrt{2D_i}\\)For ReLU activation, when using xavier initialization, there still exist \"variance decreasing\" problem.
We can use kaiming initialization instead to fix this.
"},{"location":"AI/CS231n/CS231n_notes/#batch-normalization","title":"Batch Normalization","text":"Force the inputs to be \"nicely scaled\" at each layer.
\\(N\\) : batch size
\\(D\\) : feature size
\\(x\\) : input with shape \\(N\\times D\\)
\\(\\gamma\\) : learnable scale and shift parameter with shape \\(D\\)
\\(\\beta\\) : learnable scale and shift parameter with shape \\(D\\)
The procedure of batch normalization:
Why scale: The constraint \"zero-mean, unit variance\" may be too hard.
Pros:
Cons:
Behaves differently during training and testing: this is a very common source of bugs!
"},{"location":"AI/CS231n/CS231n_notes/#transfer-learning","title":"Transfer Learning","text":"Train on a pre-trained model with other datasets.
An empirical suggestion:
very similar dataset very different dataset very little data Use Linear Classifier on top layer. You\u2019re in trouble\u2026 Try linear classifier from different stages. quite a lot of data Finetune a few layers. Finetune a larger number of layers."},{"location":"AI/CS231n/CS231n_notes/#regularization","title":"Regularization","text":""},{"location":"AI/CS231n/CS231n_notes/#common-pattern-of-regularization","title":"Common Pattern of Regularization","text":"Training: Add some kind of randomness. \\(y=f(x,z)\\)
Testing: Average out randomness (sometimes approximate). \\(y=f(x)=E_z\\big[f(x,z)\\big]=\\int p(z)f(x,z)dz\\\\\\)
"},{"location":"AI/CS231n/CS231n_notes/#regularization-term","title":"Regularization Term","text":"L2 regularization: \\(R(W)=\\sum_k\\sum_lW_{k,l}^2\\) (weight decay)
L1 regularization: \\(R(W)=\\sum_k\\sum_l|W_{k,l}|\\)
Elastic net : \\(R(W)=\\sum_k\\sum_l\\big(\\beta W_{k,l}^2+|W_{k,l}|\\big)\\) (L1+L2)
"},{"location":"AI/CS231n/CS231n_notes/#dropout","title":"Dropout","text":"Training: Randomly set some neurons to 0 with a probability \\(p\\) .
Testing: Each neuron multiplies by dropout probability \\(p\\) . (scale the output back)
More common: Scale the output with \\(\\frac{1}{p}\\) when training, keep the original output when testing.
Why dropout works:
See above.
"},{"location":"AI/CS231n/CS231n_notes/#data-augmentation","title":"Data Augmentation","text":"There also exists automatic data augmentation method using neural networks.
"},{"location":"AI/CS231n/CS231n_notes/#other-methods-and-summary","title":"Other Methods and Summary","text":"DropConnect: Drop connections between neurons.
Fractional Max Pooling: Use randomized pooling regions.
Stochastic Depth: Skip some layers in the network.
Cutout: Set random image regions to zero.
Mixup: Train on random blends of images.
Regularization Method Usage Dropout For large fully-connected layers. Batch Normalization & Data Augmentation Almost always a good idea. Cutout & Mixup For small classification datasets."},{"location":"AI/CS231n/CS231n_notes/#hyperparameter-tuning","title":"Hyperparameter Tuning","text":"Most Common Hyperparameters Less Sensitive Hyperparameters learning ratelearning rate decay scheduleweight decay setting of momentum...Tips on hyperparameter tuning:
Have a worker that continuously samples random hyperparameters and performs the optimization. During the training, the worker will keep track of the validation performance after every epoch, and writes a model checkpoint to a file.
Have a master that launches or kills workers across a computing cluster, and may additionally inspect the checkpoints written by workers and plot their training statistics.
"},{"location":"AI/CS231n/CS231n_notes/#common-procedures","title":"Common Procedures","text":"Turn off weight decay, sanity check loss at initialization \\(\\log(C)\\) for softmax with \\(C\\) classes.
Try to train to 100% training accuracy on a small sample of training data.
Fiddle with architecture, learning rate, weight initialization.
Use the architecture from the previous step, use all training data, turn on small weight decay, find a learning rate that makes the loss drop significantly within 100 iterations.
Good learning rates to try: \\(0.1,0.01,0.001,0.0001,\\dots\\)
Choose a few values of learning rate and weight decay around what worked from Step 3, train a few models for 1-5 epochs.\\
Good weight decay to try: \\(0.0001,0.00001,0\\)
Pick best models from Step 4, train them for longer (10-20 epochs) without learning rate decay.
CS231n Convolutional Neural Networks for Visual Recognition
Compute analytical gradient manually using \\(f_a'=\\frac{\\partial f(x)}{\\partial x}=\\frac{f(x-h)-f(x+h)}{2h}\\\\\\)
Get relative error between numerical gradient \\(f_n'\\) and analytical gradient \\(f_a'\\) using \\(E=\\frac{|f_n'-f_a'|}{\\max{|f_n'|,|f_a'|}}\\\\\\)
Relative Error Result \\(E>10^{-2}\\) Probably \\(f_n'\\) is wrong. \\(10^{-2}>E>10^{-4}\\) Not good, should check the gradient. \\(10^{-4}>E>10^{-6}\\) Okay for objectives with kinks. (e.g. ReLU)Not good for objectives with no kink. (e.g. softmax, tanh) \\(10^{-7}>E\\) Good.Tips on gradient checks:
For example, we have a layer with shape \\(128\\times13\\times13\\). We pick the 17th channel from all 128 channels. Then we run many pictures through the network. During each run we can find a maximal activation feature among all the \\(13\\times13\\) features in channel 17. We then record the corresponding picture patch for each maximal activation feature. At last, we visualize all picture patches for each feature.
This will help us find the relationship between each maximal activation feature and its corresponding picture patches.
(each row of the following picture represents a feature)
"},{"location":"AI/CS231n/CS231n_notes/#saliency-via-occlusion","title":"Saliency via Occlusion","text":"Mask part of the image before feeding to CNN, check how much predicted probabilities change.
"},{"location":"AI/CS231n/CS231n_notes/#saliency-via-backprop","title":"Saliency via Backprop","text":"Striving for Simplicity: The All Convolutional Net
Just like \"Maximally Activating Patches\", this could find the part of an image that a neuron responds to.
"},{"location":"AI/CS231n/CS231n_notes/#gradient-ascent","title":"Gradient Ascent","text":"Generate a synthetic image that maximally activates a neuron.
Objective: \\(\\max S_c(I)-\\lambda\\lVert I\\lVert^2\\)
Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps
"},{"location":"AI/CS231n/CS231n_notes/#adversarial-examples","title":"Adversarial Examples","text":"Find an fooling image that can make the network misclassify correctly-classified images when it is added to the image.
Given a CNN feature vector \\(\\Phi_0\\) for an image, find a new image \\(x\\) that:
Objective: \\(\\min \\lVert\\Phi(x)-\\Phi_0\\lVert+\\lambda R(x)\\)
Understanding Deep Image Representations by Inverting Them
"},{"location":"AI/CS231n/CS231n_notes/#deepdream-amplify-existing-features","title":"DeepDream: Amplify Existing Features","text":"Given an image, amplify the neuron activations at a layer to generate a new one.
Gram Matrix: \u683c\u62c9\u59c6\u77e9\u9635\uff08Gram matrix\uff09\u8be6\u7ec6\u89e3\u8bfb
Layer \\(i\\) gives feature map of shape \\(C_i\\times H_i\\times W_i\\).
Texture Synthesis Using Convolutional Neural Networks
"},{"location":"AI/CS231n/CS231n_notes/#style-transfer","title":"Style Transfer","text":""},{"location":"AI/CS231n/CS231n_notes/#feature-gram-reconstruction","title":"Feature + Gram Reconstruction","text":"Problem: Style transfer requires many forward / backward passes. Very slow!
"},{"location":"AI/CS231n/CS231n_notes/#fast-style-transfer","title":"Fast Style Transfer","text":""},{"location":"AI/CS231n/CS231n_notes/#9-object-detection-and-image-segmentation","title":"9 - Object Detection and Image Segmentation","text":""},{"location":"AI/CS231n/CS231n_notes/#semantic-segmentation","title":"Semantic Segmentation","text":"Paired Training Data: For each training image, each pixel is labeled with a semantic category.
Fully Convolutional Network: Design a network with only convolutional layers without downsampling operators to make predictions for pixels all at once!
Problem: Convolutions at original image resolution will be very expensive...
Solution: Design fully convolutional network with downsampling and upsampling inside it!
Unpooling:
Nearest Neighbor \"Bed of Nails\" \"Position Memory\"Transposed Convolution: (example size \\(3\\times3\\), stride \\(2\\), pad \\(1\\))
Normal Convolution Transposed Convolution "},{"location":"AI/CS231n/CS231n_notes/#object-detection","title":"Object Detection","text":""},{"location":"AI/CS231n/CS231n_notes/#single-object","title":"Single Object","text":"Classification + Localization. (classification + regression problem)
"},{"location":"AI/CS231n/CS231n_notes/#multiple-object","title":"Multiple Object","text":""},{"location":"AI/CS231n/CS231n_notes/#r-cnn","title":"R-CNN","text":"Using selective search to find \u201cblobby\u201d image regions that are likely to contain objects.
Problem: Very slow. Need to do 2000 independent forward passes for each image!
"},{"location":"AI/CS231n/CS231n_notes/#fast-r-cnn","title":"Fast R-CNN","text":"Pass the image through ConvNet before cropping. Crop the conv feature instead.
Problem: Runtime is dominated by region proposals. (about \\(90\\%\\) time cost)
"},{"location":"AI/CS231n/CS231n_notes/#faster-r-cnn","title":"Faster R-CNN","text":"Insert Region Proposal Network (RPN) to predict proposals from features.
Otherwise same as Fast R-CNN: Crop features for each proposal, classify each one.
Region Proposal Network (RPN) : Slide many fixed windows over ConvNet features.
We have \\(k\\) fixed windows (anchor boxes) of different size/scale centered with each anchor.
For positive boxes, also predict a corrections to the ground-truth box.
Faster R-CNN is a Two-stage object detector:
Backbone network
Region proposal network
Crop features: RoI pool / align
Predict object class
Prediction bbox offset
"},{"location":"AI/CS231n/CS231n_notes/#single-stage-object-detectors-yolo","title":"Single-Stage Object Detectors: YOLO","text":"You Only Look Once: Unified, Real-Time Object Detection
Mask R-CNN: Add a small mask network that operates on each RoI and predicts a \\(28\\times28\\) binary mask.
Mask R-CNN performs very good results!
"},{"location":"AI/CS231n/CS231n_notes/#10-recurrent-neural-networks","title":"10 - Recurrent Neural Networks","text":"Supplement content added according to Deep Learning Book - RNN.
"},{"location":"AI/CS231n/CS231n_notes/#recurrent-neural-network-rnn","title":"Recurrent Neural Network (RNN)","text":""},{"location":"AI/CS231n/CS231n_notes/#motivation-sequence-processing","title":"Motivation: Sequence Processing","text":"One to One One to Many Many to One Many to Many Many to Many Vanilla Neural Networks Image Captioning Action Prediction Video Captioning Video Classification on Frame Level"},{"location":"AI/CS231n/CS231n_notes/#vanilla-rnn","title":"Vanilla RNN","text":"\\(x^{(t)}\\) : Input at time \\(t\\).
\\(h^{(t)}\\) : State at time \\(t\\).
\\(o^{(t)}\\) : Output at time \\(t\\)\u200b\u200b.
\\(y^{(t)}\\) : Expected output at time \\(t\\).
"},{"location":"AI/CS231n/CS231n_notes/#many-to-one","title":"Many to One","text":"Calculation State Transition \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(\\tau)}=\\text{sigmoid}\\ \\big(Vh^{(\\tau)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#many-to-many-type-2","title":"Many to Many (type 2)","text":"Calculation State Transition \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#rnn-with-teacher-forcing","title":"RNN with Teacher Forcing","text":"Update current state according to last-time output instead of last-time state.
Calculation State Transition \\(h^{(t)}=\\tanh(Wo^{(t-1)}+Ux^{(t)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#rnn-with-output-forwarding","title":"RNN with \"Output Forwarding\"","text":"We can also combine last-state output with this-state input together.
Calculation State Transition (training) \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+Ry^{(t-1)}+b)\\) State Transition (testing) \\(h^{(t)}=\\tanh(Wh^{(t-1)}+Ux^{(t)}+Ro^{(t-1)}+b)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\)Usually we use \\(o^{(t-1)}\\) in place of \\(y^{(t-1)}\\) at testing time.
"},{"location":"AI/CS231n/CS231n_notes/#bidirectional-rnn","title":"Bidirectional RNN","text":"When dealing with a whole input sequence, we can process features from two directions.
Calculation State Transition (forward) \\(h^{(t)}=\\tanh(W_1h^{(t-1)}+U_1x^{(t)}+b_1)\\) State Transition (backward) \\(g^{(t)}=\\tanh(W_2g^{(t+1)}+U_2x^{(t)}+b_2)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+Wg^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#encoder-decoder-sequence-to-sequence-rnn","title":"Encoder-Decoder Sequence to Sequence RNN","text":"This is a many-to-many structure (type 1).
First we encode information according to \\(x\\) with no output.
Later we decode information according to \\(y\\) with no input.
\\(C\\) : Context vector, often \\(C=h^{(T)}\\) (last state of encoder).
Calculation State Transition (encode) \\(h^{(t)}=\\tanh(W_1h^{(t-1)}+U_1x^{(t)}+b_1)\\) State Transition (decode, training) \\(s^{(t)}=\\tanh(W_2s^{(t-1)}+U_2y^{(t)}+TC+b_2)\\) State Transition (decode, testing) \\(s^{(t)}=\\tanh(W_2s^{(t-1)}+U_2o^{(t)}+TC+b_2)\\) Output Calculation \\(o^{(t)}=\\text{sigmoid}\\ \\big(Vs^{(t)}+c\\big)\\)"},{"location":"AI/CS231n/CS231n_notes/#example-image-captioning","title":"Example: Image Captioning","text":""},{"location":"AI/CS231n/CS231n_notes/#summary_2","title":"Summary","text":"Advantages of RNN:
Disadvantages of RNN:
Add a \"cell block\" to store history weights.
\\(c^{(t)}\\) : Cell at time \\(t\\).
\\(f^{(t)}\\) : Forget gate at time \\(t\\). Deciding whether to erase the cell.
\\(i^{(t)}\\) : Input gate at time \\(t\\). Deciding whether to write to the cell.
\\(g^{(t)}\\) : External input gate at time \\(t\\). Deciding how much to write to the cell.
\\(o^{(t)}\\) : Output gate at time \\(t\\). Deciding how much to reveal the cell.
Calculation (Gate) Forget Gate \\(f^{(t)}=\\text{sigmoid}\\ \\big(W_fh^{(t-1)}+U_fx^{(t)}+b_f\\big)\\) Input Gate \\(i^{(t)}=\\text{sigmoid}\\ \\big(W_ih^{(t-1)}+U_ix^{(t)}+b_i\\big)\\) External Input Gate \\(g^{(t)}=\\tanh(W_gh^{(t-1)}+U_gx^{(t)}+b_g)\\) Output Gate \\(o^{(t)}=\\text{sigmoid}\\ \\big(W_oh^{(t-1)}+U_ox^{(t)}+b_o\\big)\\) Calculation (Main) Cell Transition \\(c^{(t)}=f^{(t)}\\odot c^{(t-1)}+i^{(t)}\\odot g^{(t)}\\) State Transition \\(h^{(t)}=o^{(t)}\\odot\\tanh(c^{(t)})\\) Output Calculation \\(O^{(t)}=\\text{sigmoid}\\ \\big(Vh^{(t)}+c\\big)\\) "},{"location":"AI/CS231n/CS231n_notes/#other-rnn-variants","title":"Other RNN Variants","text":"GRU...
"},{"location":"AI/CS231n/CS231n_notes/#11-attention-and-transformers","title":"11 - Attention and Transformers","text":""},{"location":"AI/CS231n/CS231n_notes/#rnn-with-attention","title":"RNN with Attention","text":"Encoder-Decoder Sequence to Sequence RNN Problem:
Input sequence bottlenecked through a fixed-sized context vector \\(C\\). (e.g. \\(T=1000\\))
Intuitive Solution:
Generate new context vector \\(C_t\\) at each step \\(t\\) !
\\(e_{t,i}\\) : Alignment score for input \\(i\\) at state \\(t\\). (scalar)
\\(a_{t,i}\\) : Attention weight for input \\(i\\) at state \\(t\\).
\\(C_t\\) : Context vector at state \\(t\\).
Calculation Alignment Score \\(e_i^{(t)}=f(s^{(t-1)},h^{(i)})\\).Where \\(f\\) is an MLP. Attention Weight \\(a_i^{(t)}=\\text{softmax}\\ (e_i^{(t)})\\).Softmax includes all \\(e_i\\) at state \\(t\\). Context Vector \\(C^{(t)}=\\sum_i a_i^{(t)}h^{(i)}\\) Decoder State Transition \\(s^{(t)}=\\tanh(Ws^{(t-1)}+Uy^{(t)}+TC^{(t)}+b)\\)Example on Image Captioning:
"},{"location":"AI/CS231n/CS231n_notes/#general-attention-layer","title":"General Attention Layer","text":"Add linear transformations to the input vector before attention.
Notice:
Each \\(y\\) is a linear weighting of values \\(v\\).
The query vectors \\(q\\) are also generated from the inputs.
In this way, the shape of \\(y\\) is equal to the shape of \\(x\\).
Example with CNN:
"},{"location":"AI/CS231n/CS231n_notes/#positional-encoding","title":"Positional Encoding","text":"Self-attention layer doesn\u2019t care about the orders of the inputs!
To encode ordered sequences like language or spatially ordered image features, we can add positional encoding to the inputs.
We use a function \\(P:R\\rightarrow R^d\\) to process the position \\(i\\) into a d-dimensional vector \\(p_i=P(i)\\).
Constraint Condition of \\(P\\) Uniqueness \\(P(i)\\ne P(j)\\) Equidistance \\(\\lVert P(i+k)-P(i)\\rVert^2=\\lVert P(j+k)-P(j)\\rVert^2\\) Boundness \\(P(i)\\in[a,b]\\) Determinacy \\(P(i)\\) is always a static value. (function is not dynamic)We can either train a encoder model, or design a fixed function.
A Practical Positional Encoding Method: Using \\(\\sin\\) and \\(\\cos\\) with different frequency \\(\\omega\\) at different dimension.
\\(P(t)=\\begin{bmatrix}\\sin(\\omega_1,t)\\\\\\cos(\\omega_1,t)\\\\\\\\\\sin(\\omega_2,t)\\\\\\cos(\\omega_2,t)\\\\\\vdots\\\\\\sin(\\omega_{\\frac{d}{2}},t)\\\\\\cos(\\omega_{\\frac{d}{2}},t)\\end{bmatrix}\\), where frequency \\(\\omega_k=\\frac{1}{10000^{\\frac{2k}{d}}}\\\\\\). (wave length \\(\\lambda=\\frac{1}{\\omega}=10000^{\\frac{2k}{d}}\\\\\\))
\\(P(t)=\\begin{bmatrix}\\sin(1/10000^{\\frac{2}{d}},t)\\\\\\cos(1/10000^{\\frac{2}{d}},t)\\\\\\\\\\sin(1/10000^{\\frac{4}{d}},t)\\\\\\cos(1/10000^{\\frac{4}{d}},t)\\\\\\vdots\\\\\\sin(1/10000^1,t)\\\\\\cos(1/10000^1,t)\\end{bmatrix}\\), after we substitute \\(\\omega_k\\) into the equation.
\\(P(t)\\) is a vector with size \\(d\\), where \\(d\\) is a hyperparameter to choose according to the length of input sequence.
An intuition of this method is the binary encoding of numbers.
[lecture 11d] \u6ce8\u610f\u529b\u548ctransformer (positional encoding \u8865\u5145\uff0c\u4ee3\u7801\u5b9e\u73b0\uff0c\u8ddd\u79bb\u8ba1\u7b97)
It is easy to prove that \\(P(t)\\) satisfies \"Equidistance\": (set \\(d=2\\) for example)
\\(\\begin{aligned}\\lVert P(i+k)-P(i)\\rVert^2&=\\big[\\sin(\\omega_1,i+k)-\\sin(\\omega_1,i)\\big]^2+\\big[\\cos(\\omega_1,i+k)-\\cos(\\omega_1,i)\\big]^2\\\\&=2-2\\sin(\\omega_1,i+k)\\sin(\\omega_1,i)-2\\cos(\\omega_1,i+k)\\cos(\\omega_1,i)\\\\&=2-2\\cos(\\omega_1,k)\\end{aligned}\\)
So the distance is not associated with \\(i\\), we have \\(\\lVert P(i+k)-P(i)\\rVert^2=\\lVert P(j+k)-P(j)\\rVert^2\\).
Visualization of \\(P(t)\\) features: (set \\(d=32\\), \\(x\\) axis represents the position of sequence)
"},{"location":"AI/CS231n/CS231n_notes/#masked-self-attention-layer","title":"Masked Self-attention Layer","text":"To prevent vectors from looking at future vectors, we manually set alignment scores to \\(-\\infty\\).
"},{"location":"AI/CS231n/CS231n_notes/#multi-head-self-attention-layer","title":"Multi-head Self-attention Layer","text":"Multiple self-attention heads in parallel.
"},{"location":"AI/CS231n/CS231n_notes/#transformer","title":"Transformer","text":"Attention Is All You Need
"},{"location":"AI/CS231n/CS231n_notes/#encoder-block","title":"Encoder Block","text":"Inputs: Set of vectors \\(z\\). (in which \\(z_i\\) can be a word in a sentence, or a pixel in a picture...)
Output: Set of context vectors \\(c\\). (encoded features of \\(z\\))
The number of blocks \\(N=6\\) in original paper.
Notice:
Inputs: Set of vectors \\(y\\). (\\(y_i\\) can be a word in a sentence, or a pixel in a picture...)
Inputs: Set of context vectors \\(c\\).
Output: Set of vectors \\(y'\\). (decoded result, \\(y'_i=y_{i+1}\\) for the first \\(n-1\\) number of \\(y'\\))
The number of blocks \\(N=6\\) in original paper.
Notice:
Why we need mask in decoder:
\u4e3e\u4e2a\u4f8b\u5b50\u8bb2\u4e0btransformer\u7684\u8f93\u5165\u8f93\u51fa\u7ec6\u8282\u53ca\u5176\u4ed6
\u5728\u6d4b\u8bd5\u6216\u8005\u9884\u6d4b\u65f6\uff0cTransformer\u91ccdecoder\u4e3a\u4ec0\u4e48\u8fd8\u9700\u8981seq mask\uff1f
"},{"location":"AI/CS231n/CS231n_notes/#example-on-image-captioning-only-with-transformers","title":"Example on Image Captioning (Only with Transformers)","text":""},{"location":"AI/CS231n/CS231n_notes/#comparing-rnns-to-transformer","title":"Comparing RNNs to Transformer","text":"RNNs Transformer Pros LSTMs work reasonably well for long sequences. 1. Good at long sequences. Each attention calculation looks at all inputs.2. Can operate over unordered sets or ordered sequences with positional encodings.3. Parallel computation: All alignment and attention scores for all inputs can be done in parallel. Cons 1. Expects an ordered sequences of inputs.2. Sequential computation: Subsequent hidden states can only be computed after the previous ones are done. Requires a lot of memory: \\(N\\times M\\) alignment and attention scalers need to be calculated and stored for a single self-attention head."},{"location":"AI/CS231n/CS231n_notes/#comparing-convnets-to-transformer","title":"Comparing ConvNets to Transformer","text":"ConvNets strike back!
"},{"location":"AI/CS231n/CS231n_notes/#12-video-understanding","title":"12 - Video Understanding","text":""},{"location":"AI/CS231n/CS231n_notes/#video-classification","title":"Video Classification","text":"Take video classification task for example.
Input size: \\(C\\times T\\times H\\times W\\).
The problem is, videos are quite big. We can't afford to train on raw videos, instead we train on video clips.
Raw Videos Video Clips \\(1920\\times1080,\\ 30\\text{fps}\\) \\(112\\times112,\\ 5\\text{f}/3.2\\text{s}\\) \\(10\\text{GB}/\\text{min}\\) \\(588\\text{KB}/\\text{min}\\) "},{"location":"AI/CS231n/CS231n_notes/#plain-cnn-structure","title":"Plain CNN Structure","text":""},{"location":"AI/CS231n/CS231n_notes/#single-frame-2d-cnn","title":"Single Frame 2D-CNN","text":"Train a normal 2D-CNN model.
Classify each frame independently.
Average the result of each frame as the final result.
"},{"location":"AI/CS231n/CS231n_notes/#late-fusion","title":"Late Fusion","text":"Get high-level appearance of each frame, and combine them.
Run 2D-CNN on each frame, pool features and feed to Linear Layers.
Problem: Hard to compare low-level motion between frames.
"},{"location":"AI/CS231n/CS231n_notes/#early-fusion","title":"Early Fusion","text":"Compare frames with very first Conv Layer, after that normal 2D-CNN.
Problem: One layer of temporal processing may not be enough!
"},{"location":"AI/CS231n/CS231n_notes/#3d-cnn","title":"3D-CNN","text":"Convolve on 3 dimensions: Height, Width, Time.
Input size: \\(C_{in}\\times T\\times H\\times W\\).
Kernel size: \\(C_{in}\\times C_{out}\\times 3\\times 3\\times 3\\).
Output size: \\(C_{out}\\times T\\times H\\times W\\). (with zero paddling)
"},{"location":"AI/CS231n/CS231n_notes/#c3d-vgg-of-3d-cnns","title":"C3D (VGG of 3D-CNNs)","text":"The cost is quite expensive...
Network Calculation AlexNet 0.7 GFLOP VGG-16 13.6 GFLOP C3D 39.5 GFLOP"},{"location":"AI/CS231n/CS231n_notes/#two-stream-networks","title":"Two-Stream Networks","text":"Separate motion and appearance.
"},{"location":"AI/CS231n/CS231n_notes/#i3d-inflating-2d-networks-to-3d","title":"I3D (Inflating 2D Networks to 3D)","text":"Take a 2D-CNN architecture.
Replace each 2D conv/pool layer with a 3D version.
"},{"location":"AI/CS231n/CS231n_notes/#modeling-long-term-temporal-structure","title":"Modeling Long-term Temporal Structure","text":""},{"location":"AI/CS231n/CS231n_notes/#recurrent-convolutional-network","title":"Recurrent Convolutional Network","text":"Similar to multi-layer RNN, we replace the dot-product operation with convolution.
Feature size in layer \\(L\\), time \\(t-1\\): \\(W_h\\times H\\times W\\).
Feature size in layer \\(L-1\\), time \\(t\\): \\(W_x\\times H\\times W\\).
Feature size in layer \\(L\\), time \\(t\\): \\((W_h+W_x)\\times H\\times W\\).
Problem: RNNs are slow for long sequences. (can\u2019t be parallelized)
"},{"location":"AI/CS231n/CS231n_notes/#spatio-temporal-self-attention","title":"Spatio-temporal Self-attention","text":"Introduce self-attention into video classification problems.
"},{"location":"AI/CS231n/CS231n_notes/#vision-transformers-for-video","title":"Vision Transformers for Video","text":"Factorized attention: Attend over space / time.
So many papers...
"},{"location":"AI/CS231n/CS231n_notes/#visualizing-video-models","title":"Visualizing Video Models","text":""},{"location":"AI/CS231n/CS231n_notes/#multimodal-video-understanding","title":"Multimodal Video Understanding","text":""},{"location":"AI/CS231n/CS231n_notes/#temporal-action-localization","title":"Temporal Action Localization","text":"Given a long untrimmed video sequence, identify frames corresponding to different actions.
"},{"location":"AI/CS231n/CS231n_notes/#spatio-temporal-detection","title":"Spatio-Temporal Detection","text":"Given a long untrimmed video, detect all the people in both space and time and classify the activities they are performing.
"},{"location":"AI/CS231n/CS231n_notes/#visually-guided-audio-source-separation","title":"Visually-guided Audio Source Separation","text":"And So on...
"},{"location":"AI/CS231n/CS231n_notes/#13-generative-models","title":"13 - Generative Models","text":""},{"location":"AI/CS231n/CS231n_notes/#pixelrnn-and-pixelcnn","title":"PixelRNN and PixelCNN","text":""},{"location":"AI/CS231n/CS231n_notes/#fully-visible-belief-network-fvbn","title":"Fully Visible Belief Network (FVBN)","text":"\\(p(x)\\) : Likelihood of image \\(x\\).
\\(p(x_1,x_2,\\dots,x_n)\\) : Joint likelihood of all \\(n\\) pixels in image \\(x\\).
\\(p(x_i|x_1,x_2,\\dots,x_{i-1})\\) : Probability of pixel \\(i\\) value given all previous pixels.
For explicit density models, we have \\(p(x)=p(x_1,x_2,\\dots,x_n)=\\prod_{i=1}^np(x_i|x_1,x_2,\\dots,x_{i-1})\\\\\\).
Objective: Maximize the likelihood of training data.
"},{"location":"AI/CS231n/CS231n_notes/#pixelrnn","title":"PixelRNN","text":"Generate image pixels starting from corner.
Dependency on previous pixels modeled using an RNN (LSTM).
Drawback: Sequential generation is slow in both training and inference!
"},{"location":"AI/CS231n/CS231n_notes/#pixelcnn","title":"PixelCNN","text":"Still generate image pixels starting from corner.
Dependency on previous pixels modeled using a CNN over context region (masked convolution).
Drawback: Though its training is faster, its generation is still slow. (pixel by pixel)
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder","title":"Variational Autoencoder","text":"Supplement content added according to Tutorial on Variational Autoencoders. (paper with notes: VAE Tutorial.pdf)
\u53d8\u5206\u81ea\u7f16\u7801\u5668VAE\uff1a\u539f\u6765\u662f\u8fd9\u4e48\u4e00\u56de\u4e8b | \u9644\u5f00\u6e90\u4ee3\u7801
"},{"location":"AI/CS231n/CS231n_notes/#autoencoder","title":"Autoencoder","text":"Learn a lower-dimensional feature representation with unsupervised approaches.
\\(x\\rightarrow z\\) : Dimension reduction for input features.
\\(z\\rightarrow \\hat{x}\\) : Reconstruct input features.
After training, we throw the decoder away and use the encoder for transferring.
For generative models, there is a problem:
We can\u2019t generate new images from an autoencoder because we don\u2019t know the space of \\(z\\).
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder_1","title":"Variational Autoencoder","text":""},{"location":"AI/CS231n/CS231n_notes/#character-description","title":"Character Description","text":"\\(X\\) : Images. (random variable)
\\(Z\\) : Latent representations. (random variable)
\\(P(X)\\) : True distribution of all training images \\(X\\).
\\(P(Z)\\) : True distribution of all latent representations \\(Z\\).
\\(P(X|Z)\\) : True posterior distribution of all images \\(X\\) with condition \\(Z\\).
\\(P(Z|X)\\) : True prior distribution of all latent representations \\(Z\\) with condition \\(X\\).
\\(Q(Z|X)\\) : Approximated prior distribution of all latent representations \\(Z\\) with condition \\(X\\).
\\(x\\) : A specific image.
\\(z\\) : A specific latent representation.
\\(\\theta\\): Learned parameters in decoder network.
\\(\\phi\\): Learned parameters in encoder network.
\\(p_\\theta(x)\\) : Probability that \\(x\\sim P(X)\\).
\\(p_\\theta(z)\\) : Probability that \\(z\\sim P(Z)\\).
\\(p_\\theta(x|z)\\) : Probability that \\(x\\sim P(X|Z)\\).
\\(p_\\theta(z|x)\\) : Probability that \\(z\\sim P(Z|X)\\).
\\(q_\\phi(z|x)\\) : Probability that \\(z\\sim Q(Z|X)\\).
"},{"location":"AI/CS231n/CS231n_notes/#decoder","title":"Decoder","text":"Objective:
Generate new images from \\(\\mathscr{z}\\).
Lemma:
Any distribution in \\(d\\) dimensions can be generated by taking a set of \\(d\\) variables that are normally distributed and mapping them through a sufficiently complicated function. (source: Tutorial on Variational Autoencoders, Page 6)
Solutions:
Objective:
Learn \\(\\mathscr{z}\\) with training images.
Given: (From the decoder, we can deduce the following probabilities.)
Problem:
Both \\(p_\\theta(x)\\) and \\(p_\\theta(z|x)\\) are intractable. (can't be optimized directly as they contain integral operation)
Solution:
Learn \\(Q(Z|X)\\) to approximate the true posterior \\(P(Z|X)\\).
Use \\(q_\\phi(z|x)\\) in place of \\(p_\\theta(z|x)\\).
"},{"location":"AI/CS231n/CS231n_notes/#variational-autoencoder-combination-of-encoder-and-decoder","title":"Variational Autoencoder (Combination of Encoder and Decoder)","text":"Objective:
Maximize \\(p_\\theta(x)\\) for all \\(x^{(i)}\\) in the training set.
$$ \\begin{aligned} \\log p_\\theta\\big(x^{(i)}\\big)&=\\mathbb{E}{z\\sim q\\phi\\big(z|x^{(i)}\\big)}\\Big[\\log p_\\theta\\big(x^{(i)}\\big)\\Big]\\
&=\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(x^{(i)}|z\\big)p_\\theta\\big(z\\big)}{p_\\theta\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Bayes' Rule)}\\
&=\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(x^{(i)}|z\\big)p_\\theta\\big(z\\big)}{p_\\theta\\big(z|x^{(i)}\\big)}\\frac{q_\\phi\\big(z|x^{(i)}\\big)}{q_\\phi\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Multiply by Constant)}\\
&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-\\mathbb{E}z\\Bigg[\\log\\frac{q\\phi\\big(z|x^{(i)}\\big)}{p_\\theta\\big(z\\big)}\\Bigg]+\\mathbb{E}z\\Bigg[\\log\\frac{p\\theta\\big(z|x^{(i)}\\big)}{q_\\phi\\big(z|x^{(i)}\\big)}\\Bigg]\\quad\\text{(Logarithm)}\\
&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]+D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\quad\\text{(KL Divergence)} \\end{aligned} $$
Analyze the Formula by Term:
\\(\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]\\): Decoder network gives \\(p_\\theta\\big(x^{(i)}|z\\big)\\), can compute estimate of this term through sampling.
\\(D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\): This KL term (between Gaussians for encoder and \\(z\\) prior) has nice closed-form solution!
\\(D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\): The part \\(p_\\theta\\big(z|x^{(i)}\\big)\\) is intractable. However, we know KL divergence always \\(\\ge0\\).
Tractable Lower Bound:
We can maximize the lower bound of that formula.
As \\(D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\ge0\\) , we can deduce that:
$$ \\begin{aligned} \\log p_\\theta\\big(x^{(i)}\\big)&=\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]+D_{\\text{KL}}\\Big[p_\\theta\\big(z|x^{(i)}\\big)||q_\\phi\\big(z|x^{(i)}\\big)\\Big]\\
&\\ge\\mathbb{E}z\\Big[\\log p\\theta\\big(x^{(i)}|z\\big)\\Big]-D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big] \\end{aligned} $$
So the loss function \\(\\mathcal{L}\\big(x^{(i)},\\theta,\\phi\\big)=-\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]+D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\).
\\(\\mathbb{E}_z\\Big[\\log p_\\theta\\big(x^{(i)}|z\\big)\\Big]\\): Decoder, reconstruct the input data.
\\(D_{\\text{KL}}\\Big[q_\\phi\\big(z|x^{(i)}\\big)||p_\\theta\\big(z\\big)\\Big]\\): Encoder, make approximate posterior distribution close to prior.
"},{"location":"AI/CS231n/CS231n_notes/#generative-adversarial-networks-gans","title":"Generative Adversarial Networks (GANs)","text":""},{"location":"AI/CS231n/CS231n_notes/#motivation-modeling","title":"Motivation & Modeling","text":"Objective: Not modeling any explicit density function.
Problem: Want to sample from complex, high-dimensional training distribution. No direct way to do this!
Solution: Sample from a simple distribution, e.g. random noise. Learn the transformation to training distribution.
Problem: We can't learn the mapping relation between sample \\(z\\) and training images.
Solution: Use a discriminator network to tell whether the generate image is within data distribution or not.
Discriminator network: Try to distinguish between real and fake images.
Generator network: Try to fool the discriminator by generating real-looking images.
\\(x\\) : Real data.
\\(y\\) : Fake data, which is generated by the generator network. \\(y=G_{\\theta_g}(z)\\).
\\(D_{\\theta_d}(x)\\) : Discriminator score, which is the likelihood of real image. \\(D_{\\theta_d}(x)\\in[0,1]\\).
Objective of discriminator network:
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
Objective of generator network:
\\(\\min_{\\theta_g}\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
"},{"location":"AI/CS231n/CS231n_notes/#training-strategy","title":"Training Strategy","text":"Two combine this two networks together, we can train them alternately:
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
\\(\\min_{\\theta_g}\\bigg[\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
However, the gradient of generator decreases with the value itself, making it hard to optimize.
So we replace \\(\\log\\big(1-D_{\\theta_d}(y)\\big)\\) with \\(-\\log D_{\\theta_d}(y)\\), and use gradient ascent instead.
\\(\\max_{\\theta_d}\\bigg[\\mathbb{E}_x\\Big(\\log D_{\\theta_d}(x)\\Big)+\\mathbb{E}_{z\\sim p(z)}\\Big(\\log\\big(1-D_{\\theta_d}(y)\\big)\\Big)\\bigg]\\)
\\(\\max_{\\theta_g}\\bigg[\\mathbb{E}_{z\\sim p(z)}\\Big(\\log D_{\\theta_d}(y)\\Big)\\bigg]\\)
"},{"location":"AI/CS231n/CS231n_notes/#summary_3","title":"Summary","text":"Pros: Beautiful, state-of-the-art samples!
Cons:
Aim: Solve \u201cpretext\u201d tasks that produce good features for downstream tasks.
Application:
Labels are generated automatically.
"},{"location":"AI/CS231n/CS231n_notes/#rotation","title":"Rotation","text":"Train a classifier on randomly rotated images.
"},{"location":"AI/CS231n/CS231n_notes/#rearrangement","title":"Rearrangement","text":"Train a classifier on randomly shuffled image pieces.
Predict the location of image pieces.
"},{"location":"AI/CS231n/CS231n_notes/#inpainting","title":"Inpainting","text":"Mask part of the image, train a network to predict the masked area.
Method referencing Context Encoders: Feature Learning by Inpainting.
Combine two types of loss together to get better performance:
Transfer between greyscale images and colored images.
Cross-channel predictions for images: Split-Brain Autoencoders.
Video coloring: Establish mappings between reference and target frames in a learned feature space. Tracking Emerges by Colorizing Videos.
"},{"location":"AI/CS231n/CS231n_notes/#summary-for-pretext-tasks","title":"Summary for Pretext Tasks","text":"What we care is the performance of downstream tasks.
"},{"location":"AI/CS231n/CS231n_notes/#problems-of-specific-pretext-tasks","title":"Problems of Specific Pretext Tasks","text":"Intuitive Solution: Contrastive Learning.
"},{"location":"AI/CS231n/CS231n_notes/#contrastive-representation-learning","title":"Contrastive Representation Learning","text":"Local additional references: Contrastive Learning.md.
Objective:
Given a chosen score function \\(s\\), we aim to learn an encoder function \\(f\\) that yields:
Loss Function:
Given \\(1\\) positive sample and \\(N-1\\) negative samples:
InfoNCE Loss Cross Entropy Loss \\(\\begin{aligned}\\mathcal{L}=-\\mathbb{E}_X\\Bigg[\\log\\frac{\\exp{s\\big(f(x),f(x^+)\\big)}}{\\exp{s\\big(f(x),f(x^+)\\big)}+\\sum_{j=1}^{N-1}\\exp{s\\big(f(x),f(x^+)\\big)}}\\Bigg]\\\\\\end{aligned}\\) \\(\\begin{aligned}\\mathcal{L}&=-\\sum_{i=1}^Np(x_i)\\log q(x_i)\\\\&=-\\mathbb{E}_X\\big[\\log q(x)\\big]\\\\&=-\\mathbb{E}_X\\Bigg[\\log\\frac{\\exp(x)}{\\sum_{j=1}^N\\exp(x_j)}\\Bigg]\\end{aligned}\\)The InfoNCE Loss is a lower bound on the mutual information between \\(f(x)\\) and \\(f(x^+)\\):
\\(\\text{MI}\\big[f(x),f(x^+)\\big]\\ge\\log(N)-\\mathcal{L}\\)
The larger the negative sample size \\(N\\), the tighter the bound.
So we use \\(N-1\\) negative samples.
"},{"location":"AI/CS231n/CS231n_notes/#instance-contrastive-learning","title":"Instance Contrastive Learning","text":""},{"location":"AI/CS231n/CS231n_notes/#simclr","title":"SimCLR","text":"Use a projection function \\(g(\\cdot)\\) to project features to a space where contrastive learning is applied.
The extra projection contributes a lot to the final performance.
Score Function: Cos similarity \\(s(u,v)=\\frac{u^Tv}{||u||||v||}\\\\\\).
Positive Pair: Pair of augmented data.
"},{"location":"AI/CS231n/CS231n_notes/#momentum-contrastive-learning-moco","title":"Momentum Contrastive Learning (MoCo)","text":"There are mainly \\(3\\) training strategy in contrastive learning:
(limited by GPU size)
(inconsistency between \\(q\\) and \\(k\\))
(combination of end-to-end & memory bank)
Key differences to SimCLR:
\\(\\theta_k\\leftarrow m\\theta_k+(1-m)\\theta_q\\)
"},{"location":"AI/CS231n/CS231n_notes/#sequence-contrastive-learning","title":"Sequence Contrastive Learning","text":""},{"location":"AI/CS231n/CS231n_notes/#contrastive-predictive-coding-cpc","title":"Contrastive Predictive Coding (CPC)","text":"Contrastive: Contrast between \u201cright\u201d and \u201cwrong\u201d sequences using contrastive learning.
Predictive: The model has to predict future patterns given the current context.
Coding: The model learns useful feature vectors, or \u201ccode\u201d, for downstream tasks, similar to other self-supervised methods.
"},{"location":"AI/CS231n/CS231n_notes/#other-examples-frontier","title":"Other Examples (Frontier)","text":""},{"location":"AI/CS231n/CS231n_notes/#contrastive-language-image-pre-training-clip","title":"Contrastive Language Image Pre-training (CLIP)","text":"Contrastive learning between image and natural language sentences.
"},{"location":"AI/CS231n/CS231n_notes/#15-low-level-vision","title":"15 - Low-Level Vision","text":"Pass...
"},{"location":"AI/CS231n/CS231n_notes/#16-3d-vision","title":"16 - 3D Vision","text":""},{"location":"AI/CS231n/CS231n_notes/#representation","title":"Representation","text":""},{"location":"AI/CS231n/CS231n_notes/#explicit-vs-implicit","title":"Explicit vs Implicit","text":"Explicit: Easy to sample examples, hard to do inside/outside check.
Implicit: Hard to sample examples, easy to do inside/outside check.
Non-parametric Parametric Explicit Points.Meshes. Splines.Subdivision Surfaces. Implicit Level Sets.Voxels. Algebraic Surfaces.Constructive Solid Geometry."},{"location":"AI/CS231n/CS231n_notes/#point-clouds","title":"Point Clouds","text":"The simplest representation.
Collection of \\((x,y,z)\\) coordinates.
Cons:
Collection of vertices \\(v\\) and edges \\(e\\).
Pros:
Use specific functions to approximate the surface. (e.g. B\u00e9zier Curves)
"},{"location":"AI/CS231n/CS231n_notes/#algebraic-surfaces","title":"Algebraic Surfaces","text":"Use specific functions to represent the surface.
"},{"location":"AI/CS231n/CS231n_notes/#constructive-solid-geometry","title":"Constructive Solid Geometry","text":"Combine implicit geometry with Boolean operations.
"},{"location":"AI/CS231n/CS231n_notes/#level-sets","title":"Level Sets","text":"Store a grim of values to approximate the function.
Surface is found where interpolated value equals to \\(0\\).
"},{"location":"AI/CS231n/CS231n_notes/#voxels","title":"Voxels","text":"Binary thresholding the volumetric grid.
"},{"location":"AI/CS231n/CS231n_notes/#ai-3d","title":"AI + 3D","text":"Pass...
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/","title":"Image Classification-Data-driven Approach, k-Nearest Neighbor, train_val_test splits","text":""},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#image-classification-data-driven-approach-k-nearest-neighbor-train_val_test-splits","title":"Image Classification-Data-driven Approach, k-Nearest Neighbor, train_val_test splits","text":"\u7ea6 651 \u4e2a\u5b57 28 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#image-classification","title":"image classification","text":"import numpy as np\n\nclass NearestNeighbor(object): \n def **init**(self): \n pass\n\n def train(self, X, y): \n \"\"\" X is N x D where each row is an example. Y is 1-dimension of size N \"\"\" \n # the nearest neighbor classifier simply remembers all the training data \n self.Xtr = X \n self.ytr = y\n\n def predict(self, X): \n \"\"\" X is N x D where each row is an example we wish to predict label for \"\"\" \n num_test = X.shape[0] \n # lets make sure that the output type matches the input type \n Ypred = np.zeros(num_test, dtype = self.ytr.dtype)\n\n # loop over all test rows\n for i in range(num_test):\n # find the nearest training image to the i'th test image\n # using the L1 distance (sum of absolute value differences)\n distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)\n min_index = np.argmin(distances) # get the index with smallest distance\n Ypred[i] = self.ytr[min_index] # predict the label of the nearest example\n\n return Ypred\n
\\[ d_2 (I_1, I_2) = \\sqrt{\\sum_{p} \\left( I^p_1 - I^p_2 \\right)^2} \\] Pythondistances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))\n
"},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#k-nearest-neighbor-classifier","title":"k - Nearest Neighbor Classifier","text":""},{"location":"AI/CS231n/Image%20Classification-Data-driven%20Approach%2C%20k-Nearest%20Neighbor%2C%20train_val_test%20splits/#validation-sets-for-hyperparameter-tuning","title":"Validation sets for Hyperparameter tuning","text":"Evaluate on the test only a single time, at the very end
Split your training set into training set and a validation set. Use validation set to tune all hyperparameters. At the end run a single time on the test set and report performance.
As an aside, the computational complexity of the Nearest Neighbor classifier is an active area of research, and several\u00a0Approximate Nearest Neighbor\u00a0(ANN) algorithms and libraries exist that can accelerate the nearest neighbor lookup in a dataset (e.g.\u00a0FLANN). These algorithms allow one to trade off the correctness of the nearest neighbor retrieval with its space/time complexity during retrieval, and usually rely on a pre-processing/indexing stage that involves building a kdtree, or running the k-means algorithm.
In particular, note that images that are nearby each other are much more a function of the general color distribution of the images, or the type of background rather than their semantic identity.
Applying kNN in practicemore about Machine Learing
"},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/","title":"Linear classification-Support Vector Machine, Softmax","text":""},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/#linear-classification-support-vector-machine-softmax","title":"Linear classification-Support Vector Machine, Softmax","text":"\u7ea6 126 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Linear%20classification-Support%20Vector%20Machine%2C%20Softmax/#linear-classifiaction","title":"Linear Classifiaction","text":"\\[ L_i = \\sum_{j\\neq y_i} \\max(0, s_j - s_{y_i} + \\Delta) \\] \\[ L = \\frac{1}{N} \\sum_i \\sum_{j\\neq y_i} \\left[ \\max(0, f(x_i; W)_j - f(x_i; W)_{y_i} + \\Delta) \\right] + \\lambda \\sum_k\\sum_l W_{k,l}^2 \\] \\[ L_i = -\\log\\left(\\frac{e^{f_{y_i}}}{ \\sum_j e^{f_j} }\\right) \\hspace{0.5in} \\text{or equivalently} \\hspace{0.5in} L_i = -f_{y_i} + \\log\\sum_j e^{f_j} \\] \\[ \\frac{e^{f_{y_i}}}{\\sum_j e^{f_j}} = \\frac{Ce^{f_{y_i}}}{C\\sum_j e^{f_j}} = \\frac{e^{f_{y_i} + \\log C}}{\\sum_j e^{f_j + \\log C}} \\]"},{"location":"AI/CS231n/Numpy/","title":"Numpy","text":""},{"location":"AI/CS231n/Numpy/#python","title":"Python","text":"\u7ea6 49 \u4e2a\u5b57 104 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/CS231n/Numpy/#string","title":"string","text":"Pythons = \"hello\"\nprint(s.capitalize()) # Capitalize a string; prints \"Hello\"\nprint(s.upper()) # Convert a string to uppercase; prints \"HELLO\"\nprint(s.rjust(7)) # Right-justify a string, padding with spaces; prints \" hello\"\nprint(s.center(7)) # Center a string, padding with spaces; prints \" hello \"\nprint(s.replace('l', '(ell)')) # Replace all instances of one substring with another;\n # prints \"he(ell)(ell)o\"\nprint(' world '.strip()) # Strip leading and trailing whitespace; prints \"world\"\n
"},{"location":"AI/CS231n/Numpy/#containers","title":"Containers","text":"Pythonanimals = ['cat', 'dog', 'monkey']\nfor idx, animal in enumerate(animals):\n print('#%d: %s' % (idx + 1, animal))\n# Prints \"#1: cat\", \"#2: dog\", \"#3: monkey\", each on its own line\n
\u5217\u8868\u63a8\u5bfc\u5f0f
Pythonnums = [0, 1, 2, 3, 4]\neven_squares = [x ** 2 for x in nums if x % 2 == 0]\nprint(even_squares) # Prints \"[0, 4, 16]\"\n
\u540c\u6837\u4e5f\u6709\u5b57\u5178\u63a8\u5bfc\u5f0f
Tuples \u53ef\u4ee5\u7528\u4f5c\u5b57\u5178\u4e2d\u7684\u952e\u548c\u96c6\u5408\u7684\u5143\u7d20\uff0c\u4f46\u662f lists \u4e0d\u80fd
"},{"location":"AI/CS231n/Numpy/#numpy","title":"Numpy","text":"Pythonimport numpy as np\n\n# Create a new array from which we will select elements\na = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n\nprint(a) # prints \"array([[ 1, 2, 3],\n # [ 4, 5, 6],\n # [ 7, 8, 9],\n # [10, 11, 12]])\"\n\n# Create an array of indices\nb = np.array([0, 2, 0, 1])\n\n# Select one element from each row of a using the indices in b\nprint(a[np.arange(4), b]) # Prints \"[ 1 6 7 11]\"\n\n# Mutate one element from each row of a using the indices in b\na[np.arange(4), b] += 10\n\nprint(a) # prints \"array([[11, 2, 3],\n # [ 4, 5, 16],\n # [17, 8, 9],\n # [10, 21, 12]])\n
Pythonimport numpy as np\n\na = np.array([[1,2], [3, 4], [5, 6]])\n\nbool_idx = (a > 2) # Find the elements of a that are bigger than 2;\n # this returns a numpy array of Booleans of the same\n # shape as a, where each slot of bool_idx tells\n # whether that element of a is > 2.\n\nprint(bool_idx) # Prints \"[[False False]\n # [ True True]\n # [ True True]]\"\n\n# We use boolean array indexing to construct a rank 1 array\n# consisting of the elements of a corresponding to the True values\n# of bool_idx\nprint(a[bool_idx]) # Prints \"[3 4 5 6]\"\n\n# We can do all of the above in a single concise statement:\nprint(a[a > 2]) # Prints \"[3 4 5 6]\"\n
Pythonx = np.array([1, 2], dtype=np.int64) # Force a particular datatype\nprint(x.dtype) # Prints \"int64\"\n
Pythonimport numpy as np\n\nx = np.array([[1,2],[3,4]], dtype=np.float64)\ny = np.array([[5,6],[7,8]], dtype=np.float64)\n\n# Elementwise sum; both produce the array\n# [[ 6.0 8.0]\n# [10.0 12.0]]\nprint(x + y)\nprint(np.add(x, y))\n\n# Elementwise difference; both produce the array\n# [[-4.0 -4.0]\n# [-4.0 -4.0]]\nprint(x - y)\nprint(np.subtract(x, y))\n\n# Elementwise product; both produce the array\n# [[ 5.0 12.0]\n# [21.0 32.0]]\nprint(x * y)\nprint(np.multiply(x, y))\n\n# Elementwise division; both produce the array\n# [[ 0.2 0.33333333]\n# [ 0.42857143 0.5 ]]\nprint(x / y)\nprint(np.divide(x, y))\n\n# Elementwise square root; produces the array\n# [[ 1. 1.41421356]\n# [ 1.73205081 2. ]]\nprint(np.sqrt(x))\n
\u5e7f\u64ad\u53ef\u4ee5\u907f\u514d\u5faa\u73af
Pythonimport numpy as np\n\n# We will add the vector v to each row of the matrix x,\n# storing the result in the matrix y\nx = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\nv = np.array([1, 0, 1])\ny = x + v # Add v to each row of x using broadcasting\nprint(y) # Prints \"[[ 2 2 4]\n # [ 5 5 7]\n # [ 8 8 10]\n # [11 11 13]]\"\n
"},{"location":"AI/CS231n/Numpy/#scipy","title":"SciPy","text":""},{"location":"AI/CS231n/Numpy/#matplotlib","title":"Matplotlib","text":""},{"location":"AI/EECS%20498-007/KNN/","title":"KNN","text":"\u5bf9\u4e8e\u4e00\u4e2a\u5f85\u5206\u7c7b\u7684\u6837\u672c\uff0c\u627e\u5230\u8bad\u7ec3\u6570\u636e\u96c6\u4e2d\u4e0e\u5176\u6700\u63a5\u8fd1\u7684K\u4e2a\u6837\u672c\uff08\u5373\u6700\u8fd1\u90bb\uff09\uff0c\u7136\u540e\u6839\u636e\u8fd9K\u4e2a\u6837\u672c\u7684\u7c7b\u522b\u6765\u51b3\u5b9a\u5f85\u5206\u7c7b\u6837\u672c\u7684\u7c7b\u522b\u3002
\u7ea6 374 \u4e2a\u5b57 100 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/EECS%20498-007/KNN/#_1","title":"\u6570\u5b66\u63a8\u5bfc","text":"\u5047\u8bbe\u6211\u4eec\u6709\u4e00\u4e2a\u8bad\u7ec3\u6570\u636e\u96c6 \\(T = \\{(x_1, y_1), (x_2, y_2), \\ldots, (x_N, y_N)\\}\\)\uff0c\u5176\u4e2d \\(x_i\\) \u662f\u7279\u5f81\u5411\u91cf\uff0c \\(y_i\\) \u662f\u5bf9\u5e94\u7684\u7c7b\u522b\u6807\u7b7e\u3002\u5bf9\u4e8e\u4e00\u4e2a\u65b0\u7684\u5f85\u5206\u7c7b\u6837\u672c x\uff0cKNN\u7b97\u6cd5\u7684\u76ee\u6807\u662f\u9884\u6d4b\u5176\u7c7b\u522b \\(y\\) \u3002
\u5176\u4e2d\uff0c \\(d\\) \u662f\u7279\u5f81\u7684\u7ef4\u5ea6\u3002
\u5176\u4e2d\uff0c \\(I\\) \u662f\u6307\u793a\u51fd\u6570\uff0c\u5f53 \\(y_i = c_j\\) \u65f6\u53d6\u503c\u4e3a1\uff0c\u5426\u5219\u4e3a0\u3002
"},{"location":"AI/EECS%20498-007/KNN/#_2","title":"\u4f5c\u4e1a\u4e2d\u7684\u5b9e\u73b0","text":"Pythonimport torch\n\ndef compute_distances_two_loops(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n for i in range(num_train):\n for j in range(num_test):\n dists[i,j] = ((x_train[i] - x_test[j]) ** 2).sum() ** (1/2)\n\n return dists\n\ndef compute_distances_one_loop(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n for i in range(num_train):\n dists[i] = ((x_train[i] - x_test) ** 2).sum(dim=(1,2,3)) ** (1/2)\n\n return dists\n\ndef compute_distances_no_loops(x_train, x_test):\n num_train = x_train.shape[0]\n num_test = x_test.shape[0]\n dists = x_train.new_zeros(num_train, num_test)\n\n A = x_train.reshape(num_train, -1)\n B = x_test.reshape(num_test, -1)\n AB2 = A.mm(B.T) * 2\n dists = ((A ** 2).sum(dim=1).reshape(-1, 1) - AB2 + (B ** 2).sum(dim=1).reshape(1, -1)) ** (1/2)\n\n return dists\n\ndef predict_labels(dists, y_train, k=1):\n num_train, num_test = dists.shape\n y_pred = torch.zeros(num_test, dtype=torch.int64)\n\n values, indices = torch.topk(dists, k, dim=0, largest=False)\n for i in range(indices.shape[1]):\n _, idx = torch.max(y_train[indices[:, i]].bincount(), dim=0)\n y_pred[i] = idx\n\n return y_pred\n\nclass KnnClassifier:\n def __init__(self, x_train, y_train):\n self.x_train = x_train\n self.y_train = y_train\n\n def predict(self, x_test, k=1):\n dists = compute_distances_no_loops(self.x_train, x_test)\n y_test_pred = predict_labels(dists, self.y_train, k)\n return y_test_pred\n\n def check_accuracy(self, x_test, y_test, k=1, quiet=False):\n y_test_pred = self.predict(x_test, k=k)\n num_samples = x_test.shape[0]\n num_correct = (y_test == y_test_pred).sum().item()\n accuracy = 100.0 * num_correct / num_samples\n msg = (f'Got {num_correct} / {num_samples} correct; accuracy is {accuracy:.2f}%')\n if not quiet:\n print(msg)\n return accuracy\n\ndef knn_cross_validate(x_train, y_train, num_folds=5, k_choices=None):\n if k_choices is None:\n k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]\n\n x_train_folds = torch.chunk(x_train, num_folds, dim=0)\n y_train_folds = torch.chunk(y_train, num_folds, dim=0)\n\n k_to_accuracies = {}\n\n for k in k_choices:\n list_of_acc = []\n for num_fold in range(num_folds):\n x_train_folds_local = [x for x in x_train_folds]\n y_train_folds_local = [x for x in y_train_folds]\n x_test = x_train_folds_local[num_fold]\n y_test = y_train_folds_local[num_fold]\n del x_train_folds_local[num_fold]\n del y_train_folds_local[num_fold]\n x_train = torch.cat(x_train_folds_local, dim=0)\n y_train = torch.cat(y_train_folds_local, dim=0)\n classifier = KnnClassifier(x_train, y_train)\n list_of_acc.append(classifier.check_accuracy(x_test, y_test, k))\n k_to_accuracies[k] = list_of_acc\n\n return k_to_accuracies\n\ndef knn_get_best_k(k_to_accuracies):\n best_k = 0\n new_dict = {}\n for k, accs in sorted(k_to_accuracies.items()):\n new_dict[k] = sum(accs) / len(accs) \n max_value = max(new_dict.values())\n best_k = [k for k, v in new_dict.items() if v == max_value][0]\n return best_k\n
"},{"location":"AI/EECS%20498-007/Pytorch/","title":"pytorch \u7684\u57fa\u672c\u4f7f\u7528","text":""},{"location":"AI/EECS%20498-007/Pytorch/#pytorch","title":"pytorch \u7684\u57fa\u672c\u4f7f\u7528","text":"\u7ea6 564 \u4e2a\u5b57 45 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
Python# Create a rank 1 tensor from a Python list\na = torch.tensor([[1, 2, 3], [4, 5, 6]])\nprint('Here is a:')\nprint(a)\nprint('type(a): ', type(a))\nprint('rank of a: ', a.dim())\nprint('a.shape: ', a.shape)\n\ntorch.zeros(2, 3)\ntorch.ones(2, 3)\ntorch.eye(3)\ntorch.rand(2, 3)\ntorch.full((M, N), 3.14)\n\ny2 = torch.tensor([1, 2], dtype=torch.int64)\nprint(y2.dtype)\n\nx3 = x0.to(torch.float32)\n\nx0 = torch.eye(3, dtype=torch.float64) \u00a0# Shape (3, 3), dtype torch.float64\nx1 = torch.zeros_like(x0) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Shape (3, 3), dtype torch.float64\nx2 = x0.new_zeros(4, 5) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Shape (4, 5), dtype torch.float64\nx3 = torch.ones(6, 7).to(x0) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# Shape (6, 7), dtype torch.float64\n
Even though PyTorch provides a large number of numeric datatypes, the most commonly used datatypes are:
torch.float32
: Standard floating-point type; used to store learnable parameters, network activations, etc. Nearly all arithmetic is done using this type.torch.int64
: Typically used to store indicestorch.bool
: Stores boolean values: 0 is false and 1 is truetorch.float16
: Used for mixed-precision arithmetic, usually on NVIDIA GPUs with tensor cores. You won't need to worry about this datatype in this course.a[:, 1]
\u548c a[:, 1:2]
\u7684\u533a\u522b\uff0c\u540e\u8005\u4f1a\u4fdd\u7559\u7684\u591a\u4e00\u70b9clone()
\u4ee5\u540e\u7684\u53d8\u91cf\u8ddf\u539f\u53d8\u91cf\u662f\u72ec\u7acb\u7684\uff0c\u4f46\u662f\u7b49\u53f7\u76f4\u63a5\u8d4b\u503c\u7684\u662f\u540c\u4e00\u4e2a\u6307\u9488mask = (a > 3)\nprint('\\nMask tensor:')\nprint(mask)\n# Mask tensor: tensor([[False, False], [False, True], [ True, True]])\n
.view()
shares the same data as the input, so changes to one will affect the other.view
\u8981\u6c42\u539f\u59cb\u5f20\u91cf\u548c\u76ee\u6807\u5f20\u91cf\u5728\u5185\u5b58\u4e2d\u662f\u8fde\u7eed\u7684\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0c view
\u4f1a\u9996\u5148\u8c03\u7528 contiguous
\u65b9\u6cd5\u4f7f\u5176\u8fde\u7eed\uff0c\u7136\u540e\u6539\u53d8\u5f62\u72b6\u3002\u5982\u679c\u5f20\u91cf\u5df2\u7ecf\u662f\u8fde\u7eed\u7684\uff0c view
\u64cd\u4f5c\u4e0d\u4f1a\u590d\u5236\u6570\u636e\u3002reshape
\u4e0d\u8981\u6c42\u539f\u59cb\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0creshape
\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\u5e76\u590d\u5236\u6570\u636e\uff0c\u4ee5\u786e\u4fdd\u65b0\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002view
\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\uff0c\u5b83\u4e0e\u539f\u59cb\u5f20\u91cf\u5171\u4eab\u76f8\u540c\u7684\u6570\u636e\uff0c\u4f46\u662f\u6709\u4e0d\u540c\u7684\u5f62\u72b6\u3002\u5982\u679c\u539f\u59cb\u5f20\u91cf\u4e0d\u662f\u8fde\u7eed\u7684\uff0cview
\u4f1a\u8fd4\u56de\u4e00\u4e2a\u526f\u672c\u3002reshape
\u4e5f\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5f20\u91cf\uff0c\u4f46\u603b\u662f\u521b\u5efa\u6570\u636e\u7684\u526f\u672c\uff0c\u5373\u4f7f\u539f\u59cb\u5f20\u91cf\u662f\u8fde\u7eed\u7684\u3002view
\u3002reshape
\u3002view
\u7684\u53c2\u6570\u662f\u76ee\u6807\u5f62\u72b6\u7684\u7ef4\u5ea6\u3002reshape
\u7684\u53c2\u6570\u4e5f\u662f\u76ee\u6807\u5f62\u72b6\u7684\u7ef4\u5ea6\uff0c\u4f46\u5b83\u53ef\u4ee5\u63a5\u53d7\u4e00\u4e2a\u989d\u5916\u7684\u53c2\u6570inplace
\uff0c\u5982\u679c\u8bbe\u7f6e\u4e3aTrue
\uff0c\u5219\u4f1a\u5728\u539f\u5730\u4fee\u6539\u5f20\u91cf\u7684\u5f62\u72b6\u3002torch.sin(x)
\u548c x.sin()
\u662f\u7b49\u4ef7\u7684x = torch.tensor([[1, 2, 3],\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [4, 5, 6]], dtype=torch.float32)\nprint('Original tensor:')\nprint(x)\n\nprint('\\nSum over entire tensor:')\nprint(torch.sum(x))\nprint(x.sum())\n\n# We can sum over each row:\nprint('\\nSum of each row:')\nprint(torch.sum(x, dim=0))\nprint(x.sum(dim=0))\n\n# Sum over each column:\nprint('\\nSum of each column:')\nprint(torch.sum(x, dim=1))\nprint(x.sum(dim=1))\n
torch.dot
: Computes inner product of vectorstorch.mm
: Computes matrix-matrix productstorch.mv
: Computes matrix-vector productstorch.addmm
/ torch.addmv
: Computes matrix-matrix and matrix-vector multiplications plus a biastorch.bmm
/ torch.baddmm
: Batched versions of torch.mm
and torch.addmm
, respectivelytorch.matmul
: General matrix product that performs different operations depending on the rank of the inputs. Confusingly, this is similar to np.dot
in numpy.\u7ea6 677 \u4e2a\u5b57 216 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u4e24\u79cd\u7ebf\u6027\u5206\u7c7b\u5668\uff1a\u652f\u6301\u5411\u91cf\u673a\uff08SVM\uff09\u548cSoftmax\u5206\u7c7b\u5668\u3002\u8fd9\u4e24\u79cd\u5206\u7c7b\u5668\u90fd\u662f\u76d1\u7763\u5b66\u4e60\u7b97\u6cd5\uff0c\u7528\u4e8e\u5206\u7c7b\u4efb\u52a1\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#svm","title":"\u652f\u6301\u5411\u91cf\u673a\uff08SVM\uff09","text":"SVM\u7684\u76ee\u6807\u662f\u627e\u5230\u4e00\u4e2a\u8d85\u5e73\u9762\uff0c\u5b83\u53ef\u4ee5\u6700\u5927\u5316\u4e0d\u540c\u7c7b\u522b\u4e4b\u95f4\u7684\u8fb9\u754c\u3002\u8fd9\u4e2a\u8d85\u5e73\u9762\u88ab\u79f0\u4e3a\u6700\u4f18\u5206\u5272\u8d85\u5e73\u9762\u3002\u5bf9\u4e8e\u4e8c\u5206\u7c7b\u95ee\u9898\uff0cSVM\u7684\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W, b) = \\frac{1}{N} \\sum_{i=1}^{N} \\max(0, 1 - y_i (W \\cdot x_i + b)) \\]\u5176\u4e2d\uff0c\\(W\\) \u662f\u6743\u91cd\u5411\u91cf\uff0c\\(b\\) \u662f\u504f\u7f6e\u9879\uff0c\\(x_i\\) \u662f\u8f93\u5165\u7279\u5f81\uff0c\\(y_i\\) \u662f\u6807\u7b7e\uff08-1\u62161\uff09\uff0c\\(N\\) \u662f\u6837\u672c\u6570\u91cf\u3002
\u4e3a\u4e86\u5b9e\u73b0\u591a\u5206\u7c7b\uff0c\u6211\u4eec\u4f7f\u7528\u7ed3\u6784\u5316SVM\u635f\u5931\u51fd\u6570\uff0c\u5b83\u8003\u8651\u4e86\u6bcf\u4e2a\u7c7b\u522b\u7684\u5206\u6570\uff0c\u5e76\u5c1d\u8bd5\u6700\u5927\u5316\u6b63\u786e\u7c7b\u522b\u7684\u5206\u6570\u4e0e\u6b21\u9ad8\u7c7b\u522b\u5206\u6570\u4e4b\u95f4\u7684\u5dee\u8ddd\u3002\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = \\frac{1}{N} \\sum_{i=1}^{N} \\sum_{j \\neq y_i} \\max(0, \\text{score}_j - \\text{score}_{y_i} + \\Delta) \\]\u5176\u4e2d\uff0c\\(\\text{score}_j = W_j \\cdot x_i\\)\uff0c\\(\\Delta\\) \u662f\u4e00\u4e2a\u5e38\u6570\uff0c\u901a\u5e38\u8bbe\u7f6e\u4e3a1\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#softmax","title":"Softmax\u5206\u7c7b\u5668","text":"Softmax\u5206\u7c7b\u5668\u4f7f\u7528Softmax\u51fd\u6570\u5c06\u8f93\u5165\u7279\u5f81\u6620\u5c04\u5230\u6982\u7387\u5206\u5e03\u4e0a\u3002\u5bf9\u4e8e\u6bcf\u4e2a\u6837\u672c\uff0cSoftmax\u51fd\u6570\u8f93\u51fa\u6bcf\u4e2a\u7c7b\u522b\u7684\u6982\u7387\u3002Softmax\u51fd\u6570\u5b9a\u4e49\u4e3a\uff1a
\\[ \\text{softmax}(z_i) = \\frac{e^{z_i}}{\\sum_{j=1}^{K} e^{z_j}} \\]\u5176\u4e2d\uff0c\\(z_i\\) \u662f\u7b2c\\(i\\)\u4e2a\u7c7b\u522b\u7684\u5206\u6570\uff0c\\(K\\) \u662f\u7c7b\u522b\u603b\u6570\u3002
Softmax\u5206\u7c7b\u5668\u7684\u635f\u5931\u51fd\u6570\u662f\u4ea4\u53c9\u71b5\u635f\u5931\uff0c\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = -\\frac{1}{N} \\sum_{i=1}^{N} \\sum_{j=1}^{K} y_{ij} \\log(\\text{softmax}(z_j)) \\]\u5176\u4e2d\uff0c\\(y_{ij}\\) \u662f\u4e00\u4e2a\u6307\u793a\u53d8\u91cf\uff0c\u5982\u679c\u6837\u672c\\(i\\)\u5c5e\u4e8e\u7c7b\u522b\\(j\\)\uff0c\u5219\u4e3a1\uff0c\u5426\u5219\u4e3a0\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#_2","title":"\u6b63\u5219\u5316","text":"\u4e3a\u4e86\u9632\u6b62\u8fc7\u62df\u5408\uff0c\u6211\u4eec\u5728\u635f\u5931\u51fd\u6570\u4e2d\u6dfb\u52a0\u4e86\u6b63\u5219\u5316\u9879\u3002L2\u6b63\u5219\u5316\u7684\u635f\u5931\u51fd\u6570\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a
\\[ L(W) = L(W) + \\lambda \\lVert W \\rVert^2 \\]\u5176\u4e2d\uff0c\\(\\lambda\\) \u662f\u6b63\u5219\u5316\u5f3a\u5ea6\u3002
"},{"location":"AI/EECS%20498-007/linear_classifer/#_3","title":"\u4ee3\u7801\u5b9e\u73b0","text":"\u4ee3\u7801\u4e2d\u5b9e\u73b0\u4e86\u4e24\u79cd\u635f\u5931\u51fd\u6570\u7684\u6734\u7d20\u7248\u672c\uff08svm_loss_naive
\u548c softmax_loss_naive
\uff09\u548c\u5411\u91cf\u5316\u7248\u672c\uff08svm_loss_vectorized
\u548c softmax_loss_vectorized
\uff09\u3002\u5411\u91cf\u5316\u7248\u672c\u901a\u8fc7\u907f\u514d\u663e\u5f0f\u5faa\u73af\u6765\u63d0\u9ad8\u8ba1\u7b97\u6548\u7387\u3002
\u8bad\u7ec3\u8fc7\u7a0b\uff08train_linear_classifier
\uff09\u4f7f\u7528\u968f\u673a\u68af\u5ea6\u4e0b\u964d\uff08SGD\uff09\u6765\u4f18\u5316\u635f\u5931\u51fd\u6570\u3002\u5728\u6bcf\u6b21\u8fed\u4ee3\u4e2d\uff0c\u6211\u4eec\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6279\u6b21\u7684\u6837\u672c\uff0c\u8ba1\u7b97\u635f\u5931\u548c\u68af\u5ea6\uff0c\u7136\u540e\u66f4\u65b0\u6743\u91cd\u3002
\u9884\u6d4b\u8fc7\u7a0b\uff08predict_linear_classifier
\uff09\u4f7f\u7528\u8bad\u7ec3\u597d\u7684\u6743\u91cd\u6765\u9884\u6d4b\u65b0\u6837\u672c\u7684\u7c7b\u522b\u3002
\u4ee3\u7801\u4e2d\u8fd8\u5305\u542b\u4e86\u8d85\u53c2\u6570\u641c\u7d22\u7684\u51fd\u6570\uff08svm_get_search_params
\u548c softmax_get_search_params
\uff09\uff0c\u5b83\u4eec\u8fd4\u56de\u4e0d\u540c\u7684\u5b66\u4e60\u7387\u548c\u6b63\u5219\u5316\u5f3a\u5ea6\u7684\u5019\u9009\u503c\uff0c\u4ee5\u4fbf\u627e\u5230\u6700\u4f73\u7684\u6a21\u578b\u53c2\u6570\u3002
import torch\nimport random\nfrom abc import abstractmethod\n\ndef hello_linear_classifier():\n print('Hello from linear_classifier.py!')\n\nclass LinearClassifier(object):\n def __init__(self):\n random.seed(0)\n torch.manual_seed(0)\n self.W = None\n\n def train(self, X_train, y_train, learning_rate=1e-3, reg=1e-5, num_iters=100,\n batch_size=200, verbose=False):\n train_args = (self.loss, self.W, X_train, y_train, learning_rate, reg,\n num_iters, batch_size, verbose)\n self.W, loss_history = train_linear_classifier(*train_args)\n return loss_history\n\n def predict(self, X):\n return predict_linear_classifier(self.W, X)\n\n @abstractmethod\n def loss(self, W, X_batch, y_batch, reg):\n raise NotImplementedError\n\n def _loss(self, X_batch, y_batch, reg):\n self.loss(self.W, X_batch, y_batch, reg)\n\n def save(self, path):\n torch.save({'W': self.W}, path)\n print(\"Saved in {}\".format(path))\n\n def load(self, path):\n W_dict = torch.load(path, map_location='cpu')\n self.W = W_dict['W']\n print(\"load checkpoint file: {}\".format(path))\n\n\nclass LinearSVM(LinearClassifier):\n def loss(self, W, X_batch, y_batch, reg):\n return svm_loss_vectorized(W, X_batch, y_batch, reg)\n\n\nclass Softmax(LinearClassifier):\n def loss(self, W, X_batch, y_batch, reg):\n return softmax_loss_vectorized(W, X_batch, y_batch, reg)\n\n\ndef svm_loss_naive(W, X, y, reg):\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n loss = 0.0\n for i in range(num_train):\n scores = W.t().mv(X[i])\n correct_class_score = scores[y[i]]\n for j in range(num_classes):\n if j == y[i]:\n continue\n margin = scores[j] - correct_class_score + 1\n if margin > 0:\n loss += margin\n dW[:, j] += X[i]\n dW[:, y[i]] -= X[i]\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef svm_loss_vectorized(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n scores = X.mm(W)\n correct_class_score = scores[range(num_train), y]\n margin = scores - correct_class_score.view(-1, 1) + 1\n margin[range(num_train), y] = 0\n mask = (margin > 0)\n loss = margin[mask].sum()\n mask_correct_y = torch.zeros_like(scores, dtype=torch.bool)\n mask_correct_y[range(num_train), y] = True\n margin[margin > 0] = 1\n margin[margin < 0] = 0\n margin[mask_correct_y] = torch.sum(margin, axis=1) * -1\n dW = margin.T.mm(X).T\n loss /= num_train\n dW /= num_train\n loss += reg * torch.sum(W * W)\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef sample_batch(X, y, num_train, batch_size):\n indices = torch.randint(num_train, (batch_size,))\n y_batch = y[indices]\n X_batch = X[indices]\n return X_batch, y_batch\n\n\ndef train_linear_classifier(loss_func, W, X, y, learning_rate=1e-3,\n reg=1e-5, num_iters=100, batch_size=200,\n verbose=False):\n num_train, dim = X.shape\n if W is None:\n num_classes = torch.max(y) + 1\n W = 0.000001 * torch.randn(dim, num_classes, device=X.device, dtype=X.dtype)\n else:\n num_classes = W.shape[1]\n\n loss_history = []\n for it in range(num_iters):\n X_batch, y_batch = sample_batch(X, y, num_train, batch_size)\n loss, grad = loss_func(W, X_batch, y_batch, reg)\n loss_history.append(loss.item())\n W -= learning_rate * grad\n if verbose and it % 100 == 0:\n print('iteration %d / %d: loss %f' % (it, num_iters, loss))\n\n return W, loss_history\n\n\ndef predict_linear_classifier(W, X):\n y_pred = torch.zeros(X.shape[0], dtype=torch.int64)\n _, y_pred = X.mm(W).max(dim=1)\n return y_pred\n\n\ndef svm_get_search_params():\n learning_rates = [0.000001, 0.0001, 0.001, 0.005, 0.01, 0.05]\n regularization_strengths = [0.001, 0.5, 1, 3]\n return learning_rates, regularization_strengths\n\n\ndef test_one_param_set(cls, data_dict, lr, reg, num_iters=2000):\n train_acc = 0.0\n val_acc = 0.0\n cls.train(data_dict['X_train'], data_dict['y_train'], lr, reg, num_iters,\n batch_size=200, verbose=False)\n y_train_pred = cls.predict(data_dict['X_train'])\n train_acc = 100.0 * (data_dict['y_train'] == y_train_pred).double().mean().item()\n\n y_test_pred = cls.predict(data_dict['X_val'])\n val_acc = 100.0 * (data_dict['y_val'] == y_test_pred).double().mean().item()\n\n return cls, train_acc, val_acc\n\n\ndef softmax_loss_naive(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n\n scores = W.t().mv(X[0])\n correct_class_score = scores[y[0]]\n\n for i in range(num_train):\n scores = W.t().mv(X[i])\n scores = scores - scores.max()\n correct_class_score = scores[y[i]]\n loss += -correct_class_score + torch.log(torch.exp(scores).sum())\n for j in range(num_classes):\n if j == y[i]:\n dW[:, j] += torch.exp(scores[j]) / torch.exp(scores).sum() * X[i, :] - X[i, :]\n else:\n dW[:, j] += torch.exp(scores[j]) / torch.exp(scores).sum() * X[i, :]\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef softmax_loss_vectorized(W, X, y, reg):\n loss = 0.0\n dW = torch.zeros_like(W)\n num_classes = W.shape[1]\n num_train = X.shape[0]\n\n\n scores = X.mm(W)\n val, _ = scores.max(dim=1)\n scores = scores - val.view(-1, 1)\n exp_scores = scores.exp()\n exp_scores_sum = exp_scores.sum(dim=1)\n exp_scores_sum_log = exp_scores_sum.log()\n correct_class_scores = scores[range(num_train), y]\n loss = (exp_scores_sum_log - correct_class_scores).sum()\n zeros = torch.zeros((num_train, num_classes), dtype=torch.float64, device='cuda')\n zeros[range(num_train), y] = -1\n minus_X = zeros.t().mm(X)\n dW += minus_X.t()\n dW += ((exp_scores / exp_scores_sum.view(-1, 1)).t().mm(X)).t()\n\n loss /= num_train\n loss += reg * torch.sum(W * W)\n dW /= num_train\n dW += 2 * reg * W\n\n return loss, dW\n\n\ndef softmax_get_search_params():\n learning_rates = [1e-4, 1e-3,1e-2, 1e-1, 1]\n regularization_strengths = [1e-4, 1e-3, 1e-2, 1e-1] \n return learning_rates, regularization_strengths\n
"},{"location":"AI/FFB6D/FFB6D_Conda/","title":"FFB6D\u73af\u5883\u914d\u7f6e\u6307\u5357\uff1a\u539f\u751f\u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#ffb6d","title":"FFB6D\u73af\u5883\u914d\u7f6e\u6307\u5357\uff1a\u539f\u751f\u7cfb\u7edf\u5b89\u88c5","text":"\u7ea6 293 \u4e2a\u5b57 96 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/FFB6D/FFB6D_Conda/#1","title":"1. \u7cfb\u7edf\u8981\u6c42","text":"# \u6dfb\u52a0NVIDIA\u5305\u4ed3\u5e93\nsudo add-apt-repository ppa:graphics-drivers/ppa\nsudo apt-get update\n\n# \u5b89\u88c5NVIDIA\u9a71\u52a8\nsudo apt-get install -y nvidia-driver-535 # \u6839\u636e\u9700\u8981\u9009\u62e9\u7248\u672c\n\n# \u91cd\u542f\u7cfb\u7edf\nsudo reboot\n\n# \u9a8c\u8bc1\u5b89\u88c5\nnvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#22-cudacudnn","title":"2.2 \u5b89\u88c5CUDA\u548ccuDNN","text":"Bash# \u4e0b\u8f7d\u5e76\u5b89\u88c5CUDA 11.0\nwget https://developer.download.nvidia.com/compute/cuda/11.0.3/local_installers/cuda_11.0.3_450.51.06_linux.run\nsudo sh cuda_11.0.3_450.51.06_linux.run\n\n# \u914d\u7f6e\u73af\u5883\u53d8\u91cf\necho 'export PATH=/usr/local/cuda-11.0/bin:$PATH' >> ~/.bashrc\necho 'export LD_LIBRARY_PATH=/usr/local/cuda-11.0/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc\nsource ~/.bashrc\n\n# \u4e0b\u8f7d\u5e76\u5b89\u88c5cuDNN 8.0\n# \u6ce8\uff1a\u9700\u8981\u4eceNVIDIA\u5f00\u53d1\u8005\u7f51\u7ad9\u4e0b\u8f7dcuDNN v8.0\uff0c\u89e3\u538b\u540e\uff1a\nsudo cp cuda/include/cudnn*.h /usr/local/cuda/include\nsudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64\nsudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#23","title":"2.3 \u5b89\u88c5\u7cfb\u7edf\u4f9d\u8d56","text":"Bashsudo apt-get update\nsudo apt-get install -y \\\n python3.6 \\\n python3.6-dev \\\n python3-pip \\\n git \\\n cmake \\\n build-essential \\\n libopencv-dev \\\n libglib2.0-0 \\\n libsm6 \\\n libxext6 \\\n libxrender-dev \\\n libboost-all-dev \\\n libeigen3-dev\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#24-python","title":"2.4 \u914d\u7f6ePython\u73af\u5883","text":"Bash# \u8bbe\u7f6ePython 3.6\u4e3a\u9ed8\u8ba4\u7248\u672c\nsudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1\nsudo update-alternatives --set python3 /usr/bin/python3.6\n\n# \u914d\u7f6epip\u955c\u50cf\u6e90\npip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n\n# \u5347\u7ea7pip\npython3 -m pip install --upgrade pip\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#3-pytorch","title":"3. \u5b89\u88c5PyTorch\u548c\u4f9d\u8d56\u5305","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#31-pytorch","title":"3.1 \u5b89\u88c5PyTorch","text":"Bashpip3 install torch==1.10.2+cu113 torchvision==0.11.3+cu113 -f https://download.pytorch.org/whl/torch_stable.html\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#32","title":"3.2 \u5b89\u88c5\u9879\u76ee\u4f9d\u8d56","text":"\u521b\u5efarequirements.txt\u5e76\u5b89\u88c5\u4f9d\u8d56\uff1a
Bashpip3 install -r requirements.txt\n
requirements.txt\u5185\u5bb9\uff1a
Text Onlyh5py \nnumpy \npyyaml==5.4.1\nenum34 \nfuture \nscipy==1.4.1 \nopencv_contrib_python==3.4.2.16 \ntransforms3d==0.3.1 \nscikit_image==0.13.1 \nlmdb==0.94 \nsetuptools==41.0.0 \ncffi==1.11.5 \neasydict==1.7 \nplyfile==0.6 \npillow==8.2.0 \ndataclasses\nglumpy \ntqdm\ntensorboardX \npandas\nscikit-learn \nscipy \ntermcolor\npybind11\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#4","title":"4. \u7f16\u8bd1\u548c\u5b89\u88c5\u7279\u6b8a\u7ec4\u4ef6","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#41-apex","title":"4.1 \u7f16\u8bd1apex","text":"Bashgit clone https://github.com/NVIDIA/apex\ncd apex\nexport TORCH_CUDA_ARCH_LIST=\"6.0;6.1;6.2;7.0;7.5\"\npython setup.py install -v\ncd ..\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#42-normalspeed","title":"4.2 \u5b89\u88c5\u548c\u7f16\u8bd1normalspeed","text":"Bash# 1. \u51c6\u5907OpenCV\u73af\u5883\npip uninstall opencv-python opencv-python-headless -y\npip install opencv-python==4.5.3.56\n\n# 2. \u514b\u9686\u5e76\u5b89\u88c5normalspeed\ngit clone https://github.com/hfutcgncas/normalspeed.git\ncd normalspeed/normalSpeed\n\n# \u5b89\u88c5\u7f16\u8bd1\u4f9d\u8d56\nsudo apt-get install python3-pybind11\npip3 install Cython==0.29.15\n\n# \u6e05\u7406\u5e76\u91cd\u65b0\u5b89\u88c5\nrm -rf build/ dist/ *.egg-info/\npython3 setup.py install --user\ncd ../..\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#5-ffb6d","title":"5. \u514b\u9686\u548c\u914d\u7f6eFFB6D","text":"Bash# \u514b\u9686\u4ee3\u7801\ngit clone https://github.com/ethnhe/FFB6D.git\ncd FFB6D\n\n# \u521b\u5efa\u5fc5\u8981\u7684\u76ee\u5f55\nmkdir -p datasets models train_log\n\n# \u914d\u7f6e\u73af\u5883\u53d8\u91cf\nexport PYTHONPATH=$PYTHONPATH:$(pwd)\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#6","title":"6. \u9a8c\u8bc1\u5b89\u88c5","text":"Bash# \u9a8c\u8bc1CUDA\u652f\u6301\npython3 -c \"import torch; print('CUDA available:', torch.cuda.is_available())\"\n\n# \u9a8c\u8bc1apex\u5b89\u88c5\npython3 -c \"from apex import amp; print('APEX installed')\"\n\n# \u9a8c\u8bc1normalspeed\u5b89\u88c5\npython3 -c \"import normalSpeed; print('normalspeed installed')\"\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#7","title":"7. \u5e38\u89c1\u95ee\u9898","text":""},{"location":"AI/FFB6D/FFB6D_Conda/#71","title":"7.1 \u7f51\u7edc\u95ee\u9898","text":"Bash# \u4f7f\u7528\u4ee3\u7406\uff08\u5982\u9700\u8981\uff09\nexport http_proxy=\"http://proxy:port\"\nexport https_proxy=\"http://proxy:port\"\n\n# \u6216\u4f7f\u7528\u56fd\u5185\u955c\u50cf\u6e90\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
"},{"location":"AI/FFB6D/FFB6D_Conda/#72","title":"7.2 \u7248\u672c\u517c\u5bb9\u6027\u95ee\u9898","text":"\u6309\u7167\u5b98\u65b9\u6587\u6863\u914d\u7f6eLineMOD\u6570\u636e\u96c6\u5e76\u5f00\u59cb\u8bad\u7ec3\u3002
"},{"location":"AI/FFB6D/FFB6D_Conda/#_1","title":"\u53c2\u8003\u8d44\u6599","text":"\u7ea6 653 \u4e2a\u5b57 213 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"AI/FFB6D/FFB6D_Docker/#1","title":"1. \u7b80\u4ecb","text":"Docker\u662f\u4e00\u4e2a\u5f00\u6e90\u7684\u5e94\u7528\u5bb9\u5668\u5f15\u64ce\uff0c\u8ba9\u5f00\u53d1\u8005\u53ef\u4ee5\u6253\u5305\u4ed6\u4eec\u7684\u5e94\u7528\u4ee5\u53ca\u4f9d\u8d56\u5305\u5230\u4e00\u4e2a\u53ef\u79fb\u690d\u7684\u5bb9\u5668\u4e2d\uff0c\u7136\u540e\u53d1\u5e03\u5230\u4efb\u4f55\u6d41\u884c\u7684Linux\u6216Windows\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u3002\u672c\u6587\u5c06\u4ee5\u914d\u7f6eFFB6D\uff08\u4e00\u4e2a3D\u76ee\u6807\u68c0\u6d4b\u6a21\u578b\uff09\u7684\u8fd0\u884c\u73af\u5883\u4e3a\u4f8b\uff0c\u4ecb\u7ecdDocker\u7684\u57fa\u672c\u4f7f\u7528\u3002
"},{"location":"AI/FFB6D/FFB6D_Docker/#2","title":"2. \u73af\u5883\u51c6\u5907","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#21","title":"2.1 \u7cfb\u7edf\u8981\u6c42","text":"\u5b89\u88c5Docker
Bash# \u66f4\u65b0apt\u5305\u7d22\u5f15\nsudo apt-get update\n\n# \u5b89\u88c5\u5fc5\u8981\u7684\u7cfb\u7edf\u5de5\u5177\nsudo apt-get install -y \\\n apt-transport-https \\\n ca-certificates \\\n curl \\\n gnupg \\\n lsb-release\n\n# \u6dfb\u52a0Docker\u7684\u5b98\u65b9GPG\u5bc6\u94a5\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg\n\n# \u8bbe\u7f6e\u7a33\u5b9a\u7248\u4ed3\u5e93\necho \\\n \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\\n $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\n\n# \u5b89\u88c5Docker Engine\nsudo apt-get update\nsudo apt-get install -y docker-ce docker-ce-cli containerd.io\n\n# \u9a8c\u8bc1\u5b89\u88c5\nsudo docker run hello-world\n
\u5b89\u88c5NVIDIA\u9a71\u52a8
Bash# \u6dfb\u52a0NVIDIA\u5305\u4ed3\u5e93\nsudo add-apt-repository ppa:graphics-drivers/ppa\nsudo apt-get update\n\n# \u5b89\u88c5NVIDIA\u9a71\u52a8\nsudo apt-get install -y nvidia-driver-535 # \u6839\u636e\u9700\u8981\u9009\u62e9\u7248\u672c\n\n# \u91cd\u542f\u7cfb\u7edf\nsudo reboot\n\n# \u9a8c\u8bc1\u5b89\u88c5\nnvidia-smi\n
\u5b89\u88c5NVIDIA Container Toolkit
Bash# \u8bbe\u7f6e\u7a33\u5b9a\u7248\u4ed3\u5e93\ncurl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg\n\necho \"deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/ubuntu22.04/$(arch) /\" | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list\n\n# \u66f4\u65b0\u8f6f\u4ef6\u5305\u5217\u8868\nsudo apt-get update\n\n# \u5b89\u88c5nvidia-docker2\nsudo apt-get install -y nvidia-container-toolkit\n\n# \u91cd\u542fDocker\u670d\u52a1\nsudo systemctl restart docker\n\n# \u6d4b\u8bd5GPU\u652f\u6301\nsudo docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#23-docker","title":"2.3 Docker\u914d\u7f6e\u4f18\u5316","text":"\u914d\u7f6e\u955c\u50cf\u52a0\u901f
Bashsudo tee /etc/docker/daemon.json << EOF\n{\n \"registry-mirrors\": [\n \"https://docker.1panel.dev\",\n \"https://docker.zhai.cm\",\n \"https://hub.littlediary.cn\",\n \"https://docker.nastool.de\"\n ],\n \"dns\": [\"8.8.8.8\", \"8.8.4.4\"],\n \"max-concurrent-downloads\": 10,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"10m\",\n \"max-file\": \"3\"\n }\n}\nEOF\n\nsudo systemctl daemon-reload\nsudo systemctl restart docker\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#3-ffb6d","title":"3. FFB6D\u73af\u5883\u914d\u7f6e\u5b9e\u4f8b","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#31","title":"3.1 \u9879\u76ee\u7ed3\u6784","text":"Bashffb6d_docker/\n\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 build_and_run.sh\n\u251c\u2500\u2500 downloads/\n\u2502 \u251c\u2500\u2500 apex/\n\u2502 \u2514\u2500\u2500 normalspeed/\n\u251c\u2500\u2500 code/\n\u251c\u2500\u2500 datasets/\n\u251c\u2500\u2500 models/\n\u2514\u2500\u2500 train_log/\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#32-dockerfile","title":"3.2 \u521b\u5efaDockerfile","text":"Docker# \u4f7f\u7528\u8f83\u65b0\u7684 CUDA \u955c\u50cf\nFROM nvcr.io/nvidia/cuda:11.0.3-cudnn8-devel-ubuntu18.04\n\n# \u4f7f\u7528 NVIDIA CUDA 11.3 \u57fa\u7840\u955c\u50cf\n# FROM nvcr.io/nvidia/cuda:11.3.1-cudnn8-devel-ubuntu20.04\n\n# \u907f\u514d\u4ea4\u4e92\u5f0f\u63d0\u793a\nENV DEBIAN_FRONTEND=noninteractive\nENV PYTHONPATH=/workspace/code\nENV CUDA_HOME=/usr/local/cuda\nENV PATH=$CUDA_HOME/bin:$PATH\nENV LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH\n\nWORKDIR /workspace\n\n# \u5b89\u88c5\u7cfb\u7edf\u4f9d\u8d56\nRUN apt-get update && apt-get install -y \\\n python3.6 \\\n python3.6-dev \\\n python3-pip \\\n git \\\n cmake \\\n build-essential \\\n libopencv-dev \\\n libglib2.0-0 \\\n libsm6 \\\n libxext6 \\\n libxrender-dev \\\n libboost-all-dev \\\n libeigen3-dev \\\n wget \\\n && rm -rf /var/lib/apt/lists/*\n\n# \u8bbe\u7f6e Python 3.6 \u4e3a\u9ed8\u8ba4\u7248\u672c\nRUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1\nRUN update-alternatives --set python3 /usr/bin/python3.6\n\n# \u5347\u7ea7 pip\nRUN python3 -m pip install --upgrade pip\n\n# \u914d\u7f6epip\u955c\u50cf\u6e90\nRUN pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n\n# \u5148\u5b89\u88c5 PyTorch (\u4f7f\u7528\u8f83\u65b0\u4f46\u517c\u5bb9\u7684\u7248\u672c)\nRUN pip3 install torch==1.10.2+cu113 torchvision==0.11.3+cu113 -f https://download.pytorch.org/whl/torch_stable.html\n\n# \u590d\u5236\u9884\u4e0b\u8f7d\u7684\u6587\u4ef6\nCOPY downloads/apex /workspace/apex\nCOPY downloads/normalspeed /workspace/normalspeed\nCOPY code /workspace/code\n\n# \u5b89\u88c5 apex\n#RUN cd /workspace/apex && \\\n# pip install -v --no-cache-dir --global-option=\"--cpp_ext\" --global-option=\"--cuda_ext\" ./ || \\\n# (echo \"Apex installation failed. Check the error messages above.\" && exit 1)\n\n# \u5b89\u88c5 normalspeed\n#RUN cd /workspace/normalspeed && \\\n# python3 setup.py build_ext --inplace && \\\n# python3 setup.py install\n\nWORKDIR /workspace/code\n
\u66f4\u6539 requirement.txt
h5py \nnumpy \npyyaml==5.4.1\nenum34 \nfuture \nscipy==1.4.1 \nopencv_contrib_python==3.4.2.16 \ntransforms3d==0.3.1 \nscikit_image==0.13.1 \nlmdb==0.94 \nsetuptools==41.0.0 \ncffi==1.11.5 \neasydict==1.7 \nplyfile==0.6 \npillow==8.2.0 \ndataclasses\nglumpy \ntqdm\ntensorboardX \npandas\nscikit-learn \nscipy \ntermcolor\npybind11\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#33-docker-composeyml","title":"3.3 \u521b\u5efadocker-compose.yml","text":"YAMLversion: '3'\nservices:\n ffb6d:\n build: .\n image: ffb6d:latest\n container_name: ffb6d_container\n runtime: nvidia\n environment:\n - NVIDIA_VISIBLE_DEVICES=all\n volumes:\n - ./datasets:/workspace/code/datasets\n - ./train_log:/workspace/code/train_log\n - ./models:/workspace/code/models\n shm_size: '8gb'\n tty: true\n stdin_open: true\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#34","title":"3.4 \u6784\u5efa\u548c\u8fd0\u884c\u811a\u672c","text":"\u521b\u5efabuild_and_run.sh
\uff1a
#!/bin/bash\n\n# \u521b\u5efa\u5fc5\u8981\u76ee\u5f55\nmkdir -p downloads datasets models train_log\n\n# \u4e0b\u8f7d\u4f9d\u8d56\ncd downloads\nif [ ! -d \"apex\" ]; then\n git clone https://github.com/NVIDIA/apex.git\nfi\nif [ ! -d \"normalspeed\" ]; then\n git clone https://github.com/hfutcgncas/normalspeed.git\nfi\ncd ..\n\n# \u514b\u9686FFB6D\u4ee3\u7801\nif [ ! -d \"code\" ]; then\n git clone https://github.com/ethnhe/FFB6D.git code\nfi\n\n# \u6784\u5efa\u955c\u50cf\ndocker-compose build\n\n# \u8fd0\u884c\u5bb9\u5668\ndocker-compose up -d\ndocker exec -it ffb6d_container bash\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#35","title":"3.5 \u542f\u52a8\u548c\u9a8c\u8bc1","text":"Bash# \u6dfb\u52a0\u6267\u884c\u6743\u9650\nchmod +x build_and_run.sh\n\n# \u8fd0\u884c\n./build_and_run.sh\n\n# \u5728\u5bb9\u5668\u5185\u9a8c\u8bc1\npython3 -c \"import torch; print('CUDA available:', torch.cuda.is_available())\"\npython3 -c \"from apex import amp; print('APEX installed')\"\npython3 -c \"import normalspeed; print('normalspeed installed')\"\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#36-apex","title":"3.6 \u7f16\u8bd1 apex","text":"Text Onlygit clone https://github.com/NVIDIA/apex\ncd apex\nexport TORCH_CUDA_ARCH_LIST=\"6.0;6.1;6.2;7.0;7.5\"\npython setup.py install -v\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#37-normalspeed","title":"3.7 \u7f16\u8bd1 normalspeed","text":"Text Only# 1. \u5378\u8f7d\u5f53\u524dcv2\npip uninstall opencv-python opencv-python-headless -y\n\n# 2. \u5b89\u88c5\u7279\u5b9a\u7248\u672c\u7684OpenCV\uff0c\u9009\u62e9\u4e0ePython 3.6\u517c\u5bb9\u7684\u7248\u672c\npip install opencv-python==4.5.3.56\n\n# 3. \u9a8c\u8bc1\u5b89\u88c5\npython3 -c \"import cv2; print(cv2.__version__)\"\n
Text Only# \u8fdb\u5165normalSpeed\u76ee\u5f55\ncd /workspace/code/normalspeed/normalSpeed\n\n# \u5b89\u88c5\u4f9d\u8d56\napt-get update\napt-get install python3-pybind11\npip3 install Cython==0.29.15\n\n# \u6e05\u7406\u4e4b\u524d\u7684\u6784\u5efa\nrm -rf build/\nrm -rf dist/\nrm -rf *.egg-info/\n\n# \u91cd\u65b0\u5b89\u88c5\npython3 setup.py install\n\n# \u9a8c\u8bc1\u5b89\u88c5\npython3 -c \"import normalSpeed\"\n\n# \u8fd4\u56deffb6d\u76ee\u5f55\ncd /workspace/code/ffb6d/\n
Text Onlypython3 setup.py install --user\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#38","title":"3.8 \u8bad\u7ec3","text":"\u628a LineMOD \u590d\u5236\u5230\u5bf9\u5e94\u7684\u8def\u5f84\u4e0b\uff0c\u7136\u540e\u6309\u5b98\u7f51\u6765\u5c31\u597d\u4e86
"},{"location":"AI/FFB6D/FFB6D_Docker/#4","title":"4. \u5e38\u89c1\u95ee\u9898","text":""},{"location":"AI/FFB6D/FFB6D_Docker/#41","title":"4.1 \u7f51\u7edc\u95ee\u9898","text":"\u5982\u679c\u9047\u5230\u4e0b\u8f7d\u6162\u6216\u5931\u8d25\uff1a
Bash# \u4e34\u65f6\u4f7f\u7528\u4ee3\u7406\nexport http_proxy=\"http://proxy:port\"\nexport https_proxy=\"http://proxy:port\"\n\n# \u6216\u4fee\u6539pip\u6e90\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
\u6ce8\u610f\u7528\u4e86\u4ee3\u7406\u7684\u8bdd\uff0cdocker hub \u955c\u50cf\u5c31\u4f1a\u88ab\u8986\u76d6\u6389\uff0c\u5bfc\u81f4\u901f\u5ea6\u5f88\u6162\u3002\u6240\u4ee5\u5230\u65f6\u5019\u4e00\u5b9a\u8981\u53d6\u6d88\u4ee3\u7406 / \u5220\u9664\u4ee3\u7406\u6587\u4ef6
docker hub \u955c\u50cf\u8bbe\u7f6e\u4e0a\u9762\u5199\u4e86\uff0c\u5b98\u7f51\u662f\u8fd9\u4e2a GitHub - dongyubin/DockerHub: 2024\u5e7411\u6708\u66f4\u65b0\uff0c\u76ee\u524d\u56fd\u5185\u53ef\u7528Docker\u955c\u50cf\u6e90\u6c47\u603b\uff0cDockerHub\u56fd\u5185\u955c\u50cf\u52a0\u901f\u5217\u8868\uff0c\ud83d\ude80DockerHub\u955c\u50cf\u52a0\u901f\u5668
"},{"location":"AI/FFB6D/FFB6D_Docker/#42-cuda","title":"4.2 CUDA\u517c\u5bb9\u6027","text":"\u786e\u4fddNVIDIA\u9a71\u52a8\u7248\u672c\u652f\u6301\u6240\u9700\u7684CUDA\u7248\u672c\uff1a
Bash# \u68c0\u67e5\u652f\u6301\u7684\u6700\u9ad8CUDA\u7248\u672c\nnvidia-smi\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#43","title":"4.3 \u5185\u5b58\u4e0d\u8db3","text":"\u8c03\u6574Docker\u5185\u5b58\u9650\u5236\uff1a
YAML# \u5728docker-compose.yml\u4e2d\u6dfb\u52a0\nservices:\n ffb6d:\n deploy:\n resources:\n limits:\n memory: 16G\n
"},{"location":"AI/FFB6D/FFB6D_Docker/#5","title":"5. \u603b\u7ed3","text":"\u672c\u6587\u4ecb\u7ecd\u4e86\u4f7f\u7528Docker\u914d\u7f6e\u6df1\u5ea6\u5b66\u4e60\u73af\u5883\u7684\u5b8c\u6574\u6d41\u7a0b\uff0c\u4ee5FFB6D\u4e3a\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u5904\u7406\u590d\u6742\u4f9d\u8d56\u5173\u7cfb\u3002\u901a\u8fc7\u5bb9\u5668\u5316\u6280\u672f\uff0c\u6211\u4eec\u53ef\u4ee5\uff1a
\u5e0c\u671b\u672c\u6559\u7a0b\u80fd\u5e2e\u52a9\u4f60\u66f4\u597d\u5730\u7406\u89e3\u548c\u4f7f\u7528Docker\u3002
"},{"location":"AI/FFB6D/FFB6D_Docker/#_1","title":"\u53c2\u8003\u8d44\u6599","text":"Abstract
\u4e2a\u4eba\u535a\u5ba2
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
"},{"location":"Blogs/#selected-blogs","title":"Selected Blogs","text":"\u8bba\u6587\u7b14\u8bb0{{ blog_content }}
"},{"location":"Blogs/posts/24-12-29/","title":"\u5de5\u4f5c\u89c4\u5f8b","text":"\u7ea6 1038 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/24-12-29/#_1","title":"\u5de5\u4f5c\u89c4\u5f8b","text":"\u4e4b\u524d\u7684\u4e00\u4e9b\u611f\u60f3\u7eed\u5199\uff1a
Quote\u90a3\u4e48\u5982\u679c\u60f3\u8981\u63d0\u9ad8\u6548\u7387\u7684\u5bf9\u7b56\uff1a
\u6211\u60f3\u4e00\u4e2a\u5408\u7406\u7684\u751f\u6d3b\u4f5c\u606f\u5e94\u8be5\u6709\u4e00\u4e0b\u7279\u70b9\uff1a
\u5de5\u5177\uff1a obsidian\uff0c\u65f6\u95f4\u65e5\u5fd7\uff0c\u535a\u5ba2
\u7d2f\u4e86\u5c31\u4f11\u606f\uff0c\u4f11\u606f\u5b8c\u4e86\u5c31\u5de5\u4f5c
\u7684\u8fdb\u7a0b\u8f6c\u6362\u673a\u5236\u3002\u7ea6 2271 \u4e2a\u5b57 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 11 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_1","title":"\u4fe1\u606f","text":"\u6700\u8fd1\u7684\u4e00\u4e9b\u5173\u4e8e\u4fe1\u606f\u7684\u60f3\u6cd5\u3002
\u4e0b\u9762\u6211\u5148\u4e3e\u4e24\u4e2a\u4f8b\u5b50\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_2","title":"\u52c7\u6562\u53bb\u505a","text":"\u6211\u89c9\u5f97\u6211\u4e00\u76f4\u90fd\u662f\u5f88\u76f4\u63a5\u7684\u4eba\u3002 \u4e3e\u4e2a\u4f8b\u5b50\uff0c\u9ad8\u4e09\u5347\u5927\u4e00\u7684\u6691\u5047\uff0c\u6211\u5728\u8003\u8651\u8981\u4e0d\u8981\u8f6c\u4e13\u4e1a\u3002\u4e8e\u662f\u770b\u904d\u4e86\u6c34\u6e90\u6240\u6709\u76f8\u5173\u7684\u5e16\u5b50\uff0c\u95ee\u4e86\u5f88\u591a\u5b66\u957f\u5b66\u59d0\uff0c\u6574\u7406\u4e86\u5f88\u591a\u8def\u5f84\uff0c\u77e5\u9053\u4e86\u8f6c\u4e13\u4e1a\u8981\uff1a
\u4e5f\u8ba4\u8bc6\u4e86\u5f88\u591a\u5389\u5bb3\u7684\u4eba: xlb, \u661f\u7237\uff0ccl\uff0cKinnari\uff0c\u9c7c\u9c7c\u3002 \u77e5\u9053\u4e86\u5f88\u591a\u6761\u8def\uff0c\u5237\u8bfe\uff0c\u8fdb\u7ec4\uff0c\u6253 ACM\uff0c\u505a\u5f00\u6e90\uff0c\u76f4\u535a\uff0c\u8f6c\u4e13\u4e1a\u3002
\u4f46\u662f\uff0c\u518d\u540e\u6765\u6211\u4fbf\u4e0d\u60f3\u8f6c\u4e13\u4e1a\u4e86\uff08\u4e0d\u60f3\u4e0a\u5de5\u79d1\u5e73\u53f0\u7684\u91d1\u8bfe\uff09\u3002\u867d\u7136\u5230\u5934\u6765\u8fd8\u662f\u6ca1\u6709\u8f6c\u4e13\u4e1a\uff0c\u4f46\u662f\u5374\u6536\u83b7\u4e86\u4e0d\u5c11\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_3","title":"\u591a\u4ea4\u6d41","text":"\u4e00\u76f4\u611f\u89c9\u56fd\u5185\u7684\u6559\u80b2\u4e0d\u652f\u6301\u5408\u4f5c\uff0c\u5f3a\u70c8\u7684\u7ade\u4e89\u5173\u7cfb\u96be\u4ee5\u5f62\u6210\u5229\u76ca\u5171\u540c\u4f53\u3002
\u4f46\u662f\uff0c\u6700\u8fd1\u624d\u53d1\u73b0\uff0c\u6b63\u662f\u90a3\u4e9b\u4f60\u53bb\u5e2e\u52a9\u7684\u8fc7\u7a0b\u4e2d\u7684\u4ea4\u6d41\uff0c\u624d\u80fd\u591f\u8ba9\u4f60\u66f4\u597d\u7684\u53cd\u601d\uff0c\u4ea7\u751f\u65b0\u7684\u60f3\u6cd5\u3002
\u6bd4\u5982\u5728\u8fd9\u4e2a\u7cfb\u5217\u7684\u6587\u7ae0\u4e2d\uff0c Open and open again--\u5982\u4f55\u6709\u6781\u5f3a\u7684\u6267\u884c\u529b\uff1f\uff0c\u6240\u8c13\u7684 open \uff08\u4f5c\u8005\u610f\u601d\u5e94\u8be5\u662f\u548c\u4ed6\u4eba\u4ea4\u6d41\uff09\u4e5f\u53ea\u662f\u6444\u5165\u4fe1\u606f\u7684\u4e00\u79cd\u3002\u800c\u6b63\u662f\u56e0\u4e3a\u4e0e\u4eba\u4ea4\u6d41\u5f80\u5f80\u4f1a\u83b7\u5f97\u6bd4\u8f83\u9ad8\u8d28\u91cf\u7684\u4fe1\u606f\uff0c\u6240\u4ee5\u5448\u73b0\u51fa\u6765\u4ea4\u6d41\u6709\u5f88\u591a advantages\u3002\u4f46\u5b9e\u9645\u4e0a\uff0c\u662f\u4f18\u8d28\u7684\u4fe1\u606f\u5728\u53d1\u6325\u4f5c\u7528\u3002
\u4e8e\u662f\u8fc5\u901f\u548c @Kinnari \u4e00\u8d77\u7ec4\u5efa\u4e86\u4e00\u4e2a\u793e\u7fa4\uff0c\u5e0c\u671b\u80fd\u591f\u8ba9\u5927\u5bb6\u4e00\u8d77\u8ba8\u8bba\u60f3\u6cd5\uff0c\u8fed\u4ee3\u81ea\u5df1\u7684\u5de5\u4f5c\u6d41\u7a0b\uff0c\u51cf\u5c0f\u4fe1\u606f\u5dee\u3002
\u8fd9\u91cc\u662f\u7fa4\u4e8c\u7ef4\u7801 \u8fd9\u91cc\u662f\u7fa4\u89c4\u5219\u5b9e\u9645\u4e0a\uff0c\u4e0a\u6c34\u6e90\u641c\u7d22\uff0c\u53bb\u8ddf\u4ed6\u4eba\u4ea4\u6d41\u90fd\u662f\u4fe1\u606f\u8f93\u5165\u7684\u4e00\u73af\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_5","title":"\u4fe1\u606f\u7684\u8d28\u91cf","text":"\u73b0\u4ee3\u793e\u4f1a\u4e0d\u7f3a\u4f18\u8d28\u4fe1\u606f\uff0c\u7f3a\u7684\u662f\u5982\u4f55\u627e\u5230\u4f18\u8d28\u4fe1\u606f
\u5982\u4f55\u8fdc\u79bb\u4f4e\u8d28\u91cf\u4fe1\u606f\uff1f\u6211\u7684\u4e00\u4e9b\u901a\u7528\u7684\u539f\u5219\u662f\uff1a
\u5b66\u4e60\u67d0\u4e00\u9886\u57df\u77e5\u8bc6\u65f6\u9075\u5faa\u00a0\u81ea\u4f4e\u5411\u4e0a
\u00a0\u7684\u8fc7\u7a0b\uff1a
\u8f6e\u5ed3\u8ba4\u8bc6
\u3002\u6bd4\u8f83\u5168\u9762\u7684\u57fa\u672c\u8ba4\u8bc6
\u00a0\u540e\uff0c\u6211\u4f1a\u627e\u4e00\u4e9b\u76f8\u5173\u4e66\u7c4d\u53bb\u7cfb\u7edf\u6027\u7684\u5b66\u4e60\u8be5\u9886\u57df\u7684\u7406\u8bba\u77e5\u8bc6\u3002\u6211\u89c9\u5f97\u7126\u8651\u5e94\u8be5\u662f\u4fe1\u606f\u6444\u5165\u7684\u95ee\u9898\uff0c\u4e3b\u8981\u8fd8\u662f\u8981\u60f3\u6e05\u695a\u81ea\u5df1\u8981\u4ec0\u4e48\u3002
\u5176\u5b9e\u6211\u662f\u4e00\u76f4\u4e0d\u600e\u4e48\u7126\u8651\u7684\u4eba\u3002\u4f46\u662f\uff0c\u603b\u662f\u4f1a\u9047\u5230\u670b\u53cb\u6765\u54ed\u8bc9\u4ed6\u4eec\u7684\u7126\u8651\u3002\u6211\u662f\u8ba4\u4e3a\u7126\u8651\u65e0\u7528\u6240\u4ee5\u4e0d\u7126\u8651\uff0c\u8ba4\u4e3a\u73b0\u72b6\u80af\u5b9a\u6709\u5bf9\u5e94\u7684\u539f\u56e0\uff0c\u53ea\u8981\u628a\u5bf9\u5e94\u7684\u539f\u56e0\u89e3\u51b3\u4e86\u5c31\u4e0d\u4f1a\u7126\u8651\u4e86\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#_12","title":"\u5b9a\u65f6\u53cd\u601d","text":"\u8fd9\u4e2a\u5e94\u8be5\u662f\u4fe1\u606f\u8f93\u5165\u4ee5\u540e\u7684\u5de5\u4f5c\u4e86\u3002
\u5728\u6211\u770b\u6765\uff0c\u53cd\u601d\u8fed\u4ee3\u662f\u6700\u4e3a\u91cd\u8981\u7684\u6280\u80fd\u4e4b\u4e00\u3002
\u4f46\u662f\u5177\u4f53\u7684\u53ef\u80fd\u4ee5\u540e\u4f1a\u53e6\u5199\u4e00\u7bc7\u6587\u7ae0\uff0c\u4e0d\u8fc7\u5728 24-12-29 \u8fd9\u7bc7\u6587\u7ae0\u4e2d\u4e5f\u6709\u63d0\u53ca\u3002
","tags":["Blog"]},{"location":"Blogs/posts/24-12-30/#reference","title":"Reference","text":"\u7ea6 192 \u4e2a\u5b57 375 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u4e09\u7ef4\u91cd\u5efa
#\u590d\u73b0
","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/FreeSplatter%20%E4%BB%A3%E7%A0%81%E8%A7%A3%E8%AF%BB/#freesplatter","title":"FreeSplatter \u4ee3\u7801\u89e3\u8bfb","text":"","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/FreeSplatter%20%E4%BB%A3%E7%A0%81%E8%A7%A3%E8%AF%BB/#views_to_3d","title":"\u7a00\u758f\u91cd\u5efa\u5bf9\u8c61 views_to_3d","text":"Pythondef run_views_to_3d(\n self, \n image_files, # \u8f93\u5165\u7684\u56fe\u50cf\u6587\u4ef6\u5217\u8868\n do_rembg=False, # \u662f\u5426\u79fb\u9664\u56fe\u50cf\u80cc\u666f\n gs_type='2DGS', # \u9ad8\u65af\u6e32\u67d3\u7c7b\u578b\uff1a2DGS \u6216 3DGS\n mesh_reduction=0.5, # \u7f51\u683c\u7b80\u5316\u6bd4\u4f8b\n cache_dir=None, # \u7f13\u5b58\u76ee\u5f55\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\uff0c\u907f\u514d\u788e\u7247\u5316\n\n # \u521b\u5efa\u8f93\u51fa\u76ee\u5f55\n self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')\n os.makedirs(self.output_dir, exist_ok=True)\n\n # \u56fe\u50cf\u9884\u5904\u7406\uff1a\u52a0\u8f7d\u548c\u5904\u7406\u8f93\u5165\u56fe\u50cf\n images, alphas = [], [] # \u56fe\u50cf\u548c alpha \u901a\u9053\u5b58\u50a8\n for image_file in image_files:\n if isinstance(image_file, tuple): # \u517c\u5bb9\u4f20\u5165\u5143\u7ec4\u7684\u60c5\u51b5\n image_file = image_file[0]\n image = Image.open(image_file) # \u6253\u5f00\u56fe\u50cf\n w, h = image.size # \u83b7\u53d6\u56fe\u50cf\u5c3a\u5bf8\n\n # \u53ef\u9009\uff1a\u79fb\u9664\u80cc\u666f\n image_rgba = self.run_segmentation(image) # \u80cc\u666f\u79fb\u9664\n if image.mode == 'RGBA': # \u5982\u679c\u5df2\u6709 alpha \u901a\u9053\n image, alpha = rgba_to_white_background(image_rgba) # \u8f6c\u6362\u4e3a\u767d\u80cc\u666f\n image = v2.functional.center_crop(image, min(h, w)) # \u5c45\u4e2d\u88c1\u526a\n alpha = v2.functional.center_crop(alpha, min(h, w)) # \u88c1\u526a alpha \u901a\u9053\n else: # \u5982\u679c\u6ca1\u6709 alpha \u901a\u9053\n image_rgba = resize_foreground(image_rgba, 0.9) # \u7f29\u653e\u524d\u666f\n image, alpha = rgba_to_white_background(image_rgba) # \u8f6c\u6362\u4e3a\u767d\u80cc\u666f\n\n # \u8c03\u6574\u5206\u8fa8\u7387\u81f3 512x512\n image = v2.functional.resize(image, 512, interpolation=3, antialias=True).clamp(0, 1)\n alpha = v2.functional.resize(alpha, 512, interpolation=0, antialias=True).clamp(0, 1)\n\n # \u4fdd\u5b58\u5904\u7406\u540e\u7684\u56fe\u50cf\u548c alpha \u901a\u9053\n images.append(image)\n alphas.append(alpha)\n\n # \u5c06\u56fe\u50cf\u548c alpha \u901a\u9053\u5806\u53e0\u4e3a\u5f20\u91cf\n images = torch.stack(images, dim=0)\n alphas = torch.stack(alphas, dim=0)\n\n # \u751f\u6210\u53ef\u89c6\u5316\u62fc\u63a5\u56fe\u50cf\n images_vis = v2.functional.to_pil_image(rearrange(images, 'n c h w -> c h (n w)'))\n\n # \u8c03\u7528\u6838\u5fc3\u91cd\u5efa\u51fd\u6570\n legends = [f'V{i}' for i in range(1, 1 + len(images))] # \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u751f\u6210\u56fe\u4f8b\n gs_vis_path, video_path, mesh_fine_path, fig = self.run_freesplatter_object(\n images, alphas, legends=legends, gs_type=gs_type, mesh_reduction=mesh_reduction\n )\n\n return images_vis, gs_vis_path, video_path, mesh_fine_path, fig\n\n\ndef run_freesplatter_object(\n self, \n images, # \u8f93\u5165\u56fe\u50cf\u5f20\u91cf\n alphas, # \u56fe\u50cf\u7684 alpha \u901a\u9053\u5f20\u91cf\n legends=None, # \u56fe\u50cf\u89c6\u89d2\u7684\u56fe\u4f8b\n gs_type='2DGS', # \u9ad8\u65af\u6e32\u67d3\u7c7b\u578b\n mesh_reduction=0.5, # \u7f51\u683c\u7b80\u5316\u6bd4\u4f8b\n):\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n device = self.device\n\n # \u6839\u636e\u6e32\u67d3\u7c7b\u578b\u9009\u62e9\u6a21\u578b\n freesplatter = self.freesplatter_2dgs if gs_type == '2DGS' else self.freesplatter\n\n # \u5c06\u56fe\u50cf\u548c alpha \u901a\u9053\u79fb\u52a8\u5230 GPU\n images, alphas = images.to(device), alphas.to(device)\n\n # **\u6b65\u9aa4 1\uff1a\u751f\u6210\u9ad8\u65af\u70b9\u4e91**\n t0 = time.time()\n with torch.inference_mode():\n gaussians = freesplatter.forward_gaussians(images.unsqueeze(0)) # \u751f\u6210\u9ad8\u65af\u70b9\u4e91\n t1 = time.time()\n\n # **\u6b65\u9aa4 2\uff1a\u4f30\u8ba1\u76f8\u673a\u53c2\u6570\u5e76\u53ef\u89c6\u5316**\n c2ws_pred, focals_pred = freesplatter.estimate_poses(\n images, gaussians, masks=alphas, use_first_focal=True, pnp_iter=10\n ) # \u4f30\u8ba1\u76f8\u673a\u5916\u53c2\u548c\u7126\u8ddd\n fig = self.visualize_cameras_object(images, c2ws_pred, focals_pred, legends=legends) # \u53ef\u89c6\u5316\u76f8\u673a\u4f4d\u59ff\n t2 = time.time()\n\n # **\u6b65\u9aa4 3\uff1a\u4fdd\u5b58\u9ad8\u65af\u70b9\u4e91**\n gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')\n save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3, pad_2dgs_scale=True)\n print(f'Save gaussian at {gs_vis_path}')\n\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 4\uff1a\u751f\u6210\u73af\u7ed5\u89c6\u89d2\u89c6\u9891**\n with torch.inference_mode():\n c2ws_video = get_circular_cameras(N=120, elevation=0, radius=2.0, normalize=True).to(device) # \u73af\u7ed5\u76f8\u673a\u8f68\u8ff9\n fx = fy = focals_pred.mean() / 512.0 # \u8ba1\u7b97\u5f52\u4e00\u5316\u7126\u8ddd\n cx = cy = torch.ones_like(fx) * 0.5 # \u4e2d\u5fc3\u70b9\u5f52\u4e00\u5316\n fxfycxcy_video = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_video.shape[0], 1).to(device)\n\n video_frames = freesplatter.forward_renderer(\n gaussians, c2ws_video.unsqueeze(0), fxfycxcy_video.unsqueeze(0)\n )['image'][0].clamp(0, 1) # \u6e32\u67d3\u89c6\u9891\u5e27\n\n video_path = os.path.join(self.output_dir, 'gs.mp4')\n save_video(video_frames, video_path, fps=30) # \u4fdd\u5b58\u89c6\u9891\n print(f'Save video at {video_path}')\n t3 = time.time()\n\n torch.cuda.empty_cache() # \u518d\u6b21\u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 5\uff1aTSDF \u878d\u5408\u751f\u6210\u7f51\u683c**\n with torch.inference_mode():\n c2ws_fusion = get_fibonacci_cameras(N=120, radius=2.0) # TSDF \u878d\u5408\u76f8\u673a\u8f68\u8ff9\n c2ws_fusion, _ = normalize_cameras(\n c2ws_fusion, camera_position=torch.tensor([0., -2., 0.]), camera_system='opencv'\n ) # \u76f8\u673a\u5f52\u4e00\u5316\n c2ws_fusion = c2ws_fusion.to(device)\n c2ws_fusion_reference = torch.linalg.inv(c2ws_fusion[0:1]) @ c2ws_fusion\n fx = fy = focals_pred.mean() / 512.0\n cx = cy = torch.ones_like(fx) * 0.5\n fov = np.rad2deg(np.arctan(0.5 / fx.item())) * 2\n fxfycxcy_fusion = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_fusion.shape[0], 1).to(device)\n\n fusion_render_results = freesplatter.forward_renderer(\n gaussians, c2ws_fusion_reference.unsqueeze(0), fxfycxcy_fusion.unsqueeze(0)\n )\n images_fusion = fusion_render_results['image'][0].clamp(0, 1).permute(0, 2, 3, 1)\n alphas_fusion = fusion_render_results['alpha'][0].permute(0, 2, 3, 1)\n depths_fusion = fusion_render_results['depth'][0].permute(0, 2, 3, 1)\n\n # TSDF \u878d\u5408\u5904\u7406\n fusion_images = (images_fusion.detach().cpu().numpy() * 255).clip(0, 255).astype(np.uint8)\n fusion_depths = depths_fusion.detach().cpu().numpy()\n fusion_alphas = alphas_fusion.detach().cpu().numpy()\n fusion_masks = (fusion_alphas > 1e-2).astype(np.uint8)\n fusion_depths = fusion_depths * fusion_masks - np.ones_like(fusion_depths) * (1 - fusion_masks)\n\n fusion_c2ws = c2ws_fusion.detach().cpu().numpy()\n\n # \u751f\u6210\u7f51\u683c\u6587\u4ef6\n mesh_path = os.path.join(self.output_dir, 'mesh.obj')\n rgbd_to_mesh(\n fusion_images, fusion_depths, fusion_c2ws, fov, mesh_path, cam_elev_thr=-90\n ) # TSDF \u878d\u5408\u751f\u6210\u7f51\u683c\n print(f'Save mesh at {mesh_path}')\n t4 = time.time()\n\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n # **\u6b65\u9aa4 6\uff1a\u4f18\u5316\u7eb9\u7406**\n cam_pos = c2ws_fusion[:, :3, 3].cpu().numpy() # \u83b7\u53d6\u76f8\u673a\u4f4d\u7f6e\n cam_inds = torch.from_numpy(fpsample.fps_sampling(cam_pos, 16).astype(int)).to(device=device) # \u91c7\u6837\u5173\u952e\u5e27\u76f8\u673a\n\n # \u4f18\u5316\u7f51\u683c\u7eb9\u7406\n alphas_bake = alphas_fusion[cam_inds]\n images_bake = (images_fusion[cam_inds] - (1 - alphas_bake)) / alphas_bake.clamp(min=1e-6)\n\n fxfycxcy = fxfycxcy_fusion[cam_inds].clone()\n intrinsics = torch.eye(3).unsqueeze(0).repeat(len(cam_inds), 1, 1).to(fxfycxcy)\n intrinsics[:, 0, 0] = fxfycxcy[:, 0]\n intrinsics[:, 0, 2] = fxfycxcy[:, 2]\n intrinsics[:, 1, 1] = fxfycxcy[:, 1]\n intrinsics[:, 1, 2] = fxfycxcy[:, 3]\n\n out_mesh = trimesh.load(str(mesh_path), process=False) # \u52a0\u8f7d\u7f51\u683c\n out_mesh = optimize_mesh(\n out_mesh, \n images_bake, \n alphas_bake.squeeze(-1), \n c2ws_fusion[cam_inds].inverse(), \n intrinsics,\n simplify=mesh_reduction,\n verbose=False\n ) # \u4f18\u5316\u7eb9\u7406\n mesh_fine_path = os.path.join(self.output_dir, 'mesh.glb')\n out_mesh.export(mesh_fine_path) # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7f51\u683c\n print(f\"Save optimized mesh at {mesh_fine_path}\")\n t5 = time.time()\n\n # \u6253\u5370\u65f6\u95f4\u7edf\u8ba1\n print(f'Generate Gaussians: {t1-t0:.2f} seconds.')\n print(f'Estimate poses: {t2-t1:.2f} seconds.')\n print(f'Generate video: {t3-t2:.2f} seconds.')\n print(f'Generate mesh: {t4-t3:.2f} seconds.')\n print(f'Optimize mesh: {t5-t4:.2f} seconds.')\n\n return gs_vis_path, video_path, mesh_fine_path, fig\n
def visualize_cameras_object(\n self, \n images, # \u8f93\u5165\u7684\u56fe\u50cf\n c2ws, # \u76f8\u673a\u4f4d\u59ff\uff08\u4e16\u754c\u5750\u6807\u7cfb\u5230\u76f8\u673a\u5750\u6807\u7cfb\u7684\u53d8\u6362\u77e9\u9635\uff09\n focal_length, # \u7126\u8ddd\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\uff0c\u9ed8\u8ba4\u65e0\n):\n # **1. \u5904\u7406\u56fe\u50cf**\uff1a\u8c03\u6574\u56fe\u50cf\u5927\u5c0f\uff0c\u9650\u5236\u50cf\u7d20\u503c\u5728 [0, 1] \u8303\u56f4\uff0c\u7136\u540e\u8f6c\u6362\u4e3a NumPy \u683c\u5f0f\n images = v2.functional.resize(images, 128, interpolation=3, antialias=True).clamp(0, 1)\n images = (images.permute(0, 2, 3, 1).detach().cpu().numpy() * 255).astype(np.uint8)\n\n # **2. \u76f8\u673a\u4f4d\u59ff\u8f6c\u6362**\uff1a\u5c06 c2ws\uff08\u76f8\u673a\u4f4d\u59ff\uff09\u8f6c\u6362\u5230\u4e16\u754c\u5750\u6807\u7cfb\u4e0b\n cam2world = create_camera_to_world(torch.tensor([0, -2, 0]), camera_system='opencv').to(c2ws) # \u521b\u5efa\u4ece\u76f8\u673a\u5230\u4e16\u754c\u7684\u53d8\u6362\n transform = cam2world @ torch.linalg.inv(c2ws[0:1]) # \u8ba1\u7b97\u7b2c\u4e00\u4e2a\u76f8\u673a\u7684\u53c2\u8003\u53d8\u6362\n c2ws = transform @ c2ws # \u66f4\u65b0\u6240\u6709\u76f8\u673a\u7684\u4f4d\u59ff\n c2ws = c2ws.detach().cpu().numpy()\n c2ws[:, :, 1:3] *= -1 # \u4ece OpenCV \u5230 OpenGL \u5750\u6807\u7cfb\u7684\u8f6c\u6362\n\n # **3. \u8ba1\u7b97\u76f8\u673a\u89c6\u573a\u89d2\uff08FOV\uff09**\n focal_length = focal_length.mean().detach().cpu().numpy()\n fov = np.rad2deg(np.arctan(256.0 / focal_length)) * 2\n\n # **4. \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u6307\u5b9a\u989c\u8272**\n colors = [cmap(i / len(images))[:3] for i in range(len(images))]\n\n # **5. \u8bbe\u7f6e\u56fe\u4f8b**\uff1a\u5982\u679c\u672a\u63d0\u4f9b\uff0c\u9ed8\u8ba4\u4e3a\u7a7a\n legends = [None] * len(images) if legends is None else legends\n\n # **6. \u8c03\u7528\u53ef\u89c6\u5316\u5de5\u5177 CameraVisualizer**\n viz = CameraVisualizer(c2ws, legends, colors, images=images)\n fig = viz.update_figure(\n 3, # \u7ef4\u5ea6\n height=320, # \u56fe\u5f62\u9ad8\u5ea6\n line_width=5, # \u76f8\u673a\u7ebf\u5bbd\n base_radius=1, # \u57fa\u51c6\u76f8\u673a\u4f4d\u7f6e\u534a\u5f84\n zoom_scale=1, # \u7f29\u653e\u6bd4\u4f8b\n fov_deg=fov, # \u89c6\u573a\u89d2\n show_grid=True, # \u662f\u5426\u663e\u793a\u7f51\u683c\n show_ticklabels=True, # \u662f\u5426\u663e\u793a\u5750\u6807\u8f74\u523b\u5ea6\n show_background=True, # \u662f\u5426\u663e\u793a\u80cc\u666f\n y_up=False, # Y \u8f74\u65b9\u5411\u5411\u4e0b\n )\n return fig\n\n\ndef run_views_to_scene(\n self, \n image1, # \u8f93\u5165\u7684\u7b2c\u4e00\u4e2a\u56fe\u50cf\n image2, # \u8f93\u5165\u7684\u7b2c\u4e8c\u4e2a\u56fe\u50cf\n cache_dir=None, # \u8f93\u51fa\u7f13\u5b58\u76ee\u5f55\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n # **1. \u521b\u5efa\u8f93\u51fa\u76ee\u5f55**\n self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')\n os.makedirs(self.output_dir, exist_ok=True)\n\n # **2. \u56fe\u50cf\u9884\u5904\u7406**\n images = []\n for image in [image1, image2]:\n w, h = image.size # \u83b7\u53d6\u56fe\u50cf\u5bbd\u9ad8\n image = torch.from_numpy(np.asarray(image) / 255.0).float() # \u8f6c\u4e3a NumPy\uff0c\u518d\u8f6c\u4e3a\u5f20\u91cf\n image = rearrange(image, 'h w c -> c h w') # \u8c03\u6574\u7ef4\u5ea6\u4e3a (C, H, W)\n image = v2.functional.center_crop(image, min(h, w)) # \u4e2d\u5fc3\u88c1\u526a\n image = v2.functional.resize(image, 512, interpolation=3, antialias=True).clamp(0, 1) # \u8c03\u6574\u5927\u5c0f\u5e76\u5f52\u4e00\u5316\n images.append(image) # \u6dfb\u52a0\u5230\u5217\u8868\n\n # **3. \u5c06\u56fe\u50cf\u5806\u53e0\u6210\u4e00\u4e2a\u5f20\u91cf**\n images = torch.stack(images, dim=0)\n\n # **4. \u751f\u6210\u62fc\u63a5\u53ef\u89c6\u5316\u56fe\u50cf**\n images_vis = v2.functional.to_pil_image(rearrange(images, 'n c h w -> c h (n w)'))\n\n # **5. \u8c03\u7528\u573a\u666f\u91cd\u5efa\u65b9\u6cd5**\n legends = [f'V{i}' for i in range(1, 1+len(images))] # \u4e3a\u89c6\u89d2\u751f\u6210\u56fe\u4f8b\n gs_vis_path, video_path, fig = self.run_freesplatter_scene(images, legends=legends)\n\n return images_vis, gs_vis_path, video_path, fig\n\n\ndef run_freesplatter_scene(\n self, \n images, # \u8f93\u5165\u56fe\u50cf\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\n):\n torch.cuda.empty_cache() # \u6e05\u7406\u663e\u5b58\n\n freesplatter = self.freesplatter_scene # \u4f7f\u7528 FreeSplatter \u573a\u666f\u6a21\u578b\n\n device = self.device\n images = images.to(device) # \u5c06\u56fe\u50cf\u79fb\u52a8\u5230 GPU\n\n # **1. \u751f\u6210\u9ad8\u65af\u70b9\u4e91**\n t0 = time.time()\n with torch.inference_mode():\n gaussians = freesplatter.forward_gaussians(images.unsqueeze(0)) # \u8c03\u7528\u9ad8\u65af\u751f\u6210\u5668\n t1 = time.time()\n\n # **2. \u4f30\u8ba1\u76f8\u673a\u4f4d\u59ff**\n c2ws_pred, focals_pred = freesplatter.estimate_poses(images, gaussians, use_first_focal=True, pnp_iter=10)\n # **2.1 \u5f52\u4e00\u5316\u76f8\u673a\u57fa\u7ebf**\n baseline_pred = (c2ws_pred[:, :3, 3] - c2ws_pred[:1, :3, 3]).norm() + 1e-2 # \u8ba1\u7b97\u76f8\u673a\u57fa\u7ebf\n scale_factor = 1.0 / baseline_pred # \u5f52\u4e00\u5316\u6bd4\u4f8b\n c2ws_pred = c2ws_pred.clone()\n c2ws_pred[:, :3, 3] *= scale_factor # \u7f29\u653e\u76f8\u673a\u4f4d\u7f6e\n\n # **3. \u53ef\u89c6\u5316\u76f8\u673a**\n fig = self.visualize_cameras_scene(images, c2ws_pred, focals_pred, legends=legends)\n t2 = time.time()\n\n # **4. \u4fdd\u5b58\u9ad8\u65af\u70b9\u4e91**\n gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')\n save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3) # \u4fdd\u5b58\u70b9\u4e91\n print(f'Save gaussian at {gs_vis_path}')\n\n # **5. \u6e32\u67d3\u89c6\u9891**\n with torch.inference_mode():\n c2ws_video = generate_interpolated_path(c2ws_pred.detach().cpu().numpy()[:, :3, :], n_interp=120) # \u751f\u6210\u63d2\u503c\u8def\u5f84\n c2ws_video = torch.cat([\n torch.from_numpy(c2ws_video), \n torch.tensor([0, 0, 0, 1]).reshape(1, 1, 4).repeat(c2ws_video.shape[0], 1, 1)\n ], dim=1).to(gaussians) # \u5c06\u8def\u5f84\u8f6c\u6362\u4e3a\u9f50\u6b21\u5750\u6807\n fx = fy = focals_pred.mean() / 512.0 # \u8ba1\u7b97\u5f52\u4e00\u5316\u7126\u8ddd\n cx = cy = torch.ones_like(fx) * 0.5 # \u5f52\u4e00\u5316\u4e2d\u5fc3\u70b9\n fxfycxcy_video = torch.tensor([fx, fy, cx, cy]).unsqueeze(0).repeat(c2ws_video.shape[0], 1).to(device)\n\n video_frames = freesplatter.forward_renderer(\n gaussians, # \u9ad8\u65af\u70b9\u4e91\n c2ws_video.unsqueeze(0), # \u76f8\u673a\u8f68\u8ff9\n fxfycxcy_video.unsqueeze(0), # \u76f8\u673a\u53c2\u6570\n rescale=scale_factor.reshape(1).to(gaussians) # \u7f29\u653e\u6bd4\u4f8b\n )['image'][0].clamp(0, 1) # \u6e32\u67d3\u56fe\u50cf\u5e27\n\n video_path = os.path.join(self.output_dir, 'gs.mp4')\n save_video(video_frames, video_path, fps=30) # \u4fdd\u5b58\u89c6\u9891\n print(f'Save video at {video_path}')\n t3 = time.time()\n\n # **6. \u6253\u5370\u65f6\u95f4\u7edf\u8ba1**\n print(f'Generate Gaussians: {t1-t0:.2f} seconds.')\n print(f'Estimate poses: {t2-t1:.2f} seconds.')\n print(f'Generate video: {t3-t2:.2f} seconds.')\n\n return gs_vis_path, video_path, fig\n\n\ndef visualize_cameras_scene(\n self, \n images, # \u8f93\u5165\u7684\u56fe\u50cf\n c2ws, # \u76f8\u673a\u4f4d\u59ff\n focal_length, # \u7126\u8ddd\n legends=None, # \u6bcf\u4e2a\u89c6\u89d2\u7684\u56fe\u4f8b\n):\n # **1. \u5904\u7406\u56fe\u50cf**\uff1a\u8c03\u6574\u5206\u8fa8\u7387\uff0c\u5f52\u4e00\u5316\uff0c\u8f6c\u6362\u4e3a NumPy \u683c\u5f0f\n images = v2.functional.resize(images, 128, interpolation=3, antialias=True).clamp(0, 1)\n images = (images.permute(0, 2, 3, 1).detach().cpu().numpy() * 255).astype(np.uint8)\n\n # **2. \u8f6c\u6362\u76f8\u673a\u4f4d\u59ff\u5750\u6807\u7cfb**\n c2ws = c2ws.detach().cpu().numpy()\n c2ws[:, :, 1:3] *= -1 # OpenCV \u5230 OpenGL \u8f6c\u6362\n\n # **3. \u8ba1\u7b97\u89c6\u573a\u89d2\uff08FOV\uff09**\n focal_length = focal_length.mean().detach().cpu().numpy()\n fov = np.rad2deg(np.arctan(256.0 / focal_length)) * 2\n\n # **4. \u4e3a\u6bcf\u4e2a\u89c6\u89d2\u5206\u914d\u989c\u8272**\n colors = [cmap(i / len(images))[:3] for i in range(len(images))]\n\n # **5. \u8bbe\u7f6e\u56fe\u4f8b**\n legends = [None] * len(images) if legends is None else legends\n\n # **6. \u53ef\u89c6\u5316\u76f8\u673a**\n viz = CameraVisualizer(c2ws, legends, colors, images=images)\n fig = viz.update_figure(\n 2, \n height=320,\n line_width=5,\n base_radius=1, \n zoom_scale=1, \n fov_deg=fov, \n show_grid=True, \n show_ticklabels=True, \n show_background=True, \n y_up=False,\n )\n return fig\n
","tags":["\u79d1\u7814","\u4e09\u7ef4\u91cd\u5efa","\u590d\u73b0"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/","title":"Gaussian_Splatting_Code","text":"\u7ea6 982 \u4e2a\u5b57 34 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u590d\u73b0
#\u4e09\u7ef4\u91cd\u5efa
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#gaussian_splatting_code","title":"Gaussian_Splatting_Code","text":"\u4e3b\u8981\u6709 colmap \u548c blender \u4e24\u79cd\u6570\u636e\u7c7b\u578b\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#1-colmap","title":"1. Colmap \u6570\u636e\u96c6\u52a0\u8f7d\u8fc7\u7a0b","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#11","title":"1.1 \u52a0\u8f7d\u51fd\u6570","text":"readColmapSceneInfo
\uff0c\u8c03\u7528\u4e86\u4e00\u7cfb\u5217\u5b50\u51fd\u6570\u4ee5\u52a0\u8f7d\u76f8\u673a\u53c2\u6570\u3001\u70b9\u4e91\u548c\u76f8\u5173\u6587\u4ef6\u3002sparse/
\u6587\u4ef6\u5939\uff0c\u5305\u542b\u76f8\u673a\u53c2\u6570\u6587\u4ef6\u3001\u70b9\u4e91\u6587\u4ef6\u7b49\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythoncameras_extrinsic_file = os.path.join(path, \"sparse/0\", \"images.bin\")\ncam_extrinsics = read_extrinsics_binary(cameras_extrinsic_file)\n
\u5982\u679c images.bin
\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u52a0\u8f7d images.txt
\uff1a
cameras_extrinsic_file = os.path.join(path, \"sparse/0\", \"images.txt\")\ncam_extrinsics = read_extrinsics_text(cameras_extrinsic_file)\n
\u5916\u53c2\u5305\u62ec\uff1a
R
)\u3002T
)\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythoncameras_intrinsic_file = os.path.join(path, \"sparse/0\", \"cameras.bin\")\ncam_intrinsics = read_intrinsics_binary(cameras_intrinsic_file)\n
\u5982\u679c cameras.bin
\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u52a0\u8f7d cameras.txt
\uff1a
cameras_intrinsic_file = os.path.join(path, \"sparse/0\", \"cameras.txt\")\ncam_intrinsics = read_intrinsics_text(cameras_intrinsic_file)\n
\u5185\u53c2\u5305\u62ec\uff1a
focal length
\uff09\u3002principal point
\uff09\u3002width
\u548c height
\uff09\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonply_path = os.path.join(path, \"sparse/0/points3D.ply\")\nbin_path = os.path.join(path, \"sparse/0/points3D.bin\")\ntxt_path = os.path.join(path, \"sparse/0/points3D.txt\")\n\nif not os.path.exists(ply_path):\n print(\"Converting point3d.bin to .ply, will happen only the first time you open the scene.\")\n xyz, rgb, _ = read_points3D_binary(bin_path)\n storePly(ply_path, xyz, rgb)\npcd = fetchPly(ply_path)\n
points3D.bin
points3D.txt
points3D.ply
\uff08\u5982\u679c\u5b58\u5728\u5219\u76f4\u63a5\u52a0\u8f7d\uff0c\u5426\u5219\u4ece bin
\u6216 txt
\u8f6c\u6362\u4e3a .ply
\uff09\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonif eval:\n cam_names = [cam_extrinsics[cam_id].name for cam_id in cam_extrinsics]\n cam_names = sorted(cam_names)\n test_cam_names_list = [name for idx, name in enumerate(cam_names) if idx % llffhold == 0]\nelse:\n test_cam_names_list = []\n
eval
\u53c2\u6570\u542f\u7528\u3002llffhold=8
\uff09\u9009\u53d6\u4e00\u4e2a\u4f5c\u4e3a\u6d4b\u8bd5\u96c6\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonnerf_normalization = getNerfppNorm(train_cam_infos)\n
translate
) \u548c\u534a\u5f84 (radius
)\u3002\u51fd\u6570\u8fd4\u56de\u4e00\u4e2a SceneInfo
\u6570\u636e\u7ed3\u6784\uff1a
point_cloud
\uff1a\u70b9\u4e91\u6570\u636e\u3002train_cameras
\uff1a\u8bad\u7ec3\u76f8\u673a\u5217\u8868\u3002test_cameras
\uff1a\u6d4b\u8bd5\u76f8\u673a\u5217\u8868\u3002nerf_normalization
\uff1a\u573a\u666f\u5f52\u4e00\u5316\u53c2\u6570\u3002ply_path
\uff1a\u70b9\u4e91\u6587\u4ef6\u8def\u5f84\u3002readNerfSyntheticInfo
\uff0c\u4ece Blender \u5bfc\u51fa\u7684 JSON \u6587\u4ef6\u52a0\u8f7d\u76f8\u673a\u548c\u56fe\u50cf\u4fe1\u606f\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythontrain_cam_infos = readCamerasFromTransforms(path, \"transforms_train.json\", depths_folder, white_background, False, extension)\ntest_cam_infos = readCamerasFromTransforms(path, \"transforms_test.json\", depths_folder, white_background, True, extension)\n
transforms_train.json
\u548c transforms_test.json
\u3002transforms_train.json
:transform_matrix
\uff08\u76f8\u673a\u5230\u4e16\u754c\u7684\u53d8\u6362\u77e9\u9635\uff09\u3002camera_angle_x
) \u7528\u4e8e\u8ba1\u7b97\u7126\u8ddd\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonif not os.path.exists(ply_path):\n num_pts = 100_000\n print(f\"Generating random point cloud ({num_pts})...\")\n xyz = np.random.random((num_pts, 3)) * 2.6 - 1.3\n shs = np.random.random((num_pts, 3)) / 255.0\n storePly(ply_path, xyz, SH2RGB(shs) * 255)\npcd = fetchPly(ply_path)\n
[-1.3, 1.3]
\u3002\u4ee3\u7801\u5982\u4e0b\uff1a
Pythonnerf_normalization = getNerfppNorm(train_cam_infos)\n
translate
) \u548c\u534a\u5f84 (radius
)\u3002\u51fd\u6570\u8fd4\u56de\u4e00\u4e2a SceneInfo
\u6570\u636e\u7ed3\u6784\uff1a
point_cloud
\uff1a\u751f\u6210\u7684\u70b9\u4e91\u3002train_cameras
\uff1a\u8bad\u7ec3\u76f8\u673a\u5217\u8868\u3002test_cameras
\uff1a\u6d4b\u8bd5\u76f8\u673a\u5217\u8868\u3002nerf_normalization
\uff1a\u573a\u666f\u5f52\u4e00\u5316\u53c2\u6570\u3002ply_path
\uff1a\u70b9\u4e91\u6587\u4ef6\u8def\u5f84\u3002images.bin
\u548c cameras.bin
\u4e2d\u52a0\u8f7d\u5916\u53c2\u548c\u5185\u53c2 \u4ece transforms_train.json
\u4e2d\u52a0\u8f7d\u53d8\u6362\u77e9\u9635 \u70b9\u4e91 \u4ece points3D.bin
\u6216 points3D.txt
\u52a0\u8f7d \u968f\u673a\u751f\u6210 10 \u4e07\u4e2a\u70b9 \u56fe\u50cf\u6570\u636e \u5b58\u50a8\u5728 images/
\u6587\u4ef6\u5939 \u8def\u5f84\u7531 JSON \u6587\u4ef6\u6307\u5b9a \u6df1\u5ea6\u56fe \u53ef\u9009\uff0c\u9700 depth_params.json
\u5b9a\u4e49 \u53ef\u9009\uff0c\u9700\u63d0\u4f9b\u6df1\u5ea6\u56fe\u6587\u4ef6\u5939 \u5f52\u4e00\u5316 \u57fa\u4e8e\u76f8\u673a\u4f4d\u7f6e\u8ba1\u7b97\u573a\u666f\u4e2d\u5fc3\u548c\u534a\u5f84 \u540c\u4e0a \u6d4b\u8bd5\u96c6\u5212\u5206 \u6bcf 8 \u4e2a\u89c6\u89d2\u5212\u5206\u4e00\u4e2a\u5230\u6d4b\u8bd5\u96c6\uff0c\u6216\u8bfb\u53d6 test.txt
\u6d4b\u8bd5\u96c6\u901a\u8fc7 transforms_test.json
\u6307\u5b9a \u80cc\u666f\u989c\u8272 \u65e0 \u53ef\u9009\u767d\u8272\u6216\u9ed1\u8272\u80cc\u666f","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#4_1","title":"4. \u6240\u9700\u51c6\u5907\u7684\u6587\u4ef6","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_Code/#colmap","title":"Colmap \u6570\u636e\u96c6","text":"sparse/0/images.bin
\u6216 images.txt
\u3002sparse/0/cameras.bin
\u6216 cameras.txt
\u3002sparse/0/points3D.bin
\u6216 points3D.txt
\u3002images/
\u3002sparse/0/depth_params.json
\uff08\u6df1\u5ea6\u53c2\u6570\uff09\u3002sparse/0/test.txt
\uff08\u6d4b\u8bd5\u96c6\u5212\u5206\u6587\u4ef6\uff09\u3002transforms_train.json
\u3002transforms_test.json
\u3002white_background
\uff09\u3002Random Point Initialization \u00b7 Issue #39 \u00b7 graphdeco-inria/gaussian-splatting \u00b7 GitHub
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/","title":"Gaussian Splatting \u590d\u73b0","text":"\u7ea6 1407 \u4e2a\u5b57 4 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
#\u590d\u73b0
#\u4e09\u7ef4\u91cd\u5efa
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#gaussian-splatting","title":"Gaussian Splatting \u590d\u73b0","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#_1","title":"\u5b98\u65b9\u6570\u636e\u96c6\u590d\u73b0","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#prepare","title":"prepare","text":"Text Onlygit clone https://github.com/graphdeco-inria/gaussian-splatting --recursive\nconda env create --file environment.yml\nconda activate gaussian_splatting\n
python train.py -s ./data/tandt/train/ -m ./output/train/ --eval\n\nOptimizing ./output/train/\nOutput folder: ./output/train/ [31/12 20:58:06]\nTensorboard not available: not logging progress [31/12 20:58:06]\n------------LLFF HOLD------------- [31/12 20:58:08]\nReading camera 301/301 [31/12 20:58:08]\nConverting point3d.bin to .ply, will happen only the first time you open the scene. [31/12 20:58:08]\nLoading Training Cameras [31/12 20:58:09]\nLoading Test Cameras [31/12 20:58:19]\nNumber of points at initialisation : 182686 [31/12 20:58:20]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2589 | 7000/30000 [02:04<07:36, 50.34it/s, Loss=0.0985708, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.07567951896865116 PSNR 19.8115311672813 [31/12 21:00:25]\n\n[ITER 7000] Evaluating train: L1 0.05251172706484795 PSNR 21.924707794189455 [31/12 21:00:25]\n\n[ITER 7000] Saving Gaussians [31/12 21:00:25]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [10:58<00:00, 45.54it/s, Loss=0.0425664, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating test: L1 0.05784237639684426 PSNR 22.03640069459614 [31/12 21:09:19]\n\n[ITER 30000] Evaluating train: L1 0.025540136173367502 PSNR 27.51155662536621 [31/12 21:09:19]\n\n[ITER 30000] Saving Gaussians [31/12 21:09:19]\n\nTraining complete. [31/12 21:09:28]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#render","title":"render","text":"Text Onlypython render.py -m ./output/train/\n\nLooking for config file in ./output/train/cfg_args\nConfig file found: ./output/train/cfg_args\nRendering ./output/train/\nLoading trained model at iteration 30000 [31/12 21:14:40]\n------------LLFF HOLD------------- [31/12 21:14:41]\nReading camera 301/301 [31/12 21:14:41]\nLoading Training Cameras [31/12 21:14:41]\nLoading Test Cameras [31/12 21:14:53]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 263/263 [01:41<00:00, 2.58it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 38/38 [00:15<00:00, 2.42it/s]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#evaluate","title":"evaluate","text":"Text Onlypython metrics.py -m ./output/train/\n\nScene: ./output/train/\nMethod: ours_30000\nMetric evaluation progress: 0%| | 0/38 [00:00<?, ?it/s]Downloading: \"https://download.pytorch.org/models/vgg16-397923af.pth\" to /home/fanghaotian/.cache/torch/hub/checkpoints/vgg16-397923af.pth\n100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 528M/528M [00:28<00:00, 19.4MB/s]\nDownloading: \"https://raw.githubusercontent.com/richzhang/PerceptualSimilarity/master/lpips/weights/v0.1/vgg.pth\" to /home/fanghaotian/.cache/torch/hub/checkpoints/vgg.pth\n100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 7.12k/7.12k [00:03<00:00, 2.29kB/s]\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 38/38 [07:57<00:00, 12.58s/it] 7.12k/7.12k [00:03<00:00, 2.29kB/s]\n SSIM : 0.8192384\n PSNR : 22.0094910\n LPIPS: 0.1966141\n
\u770b\u8d77\u6765\u6bd4\u8bba\u6587\u91cc\u7684\u6570\u636e\u4f4e\u3002
.\\SIBR_remoteGaussian_app.exe
\u8fdc\u7a0b\u4e0d\u80fd\u7528\uff0c issue \u4e2d\u4e5f\u672a\u89e3\u51b3scp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/ C:\\Users\\fanghaotian\\Desktop\\\n\n./SIBR_gaussianViewer_app -m C:\\Users\\fanghaotian\\Desktop\\data\\82ea91ef-6\\\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#blender","title":"\u7528 blender \u6570\u636e\u96c6","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#prepare_1","title":"prepare","text":"nerf_synthetic/lego
\u90a3\u4e2a\u662f blender \u7684\u683c\u5f0ftree -I \"*.png\"\n.\n\u2514\u2500\u2500 lego\n \u251c\u2500\u2500 test\n \u251c\u2500\u2500 train\n \u251c\u2500\u2500 transforms_test.json\n \u251c\u2500\u2500 transforms_train.json\n \u251c\u2500\u2500 transforms_val.json\n \u2514\u2500\u2500 val\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iterations30000-no-evaluation","title":"Iterations=30000 no evaluation","text":"","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#train_1","title":"train","text":"Text Onlypython train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego/\n\nOptimizing ./output/lego/\nOutput folder: ./output/lego/ [01/01 13:31:23]\nTensorboard not available: not logging progress [01/01 13:31:23]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:31:23]\nReading Training Transforms [01/01 13:31:23]\nReading Test Transforms [01/01 13:31:31]\nGenerating random point cloud (100000)... [01/01 13:31:38]\nLoading Training Cameras [01/01 13:31:39]\nLoading Test Cameras [01/01 13:31:53]\nNumber of points at initialisation : 100000 [01/01 13:31:53]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7000/30000 [01:15<04:12, 91.02it/s, Loss=0.0152277, Depth Loss=0.0000000]\n[ITER 7000] Evaluating train: L1 0.3646775007247925 PSNR 5.983335494995117 [01/01 13:33:09]\n\n[ITER 7000] Saving Gaussians [01/01 13:33:09]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [05:26<00:00, 91.97it/s, Loss=0.0105094, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating train: L1 0.6417351365089417 PSNR 2.185275435447693 [01/01 13:37:19]\n\n[ITER 30000] Saving Gaussians [01/01 13:37:19]\n\nTraining complete. [01/01 13:37:21]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#render_1","title":"render","text":"Text Onlypython render.py -m ./output/lego/\n\nLooking for config file in ./output/lego/cfg_args\nConfig file found: ./output/lego/cfg_args\nRendering ./output/lego/\nLoading trained model at iteration 30000 [01/01 13:41:14]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:41:14]\nReading Training Transforms [01/01 13:41:14]\nReading Test Transforms [01/01 13:41:20]\nLoading Training Cameras [01/01 13:41:28]\nLoading Test Cameras [01/01 13:41:44]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 300/300 [01:06<00:00, 4.48it/s]\nRendering progress: 0it [00:00, ?it/s]\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#metric","title":"metric","text":"Text Onlypython metrics.py -m ./output/lego/\n\nScene: ./output/lego/\nMethod: ours_30000\nMetric evaluation progress: 0it [00:00, ?it/s]\n SSIM : nan\n PSNR : nan\n LPIPS: nan\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#interactive-viewers_1","title":"Interactive Viewers","text":"Text Onlyscp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/lego C:\\Users\\fanghaotian\\Desktop\\\n\n./SIBR_gaussianViewer_app -m C:\\Users\\fanghaotian\\Desktop\\lego\n
\ud83e\udd14\uff0c\u597d\u50cf\u4e00\u5b9a\u8981 --eval\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iteratations30000-evaluation","title":"Iteratations=30000 + evaluation","text":"\u90a3\u4e48\u52a0\u4e0a\u4ee5\u540e\u7528 iterations=300000\uff08default\uff09\u518d\u8dd1\u4e00\u6b21\u3002
Text Onlypython train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego_eval/ --eval\n\nOptimizing ./output/lego_eval/\nOutput folder: ./output/lego_eval/ [01/01 13:43:45]\nTensorboard not available: not logging progress [01/01 13:43:45]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:43:45]\nReading Training Transforms [01/01 13:43:45]\nReading Test Transforms [01/01 13:43:51]\nLoading Training Cameras [01/01 13:43:58]\nLoading Test Cameras [01/01 13:44:06]\nNumber of points at initialisation : 100000 [01/01 13:44:12]\nTraining progress: 23%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7000/30000 [01:24<04:48, 79.82it/s, Loss=0.0153927, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.34677238538861277 PSNR 6.254974584579468 [01/01 13:45:38]\n\n[ITER 7000] Evaluating train: L1 0.3650033831596375 PSNR 5.939675426483155 [01/01 13:45:38]\n\n[ITER 7000] Saving Gaussians [01/01 13:45:38]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 30000/30000 [05:47<00:00, 86.33it/s, Loss=0.0095609, Depth Loss=0.0000000]\n\n[ITER 30000] Evaluating test: L1 0.557637879550457 PSNR 3.0822176444530487 [01/01 13:50:00]\n\n[ITER 30000] Evaluating train: L1 0.5475435316562652 PSNR 3.064222288131714 [01/01 13:50:00]\n\n[ITER 30000] Saving Gaussians [01/01 13:50:00]\n\nTraining complete. [01/01 13:50:04]\n\n\npython render.py -m ./output/lego_eval/\n\nLooking for config file in ./output/lego_eval/cfg_args\nConfig file found: ./output/lego_eval/cfg_args\nRendering ./output/lego_eval/\nLoading trained model at iteration 30000 [01/01 13:51:20]\nFound transforms_train.json file, assuming Blender data set! [01/01 13:51:20]\nReading Training Transforms [01/01 13:51:20]\nReading Test Transforms [01/01 13:51:26]\nLoading Training Cameras [01/01 13:51:33]\nLoading Test Cameras [01/01 13:51:40]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:25<00:00, 3.94it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [00:48<00:00, 4.13it/s]\n\n\npython metrics.py -m ./output/lego_eval/\n\nScene: ./output/lego_eval/\nMethod: ours_30000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [04:00<00:00, 1.20s/it]\n SSIM : 0.2604475\n PSNR : 3.0649595\n LPIPS: 0.5116847\n
\u770b\u8d77\u6765\u6548\u679c\u4e0d\u592a\u597d\u3002 \u5e94\u8be5\u662f\u521d\u59cb\u5316\u7684\u95ee\u9898\uff0cL1 \u751a\u81f3\u8fd8\u662f\u4e0a\u6b21\u7684 10 \u500d, Evaluating train: L1 0.5475435316562652 PSNR 3.064222288131714
\u3002
\u628a iterations \u8c03\u5230 100000 \u518d\u6765\u4e00\u6b21\uff0c\u770b\u770b\u6536\u655b\u60c5\u51b5\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#iterations100000-evaluation","title":"Iterations=100000 + evaluation","text":"Text Only python train.py -s ./data/nerf_synthetic/lego/ -m ./output/lego_eval_100000/ --iterations 100000 --eval\n\nOptimizing ./output/lego_eval_100000/\nOutput folder: ./output/lego_eval_100000/ [01/01 14:00:46]\nTensorboard not available: not logging progress [01/01 14:00:46]\nFound transforms_train.json file, assuming Blender data set! [01/01 14:00:46]\nReading Training Transforms [01/01 14:00:46]\nReading Test Transforms [01/01 14:00:53]\nLoading Training Cameras [01/01 14:01:00]\nLoading Test Cameras [01/01 14:01:08]\nNumber of points at initialisation : 100000 [01/01 14:01:15]\nTraining progress: 7%|\u2588\u2588\u2588\u2588\u2588\u2589 | 7000/100000 [01:23<17:42, 87.50it/s, Loss=0.0159089, Depth Loss=0.0000000]\n[ITER 7000] Evaluating test: L1 0.34856061153113843 PSNR 6.298382818698883 [01/01 14:02:40]\n\n[ITER 7000] Evaluating train: L1 0.36839944720268253 PSNR 5.857858657836914 [01/01 14:02:40]\n\n[ITER 7000] Saving Gaussians [01/01 14:02:40]\nTraining progress: 30%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2589 | 29990/100000 [05:45<10:51, 107.52it/s, Loss=0.0095307, Depth Loss=0.0000000]\n[ITER 30000] Evaluating test: L1 0.6024469056725502 PSNR 2.6481225460767748 [01/01 14:07:02]\n\n[ITER 30000] Evaluating train: L1 0.5561836898326874 PSNR 2.9405082702636722 [01/01 14:07:02]\n\n[ITER 30000] Saving Gaussians [01/01 14:07:02]\nTraining progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100000/100000 [16:33<00:00, 100.62it/s, Loss=0.0109117, Depth Loss=0.0000000]\n\n[ITER 100000] Saving Gaussians [01/01 14:17:49]\n\nTraining complete. [01/01 14:17:51]\n
Text Onlypython render.py -m ./output/lego_eval_100000/\nLooking for config file in ./output/lego_eval_100000/cfg_args\nConfig file found: ./output/lego_eval_100000/cfg_args\nRendering ./output/lego_eval_100000/\nLoading trained model at iteration 100000 [01/01 14:21:43]\nFound transforms_train.json file, assuming Blender data set! [01/01 14:21:43]\nReading Training Transforms [01/01 14:21:43]\nReading Test Transforms [01/01 14:21:50]\nLoading Training Cameras [01/01 14:21:57]\nLoading Test Cameras [01/01 14:22:06]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 100/100 [00:22<00:00, 4.39it/s]\nRendering progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [00:42<00:00, 4.65it/s]\n
Text Onlypython metrics.py -m ./output/lego_eval_100000/\n\nScene: ./output/lego_eval_100000/\nMethod: ours_100000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 200/200 [04:03<00:00, 1.22s/it]\n SSIM : 0.2404845\n PSNR : 2.4990394\n LPIPS: 0.5251624\n
\u597d\u50cf\u8bc4\u4f30\u4ecd\u7136\u4e0d\u592a\u884c\uff0c\u8fd8\u8d8a\u8bad\u7ec3\u8d8a\u5dee\u4e86\u3002
Text Onlyscp -r -P 26000 fanghaotian@RHOS:/home/fanghaotian/3DGS/gaussian-splatting/output/lego_eval_100000/ C:\\Users\\fanghaotian\\Desktop\\\n
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#blender-colmap","title":"Blender \u8f6c Colmap","text":"colmap automatic_reconstructor --workspace_path . --image_path ./images --sparse 1 --camera_model SIMPLE_PINHOLE --dense 0\n# colmap automatic_reconstructor: \u8fd9\u662f\u8c03\u7528COLMAP\u7a0b\u5e8f\u4e2d\u7684\u81ea\u52a8\u91cd\u5efa\u6a21\u5757\uff0c\u5b83\u4f1a\u81ea\u52a8\u5b8c\u6210\u7279\u5f81\u63d0\u53d6\u3001\u5339\u914d\u3001\u91cd\u6295\u5f71\u8bef\u5dee\u4f18\u5316\u548c\u4e09\u89d2\u5316\u7b49\u6b65\u9aa4\uff0c\u4ee5\u751f\u6210\u573a\u666f\u7684\u7a00\u758f3D\u70b9\u4e91\u6a21\u578b\u3002\n# --workspace_path .: \u6307\u5b9a\u4e86\u5de5\u4f5c\u7a7a\u95f4\u8def\u5f84\u4e3a\u5f53\u524d\u76ee\u5f55(.)\uff0c\u5728\u8fd9\u4e2a\u8def\u5f84\u4e0b\uff0cCOLMAP\u5c06\u5b58\u50a8\u4e2d\u95f4\u7ed3\u679c\u4ee5\u53ca\u6700\u7ec8\u7684\u91cd\u5efa\u8f93\u51fa\u6587\u4ef6\u3002\n# --image_path ./images: \u5b9a\u4e49\u4e86\u56fe\u50cf\u6570\u636e\u96c6\u6240\u5728\u7684\u8def\u5f84\uff0c\u5373\u6240\u6709\u53c2\u4e0e\u91cd\u5efa\u7684\u56fe\u7247\u90fd\u4f4d\u4e8e./images\u76ee\u5f55\u4e0b\u3002\n# --sparse 1: \u8fd9\u4e2a\u53c2\u6570\u8868\u793a\u8fdb\u884c\u7a00\u758f\u91cd\u5efa\uff08\u4e0e\u5bc6\u96c6\u91cd\u5efa\u76f8\u5bf9\uff09\uff0c\u5373\u53ea\u6784\u5efa\u51fa\u573a\u666f\u4e2d\u7684\u5173\u952e\u70b9\u53ca\u5176\u5bf9\u5e94\u5173\u7cfb\uff0c\u5e76\u901a\u8fc7\u8fd9\u4e9b\u4fe1\u606f\u751f\u6210\u4e00\u4e2a\u7531\u7a00\u758f\u70b9\u4e91\u7ec4\u6210\u7684\u4e09\u7ef4\u6a21\u578b\u3002\n# --camera_model SIMPLE_PINHOLE: \u6307\u5b9a\u4f7f\u7528\u7684\u76f8\u673a\u6a21\u578b\u4e3a\u201c\u7b80\u5355\u9488\u5b54\u6a21\u578b\u201d\uff08Simple Pinhole Model\uff09\u3002\u8fd9\u610f\u5473\u7740COLMAP\u5728\u8fdb\u884c\u91cd\u5efa\u65f6\u5c06\u5047\u8bbe\u76f8\u673a\u9075\u5faa\u7684\u662f\u6700\u57fa\u7840\u7684\u51e0\u4f55\u6295\u5f71\u6a21\u578b\uff0c\u5176\u4e2d\u4e0d\u5305\u62ec\u50cf\u5f84\u5411\u7578\u53d8\u8fd9\u6837\u7684\u590d\u6742\u56e0\u7d20\u3002\n# --dense 0\uff0c\u51cf\u5c11\u4e0d\u9700\u8981\u7684\u8ba1\u7b97\u64cd\u4f5c\u3002\n
\u7136\u540e train render metric
Text Only(gaussian_splatting) fanghaotian@rhos-Super-Server:~/3DGS/gaussian-splatting$ python metrics.py -m ./output/lego_colmap/\n\nScene: ./output/lego_colmap/\nMethod: ours_30000\nMetric evaluation progress: 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 13/13 [00:23<00:00, 1.83s/it]\n SSIM : 0.2915006\n PSNR : 4.3199711\n LPIPS: 0.4333871\n
\u611f\u89c9\u662f\u8f6c\u6362\u7684\u65f6\u5019\u56fe\u7247\u592a\u5c11\u4e86\uff0c\u7136\u540e\u5c31\u53d8\u5dee\u4e86\u3002render \u7684\u65f6\u5019\u5f88\u5feb\u3002
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#ffmpeg","title":"ffmpeg \u7684\u95ee\u9898","text":"ffmpeg: error while loading shared libraries: libopenh264.so.5:-CSDN\u535a\u5ba2
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#_2","title":"\u4ee3\u7801\u89e3\u8bfb","text":"Gaussian_Splatting_Code
","tags":["\u79d1\u7814","\u590d\u73b0","\u4e09\u7ef4\u91cd\u5efa"]},{"location":"Blogs/posts/Gaussian_Splatting_%E5%A4%8D%E7%8E%B0/#reference","title":"Reference","text":"\u7ea6 374 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/OCRN/#beyond-object-recognition-a-new-benchmark-towards-object-concept-learning","title":"Beyond Object Recognition: A New Benchmark towards Object Concept Learning","text":"\u6587\u7ae0\u4fe1\u606f Understanding objects is a central building block of AI, especially for embodied AI. Even though object recognition excels with deep learning, current machines struggle to learn higher-level knowledge, e.g., what attributes an object has, and what we can do with it. Here, we propose a challenging Object Concept Learning (OCL) task to push the envelope of object understanding. It requires machines to reason out affordances and simultaneously give the reason: what attributes make an object possess these affordances. To support OCL, we build a densely annotated knowledge base including extensive annotations for three levels of object concept (category, attribute, affordance), and the clear causal relations of three levels. By analyzing the causal structure of OCL, we present a baseline, Object Concept Reasoning Network (OCRN). It leverages concept instantiation and causal intervention to infer the three levels. In experiments, OCRN effectively infers the object knowledge while following the causalities well. Our data and code are available at https://mvig-rhos.com/ocl.
ConclusionIn this work, we introduce object concept learning (OCL) expecting machines to infer affordances and explain what attributes enable an object to possess them. Accordingly, we build an extensive dataset and present OCRN based on casual intervention and instantiation. OCRN achieves decent performance and follows the causalities well. However, OCL remains challenging and would inspire a line of studies on reasoning-based object understanding.
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/OCRN/#model","title":"Model","text":"\u7ea6 1428 \u4e2a\u5b57 7 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u79d1\u7814
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#ulip-2-towards-scalable-multimodal-pre-training-for-3d-understanding","title":"ULIP-2: Towards Scalable Multimodal Pre-training for 3D Understanding","text":"\u6587\u7ae0\u4fe1\u606f Recent advancements in multimodal pre-training have shown promising efficacy in 3D representation learning by aligning multimodal features across 3D shapes, their 2D counterparts, and language descriptions. However, the methods used by existing frameworks to curate such multimodal data, in particular language descriptions for 3D shapes, are not scalable, and the collected language descriptions are not diverse. To address this, we introduce ULIP-2, a simple yet effective tri-modal pre-training framework that leverages large multimodal models to automatically generate holistic language descriptions for 3D shapes. It only needs 3D data as input, eliminating the need for any manual 3D annotations, and is therefore scalable to large datasets. ULIP-2 is also equipped with scaled-up backbones for better multimodal representation learning. We conduct experiments on two large-scale 3D datasets, Objaverse and ShapeNet, and augment them with tri-modal datasets of 3D point clouds, images, and language for training ULIP-2. Experiments show that ULIP-2 demonstrates substantial benefits in three downstream tasks: zero-shot 3D classification, standard 3D classification with fine-tuning, and 3D captioning (3D-tolanguage generation). It achieves a new SOTA of 50.6% (top1) on Objaverse-LVIS and 84.7% (top-1) on ModelNet40 in zero-shot classification. In the ScanObjectNN benchmark for standard fine-tuning, ULIP-2 reaches an overall accuracy of 91.5% with a compact model of only 1.4 million parameters. ULIP-2 sheds light on a new paradigm for scalable multimodal 3D representation learning without human annotations and shows significant improvements over existing baselines. The code and datasets are released at https://github.com/salesforce/ULIP.
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#task","title":"Task","text":"\u6bd4\u5982\u8fd9\u5f20\u56fe\uff0c\u539f\u59cb\u6807\u6ce8\u7684\u8bed\u4e49\u4fe1\u606f\u5c31\u4e0d\u592a\u591f\uff0c\u4f46\u662f\u7528 ULIP-2 \u6807\u6ce8\u7684\u5c31\u6bd4\u8f83\u5168\u9762\u3002
","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#our-pipeline","title":"Our Pipeline","text":"ULIP-2 \u91c7\u7528\u5927\u578b\u591a\u6a21\u6001\u6a21\u578b\uff0c\u4ece 3D \u5f62\u72b6\u7684\u6574\u4f53\u89d2\u5ea6\u4e3a\u6bcf\u4e2a 2D \u6e32\u67d3\u7684\u56fe\u50cf\u81ea\u52a8\u751f\u6210\u8be6\u7ec6\u63cf\u8ff0\u3002ULIP-2 \u5229\u7528\u9884\u5148\u5bf9\u9f50\u548c\u51bb\u7ed3\u7684\u89c6\u89c9\u8bed\u8a00\u7279\u5f81\u7a7a\u95f4\u6765\u5b9e\u73b0\u4e09\u5143\u4f53\u6a21\u6001\u4e4b\u95f4\u7684\u5bf9\u9f50\uff1a\u6574\u4f53\u6587\u672c\u3001\u56fe\u50cf\u548c 3D \u70b9\u4e91\u3002\u9884\u8bad\u7ec3\u540e\uff0c3D \u7f16\u7801\u5668\u5c06\u7528\u4e8e\u4e0b\u6e38\u4efb\u52a1\u3002
Example ","tags":["\u79d1\u7814"]},{"location":"Blogs/posts/ULIP-2/#key-insight","title":"Key insight","text":"We present ULIP-2, a novel framework for multimodal 3D representation learning. By leveraging large multimodal models for language description generation and scaling up the multimodal 3D pre-training, ULIP-2 not only addresses the quality and scalability challenges in existing multimodal 3D datasets but also demonstrates significant improvements in all downstream tasks. We also release \"ULIP-Objaverse\" triplets and \"ULIP-ShapeNet\" triplets, two large-scale trimodal datasets to foster further research. Limitations. ULIP-2\u2019s pre-training primarily utilizes object-level 3D shape datasets, which inherently differ from scene-level 3D data in their distribution and complexity. Exploring the application of the ULIP-2 framework to scenelevel 3D data understanding, and leveraging the knowledge learned from object-level 3D data for this purpose, represents a compelling avenue for future research. Broader Impact. ULIP-2 aims to minimize human annotation in 3D multimodal pre-training, reducing labor but potentially impacting low-skilled job markets. This dual impact, a common concern in AI advancements, underscores the need for broader considerations in AI research.
\u7ea6 2374 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 12 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Blog
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#ai","title":"\u4e00\u4e9b AI \u4e0e\u4e2a\u4eba\u5b66\u4e60\u7684\u601d\u8003","text":"","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#_1","title":"\u4e2a\u4eba\u4f7f\u7528\u60c5\u51b5","text":"\u8ba9\u6211\u4eec\u6765\u7ec6\u5316\u4e00\u4e0b\u8fd9\u4e2a\u95ee\u9898\uff0c\u4e00\u822c\u6765\u8bf4\uff0c\u6211\u4f1a\u6709\u4ee5\u4e0b\u51e0\u79cd\u60c5\u51b5\uff1a
\u4f9d\u8d56 LLM\uff0c\u4f46\u662f\u8981\u610f\u8bc6\u5230\u5b83\u7684\u5c40\u9650\u6027\uff0c\u9519\u8bef\u7684\u5bf9\u8bdd\u5386\u53f2\u4f1a\u8ba9\u5b83\u8d8a\u9519\u8d8a\u8fdc\uff0c\u4f60\u8981\u77e5\u9053\u9002\u65f6\u7684\u91cd\u542f\u5bf9\u8bdd\u6765\u907f\u514d\u201c\u964d\u667a\u201d\u3002
\u6bd4\u5982\u6211\u66fe\u7ecf\u5c1d\u8bd5\u8fd9\u4e2a\u4f7f\u7528\u6280\u5de7\uff0c\u4f46\u662f\u5f88\u96be\u8fbe\u5230\u6bd4\u8f83\u597d\u7684\u6548\u679c\u3002
\u5f15\u7528\u522b\u4eba\u7684\u603b\u7ed3\u6765\u8bf4\uff1a
\u4e00\u3001LLM \u4e0a\u4e0b\u6587\u662f\u53d7\u9650\u7684\uff0c\u4e14\u4e0a\u4e0b\u6587\u8d8a\u591a\uff0c\u5b83\u8d8a\u96be\u6355\u83b7\u5230\u4f60\u7684\u610f\u56fe\u3002 \u4e8c\u3001LLM \u8f93\u51fa\u662f\u4e25\u91cd\u53d7\u9650\u7684\uff0c\u76ee\u524d\u5e38\u7528\u7684\u6700\u591a\u4e3a 8192 Tokens\u3002 \u4e09\u3001\u65e0\u8bba\u662fCursor\u3001Windsurf\u3001Copilot\u8fd8\u662fCline\uff0c\u5b83\u4eec\u90fd\u53ea\u662f\u4f60\u7684\u52a9\u624b\uff0c\u8bf7\u5168\u7a0b\u53c2\u4e0e\u5e76\u628a\u63e1\u4e3b\u5bfc\u6743\u548c\u51b3\u7b56\u6743\u3002
\u6bd4\u65b9\u8bf4\uff1a - \u6211\u4eec\u5e94\u8be5\u8ba9 AI \u5e2e\u52a9\u6211\u4eec\u8bfb\u4ee3\u7801\uff0c\u4ece\u800c\u77e5\u9053\u81ea\u5df1\u5e94\u8be5\u5982\u4f55\u6539\u4ee3\u7801\u3002 - \u800c\u4e0d\u662f\u8ba9\u5b83\u7ed9\u6211\u4eec\u76f4\u63a5\u4fee\u6539\u4ee3\u7801\u3002 - \u6211\u4eec\u5e94\u8be5\u8ba9 AI \u7ed9\u6211\u4eec\u89e3\u91ca\u77e5\u8bc6\u70b9\uff0c\u4e3e\u4f8b\u5b50\uff0c\u4ece\u800c\u8ba9\u6211\u4eec\u66f4\u52a0\u5feb\u901f\u7684\u5438\u6536\u77e5\u8bc6\u3002 - \u800c\u4e0d\u662f\u8ba9\u5b83\u7ed9\u6211\u4eec\u751f\u6210\u7b14\u8bb0\uff0c\u53d6\u4ee3\u81ea\u5df1\u5b66\u4e60\u7684\u8fc7\u7a0b\u3002
\u7528\u4e00\u4e2a\u66f4\u52a0\u5168\u9762\u7684\u4f8b\u5b50\u6765\u8bf4\uff0c\u5982\u679c\u6211\u4eec\u60f3\u8981\u6784\u5efa\u4e00\u4e2a\u7f51\u7ad9\uff0c\u4e0b\u9762\u662f\u4e00\u4e9b\u6700\u4f73\u5b9e\u8df5\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#21","title":"2.1. \u660e\u786e\u5b9a\u4f4d","text":"\u4e00\u5f00\u59cb\u6211\u5c31\u660e\u786e\u4e86\u81ea\u5df1\u7684\u89d2\u8272\u5b9a\u4f4d\uff1a\u4ea7\u54c1\u7ecf\u7406\u3002\u6211\u4e0d\u61c2\u7f16\u7a0b\u8bed\u8a00\u548c\u4ee3\u7801\u5b9e\u73b0\uff0c\u6211\u7684\u804c\u8d23\u5c31\u662f\u8bbe\u8ba1\u6307\u5bfc LLM \u5b9e\u73b0\u9879\u76ee\uff0c\u5728\u8fc7\u7a0b\u4e2d\u901a\u8fc7\u54a8\u8be2\u7ec6\u8282\u518d\u8c03\u6574\u5177\u4f53\u7684\u5b9e\u73b0\u6b65\u9aa4\u3002
\u5728\u95ee\u7b54\u7684\u8fc7\u7a0b\u4e2d\uff0c\u4e00\u5b9a\u8981\u5f53\u4e00\u4e2a\u597d\u5947\u5b9d\u5b9d\uff0c\u4e0d\u505c\u7684\u95ee\u600e\u4e48\u505a\u548c\u4e3a\u4ec0\u4e48\uff0c\u4f60\u8ddf LLM \u5ba2\u6c14\u4ec0\u4e48\uff1f\u4e0d\u61c2\u5c31\u95ee\uff0c\u54ea\u91cc\u4e0d\u4f1a\u95ee\u54ea\u91cc\uff01
\u6211\u4e00\u5f00\u59cb\u5c31\u662f\u4ec0\u4e48\u90fd\u4e0d\u61c2\uff0c\u7136\u540e\u518d\u548c LLM \u7684\u4ea4\u6d41\u57fa\u7840\u4e0a\uff0c\u4ee5\u5b83\u7684\u56de\u7b54\u4f5c\u4e3a\u9636\u68af\u4e00\u6b65\u6b65\u4f18\u5316\u63d0\u95ee\u5185\u5bb9\u3002 \u4e0b\u9762\u662f\u6211\u7684\u7b2c\u4e00\u6b21\u505a\u7f51\u7ad9\u7684\u5bf9\u8bdd\u8fc7\u7a0b\uff1a
\u81f3\u6b64\uff0c\u6211\u5c31\u5b8c\u6210\u4e86 Next. js \u9879\u76ee\u7684\u521b\u5efa\uff0c\u5341\u5206\u949f\u524d\u6211\u4e00\u7a8d\u4e0d\u901a\uff0c\u5341\u5206\u949f\u540e\u6211\u89c9\u5f97\u6211\u5df2\u7ecf\u4e86\u89e3\u4e86\u4e00\u4e2a\u4ea7\u54c1\u7ecf\u7406\u9700\u8981\u638c\u63e1\u7684\u5185\u5bb9\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#22","title":"2.2. \u9879\u76ee\u89c4\u5212","text":"\u5728\u5b9e\u73b0\u9879\u76ee\u524d\u671f\u5c31\u4e00\u5b9a\u8981\u505a\u597d\u89c4\u5212\uff0c\u8fd9\u662f\u4e0e LLM \u914d\u5408\u987a\u5229\u7684\u57fa\u7840\u3002\u4e3a\u4e86\u4e0d\u91cd\u8e48\u9879\u76ee\u6df7\u4e71\uff0c\u65e0\u6cd5\u8c03\u6574\uff0c\u5fc3\u70e6\u610f\u4e71\u7684\u8986\u8f99\uff0c\u5728\u4efb\u4f55\u9879\u76ee\u5f00\u59cb\u524d\uff0c\u6700\u597d\u90fd\u8981\u6839\u636e\u5b9e\u73b0\u96be\u5ea6\uff0c\u82b1\u4e0a\u4e00\u5b9a\u65f6\u95f4\u53bb\u548c LLM \u597d\u597d\u68b3\u7406\u9879\u76ee\u7ed3\u6784\uff0c\u8ba9\u5b83\u4e0d\u8981\u7ed9\u51fa\u5177\u4f53\u4ee3\u7801\u800c\u662f\u7ed9\u51fa\u9879\u76ee\u7684\u76ee\u5f55\u7ed3\u6784\uff0c\u8fd9\u6837\u4f60\u5fc3\u91cc\u5c31\u6709\u6570\uff0c\u4e4b\u540e\u5982\u679c\u51fa\u73b0\u9519\u6f0f\uff0c\u4f60\u4e5f\u80fd\u6839\u636e\u8fd9\u4e2a\u7ed3\u6784\u5355\u72ec\u5411 LLM \u8be2\u95ee\u5177\u4f53\u7ec6\u8282\u3002
\u9879\u76ee\u89c4\u5212\u5c31\u901a\u8fc7 README \u6765\u7f16\u5199\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\u9700\u8981\u6709\uff1a
\u4e4b\u540e\u5c31\u56f4\u7ed5 README \u53bb\u5b9e\u73b0\u5c31\u5fc3\u91cc\u6709\u5e95\u4e86\u3002
\u76ee\u5f55\u7ed3\u6784
\u4e4b\u540e\u57fa\u672c\u90fd\u662f\u8981\u6539\u53d8\u7684\uff0c\u53ea\u662f\u4f5c\u4e3a\u53c2\u8003\uff0c\u4e0d\u7528\u8fc7\u4e8e\u5173\u6ce8\u3002 \u5927\u90e8\u5206\u65f6\u5019\u6211\u4e00\u76f4\u4fee\u6539\u7684\u662f \u9879\u76ee\u529f\u80fd
\uff0c\u6211\u4f1a\u4f7f\u7528 - []
\u6e05\u5355\u6765\u7ba1\u7406\u529f\u80fd\u5b9e\u73b0\u5217\u8868\uff0c\u907f\u514d\u9057\u6f0f\u548c\u5173\u6ce8\u70b9\u504f\u79fb\uff0c\u56e0\u4e3a LLM \u5f88\u8f7b\u6613\u7684\u5c31\u80fd\u5199\u51fa\u8ba9\u4f60\u89c9\u5f97\u8d3c\u725b\u903c\u7684\u4ee3\u7801\uff0c\u4f46\u662f\u5207\u5fcc\u81ea\u6211\u611f\u52a8\uff0c\u5728\u9879\u76ee\u57fa\u7840\u529f\u80fd\u5b9e\u73b0\u524d\uff0c\u4e0d\u8981\u8ba9 LLM \u81ea\u6211\u53d1\u6325\uff0c\u5148\u628a Demo \u5b8c\u6210\u518d\u8bf4\u5176\u4ed6\u3002
\u4e00\u5b9a\u8981\u4f7f\u7528 git \u7ba1\u7406\u4ee3\u7801\uff0c\u7f16\u7a0b\u4e60\u60ef\u51b3\u5b9a\u4e86\u5b9e\u73b0\u6548\u7387\u3002\u6211\u7684\u7ecf\u9a8c\u5c31\u662f\uff1a\u591a\u6682\u5b58\u3001\u52e4\u63d0\u4ea4\u3001\u63a7\u7248\u672c
\u5728\u89c4\u5212\u597d\u9879\u76ee\u7cfb\u7edf\u67b6\u6784\u540e\uff0c\u8ba9 LLM \u5b9e\u73b0\u4e00\u4e2a\u57fa\u7840\u7684\u7f51\u7ad9\u6846\u67b6\uff0c\u6211\u5c31\u4f1a commit \u7b2c\u4e00\u4e2a\u7248\u672c\uff0c\u5728\u8fd9\u4e2a\u57fa\u7840\u4e0a\u8fdb\u884c\u589e\u5220\u6539\u67e5\u3002\u56e0\u4e3a\u4f7f\u7528 LLM \u7f16\u5199\u4ee3\u7801\uff0c\u6700\u5fcc\u8bb3\u4e00\u53e3\u6c14\u7528 LLM \u5b9e\u73b0\u592a\u591a\u529f\u80fd\uff0c\u5bfc\u81f4\u51fa\u73b0\u95ee\u9898\u4e86\u79ef\u91cd\u96be\u8fd4\u8eab\u5fc3\u4ff1\u75b2\u3002
\u6bcf\u6b21\u5728\u8fdb\u884c\u5927\u89c4\u6a21\u6539\u52a8\u6216\u8005\u662f\u8c03\u6574\u529f\u80fd\u4e4b\u524d\uff0c\u4e00\u5b9a\u8981\u53bb\u4f7f\u7528 Stage All Changes
\u6682\u5b58\u6539\u52a8\uff0c\u907f\u514d\u5f71\u54cd\u4e86\u672c\u6765\u5df2\u7ecf\u5b9e\u73b0\u7684\u4ee3\u7801\u3002
\u5e76\u4e14\u4e00\u5b9a\u8981\u505a\u597d\u529f\u80fd\u62c6\u5206\uff0c\u514b\u5236\u514b\u5236\u518d\u514b\u5236\uff0c\u53ea\u8981\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5c31\u63d0\u4ea4\uff0c\u4e0d\u7136\u7275\u4e00\u53d1\u800c\u52a8\u5168\u8eab\uff0c\u8d8a\u6539\u8d8a\u4e71\u3002\u6211\u5df2\u7ecf\u5728\u8fd9\u4e0a\u9762\u5403\u4e8f\u592a\u591a\u6b21\u4e86\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#23","title":"2.3. \u62c6\u5206\u6a21\u5757","text":"\u62ff\u7f51\u7ad9\u6765\u4e3e\u4f8b\uff0c\u62c6\u5206\u6a21\u5757\u5c31\u662f\u62bd\u6837\u4ee3\u7801\u529f\u80fd\uff0c\u6bd4\u5982\u5728 page \u4e2d\u6709\u4e24\u4e2a\u90e8\u5206\uff1a\u9876\u680f\u548c\u5185\u5bb9\u533a\u57df\uff0c\u90a3\u4e48\u6211\u4eec\u6700\u597d\u62c6\u5206\u51fa HeadBar.tsx
\u4e13\u95e8\u8d1f\u8d23\u9876\u680f\u7684\u903b\u8f91\uff1b\u7136\u540e\u5728\u9876\u680f\u4e2d\u6709\u5934\u50cf\u3001\u4e3b\u9875\u6309\u94ae\u3001logo \u4e09\u90e8\u5206\uff0c\u90a3\u4e48\u6211\u5c31\u62c6\u5206\u51fa\uff1a Avatar.tsx
\u3001 HomeButton.tsx
\u3001 Logo.tsx
\uff0c\u5206\u522b\u8d1f\u8d23\u81ea\u5df1\u7ec4\u4ef6\u7684\u529f\u80fd\u3002
\u6309\u7167\u8fd9\u4e2a\u601d\u8def\uff0c\u8fd8\u53ef\u4ee5\u62c6\u5206\u529f\u80fd\u903b\u8f91\uff0c\u6bd4\u5982\u521b\u5efa\u7f51\u7edc\u8bf7\u6c42\u7ec4\u4ef6\u3001\u8def\u7531\u8c03\u7528\u5207\u7247\u3001\u5de5\u5382\u6a21\u5f0f\u7ec4\u4ef6\u7b49\uff0c\u4e0d\u8981\u770b\u540d\u5b57\u9ad8\u5927\u4e0a\u542c\u4e0d\u61c2\uff0c\u5b9e\u9645\u4e0a\u8fd9\u4e9b\u90fd\u662f LLM \u4f1a\u5728\u5b9e\u73b0\u8fc7\u7a0b\u4e2d\u81ea\u7136\u5448\u73b0\u7684\u903b\u8f91\uff0c\u76ee\u7684\u5c31\u662f\u4e3a\u4e86\u62bd\u6837\u4ee3\u7801\uff0c\u907f\u514d\u91cd\u590d\u5b9e\u73b0\u548c\u65b9\u4fbf\u7edf\u4e00\u7ba1\u7406\u3002
\u5c3d\u53ef\u80fd\u4fdd\u8bc1\u6bcf\u4e2a\u6587\u4ef6\u53ea\u8d1f\u8d23\u5355\u72ec\u7684\u6a21\u5757\u529f\u80fd\uff0c\u4ee3\u7801\u884c\u6570\u63a7\u5236\u5728 200 \u884c\u4ee5\u5185\u3002
\u4e0d\u8981\u5acc\u9ebb\u70e6\uff0c\u521b\u5efa\u6587\u4ef6\u4e0d\u9700\u8981\u81ea\u5df1\u52a8\u624b\uff0c\u76f4\u63a5\u8ba9 LLM \u5e2e\u4f60\u62c6\u5206\u5b9e\u73b0\uff0c\u4f60\u70b9\u51fb Apply
\u6309\u94ae\u5b83\u5c31\u4f1a\u81ea\u52a8\u521b\u5efa\u5e76\u586b\u5165\u4ee3\u7801\u3002
\u8fd9\u662f\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u4e60\u60ef\uff0c\u5148\u6267\u884c\uff0c\u7b49\u56de\u8fc7\u5934\u6765\u4f60\u81ea\u7136\u4f1a\u610f\u8bc6\u5230\u5b83\u7684\u4ef7\u503c\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#24","title":"2.4. \u521b\u5efa\u65b0\u5bf9\u8bdd\uff0c\u7cbe\u7b80\u4e0a\u4e0b\u6587","text":"\u4e0a\u4e0b\u6587\u957f\u5ea6\u76f4\u63a5\u51b3\u5b9a\u4e86 LLM \u56de\u7b54\u7684\u8d28\u91cf\u3002
\u4e3a\u4e86\u6700\u597d\u7684\u56de\u7b54\u6548\u679c\uff0c\u6211\u4f1a\u5c3d\u53ef\u80fd\u7684\u907f\u514d\u8fc7\u957f\u7684\u5bf9\u8bdd\u5185\u5bb9\uff0c\u5e76\u4e14\u4fdd\u8bc1\u4e00\u6b21\u5bf9\u8bdd\u53ea\u89e3\u51b3\u4e00\u4e2a\u95ee\u9898\uff0c\u4e4b\u540e\u8fd8\u53ef\u4ee5\u901a\u8fc7\u56de\u770b\u5bf9\u8bdd\u5386\u53f2\u6765\u67e5\u7f3a\u8865\u6f0f\u3002
\u4e0a\u9762\u62c6\u5206\u6a21\u5757\u4e5f\u80fd\u6781\u5927\u7684\u51cf\u5c11\u4e0a\u4e0b\u6587\uff0c\u4f60\u53ea\u9700\u8981\u6dfb\u52a0\u76f8\u5173\u7684\u4ee3\u7801\uff0c\u5bf9\u8bdd\u5373\u53ef\u89e3\u51b3\u9700\u6c42\uff0c\u800c\u4e0d\u9700\u8981\u6bcf\u6b21\u643a\u5e26\u591a\u4f59\u7684\u4ee3\u7801\u8fdb\u884c\u63d0\u95ee\u3002
\u5982\u679c\u5728\u4e00\u6b21\u5bf9\u8bdd\u4e2d\uff0c\u4e00\u76f4\u6ca1\u6709\u89e3\u51b3\u95ee\u9898\uff0c\u6700\u597d\u521b\u5efa\u65b0\u5bf9\u8bdd\uff0c\u9000\u540e\u4e00\u6b65\uff0c\u8ba9 LLM \u4ece\u66f4\u591a\u7684\u89d2\u5ea6\u53bb\u601d\u8003\u95ee\u9898\u51fa\u73b0\u5728\u54ea\uff0c\u7136\u540e\u4f60\u518d\u6839\u636e\u5b83\u7684\u56de\u7b54\uff0c\u4f9d\u6b21\u63d0\u95ee\u5c1d\u8bd5\u89e3\u51b3\u3002
\u6211\u5728\u5b9e\u73b0 telegram bot \u7684\u65f6\u5019\u5c31\u9047\u5230\u8fc7\u65e0\u6cd5\u542f\u52a8\u673a\u5668\u4eba\u7684\u60c5\u51b5\uff0cLLM \u4e00\u76f4\u6267\u7740\u4e8e\u89e3\u51b3\u65f6\u5ef6\u548c\u65f6\u5e8f\u95ee\u9898\uff0c\u4f46\u662f\u5728\u4e00\u6b21\u56de\u7b54\u4e2d\u5b83\u63d0\u5230\u4e86\u53ef\u80fd\u662f\u4ee3\u7406\u8bbe\u7f6e\u9519\u8bef\uff0c\u6211\u6355\u6349\u5230\u4e86\u8fd9\u4e2a\u7b54\u6848\uff0c\u5e76\u4e14\u9a6c\u4e0a\u5c1d\u8bd5\uff0c\u679c\u7136\u89e3\u51b3\u4e86\u95ee\u9898\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#_4","title":"\u603b\u7ed3","text":"\u4e0d\u5e94\u8be5\u4e0d\u4f7f\u7528 AI\uff0c\u800c\u662f\u4e0d\u8981\u8ba9\u5b83\u4ee3\u66ff\u4f60\u7684\u601d\u8003\u8fc7\u7a0b\u3002\u5bf9\u4e8e\u9879\u76ee / \u4efb\u52a1 / \u95ee\u9898\uff0c\u4f60\u9700\u8981\u81ea\u5df1\u638c\u63a7\uff0c\u5373\uff0c\u4f60\u8981\u77e5\u9053 AI \u7ed9\u4f60\u7684\u56de\u7b54\u6b63\u786e\u4e0e\u5426\u800c\u4e0d\u662f\u4efb\u7531\u5b83\u751f\u6210\u3002
","tags":["Blog"]},{"location":"Blogs/posts/%E7%94%A8AI%E5%90%8E%E7%9A%84%E9%97%AE%E9%A2%98/#reference","title":"Reference","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
CS61A\u7ea6 997 \u4e2a\u5b57 36 \u884c\u4ee3\u7801 14 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 5 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/15-213/CSAPP/#1","title":"1 \u8ba1\u7b97\u673a\u7cfb\u7edf\u6f2b\u6e38","text":""},{"location":"CS_Basic/15-213/CSAPP/#2","title":"2 \u4fe1\u606f\u7684\u8868\u793a\u548c\u5904\u7406","text":"#include <stdio.h>\n\n\n\ntypedef unsigned char *byte_pointer;\n\nvoid show_bytes(byte_pointer start, size_t len) {\n\u00a0 size_t i;\n\u00a0 for (i = 0; i < len; i++)\n\u00a0 \u00a0 printf(\" %.2x\", start[i]);\n\u00a0 printf(\"\\n\");\n}\n\nvoid show_int(int x) { show_bytes((byte_pointer)&x, sizeof(int)); }\n\nvoid show_float(float x) { show_bytes((byte_pointer)&x, sizeof(float)); }\n\nvoid show_pointer(void *x) { show_bytes((byte_pointer)&x, sizeof(void *)); }\n\nvoid test_show_bytes(int val) {\n\u00a0 int ival = val;\n\u00a0 float fval = (float)ival;\n\u00a0 int *pval = &ival;\n\u00a0 show_int(ival);\n\u00a0 show_float(fval);\n\u00a0 show_pointer(pval);\n}\n\nint main() {\n\u00a0 int val = 12345;\n\u00a0 test_show_bytes(val);\n\u00a0 return 0;\n}\n
Text Only 39 30 00 00 //\u5c0f\u7aef\u6cd5\n 00 e4 40 46\n 8c f6 bf ef b4 00 00 00\n
"},{"location":"CS_Basic/15-213/CSAPP/#214","title":"2.1.4 \u8868\u793a\u5b57\u7b26\u4e32","text":""},{"location":"CS_Basic/15-213/CSAPP/#215","title":"2.1.5 \u8868\u793a\u4ee3\u7801","text":"x>>k
\u662f\u7b97\u6570\u53f3\u79fb\uff0c x>>>k
\u662f\u903b\u8f91\u53f3\u79fb\\(\\displaystyle \u51fd\u6570B2T_w\u662f\u4e00\u4e2a\u53cc\u5c04\u3002\\)
\u53cd\u7801
\u7ea6 2520 \u4e2a\u5b57 489 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 19 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#0-c","title":"0 \u5f00\u59cb\u5b66\u4e60 C++","text":"C++#include <iostream>\n\nint main()\n{\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#01","title":"0.1 \u6ce8\u91ca","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#02-displaystyle-include","title":"0.2 \\(\\displaystyle \\#\\)include \u6307\u4ee4","text":"(std::cout << \"Hello, World!\") << std::endl\n
#include <iostream>\n#include <string>\n\nint main() \n{\n std::cout << \"Please enter your first name:\";\n\n std::string name;\n std::cin >> name;\n\n std::cout << \"Hello\" << name << \"!\" << std::endl;\n return 0;\n}\n
std::string stars(10, '*')\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#13","title":"1.3 \u5c0f\u7ed3","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2","title":"2 \u5faa\u73af\u548c\u8ba1\u6570","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#21","title":"2.1 \u95ee\u9898","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#22","title":"2.2 \u7a0b\u5e8f\u7684\u6574\u4f53\u7ed3\u6784","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#23","title":"2.3 \u8f93\u51fa\u6570\u76ee\u672a\u77e5\u7684\u884c","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#231-while","title":"2.3.1 while \u8bed\u53e5","text":"const std::string::size_type cols = greeting.size() + pad * 2 + 2;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#241","title":"2.4.1 \u8f93\u51fa\u8fb9\u754c\u5b57\u7b26","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2411-if","title":"2.4.1.1 if \u8bed\u53e5","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#2412","title":"2.4.1.2 \u903b\u8f91\u8fd0\u7b97\u7b26","text":"for (int r = 0; r != rows; ++r) {\n\n}\n
for (init-statement condition; expression)\n statement\n\n#equals to\n\n{\n inti-statement\n while (condition) {\n statement\n expression;\n }\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#253","title":"2.5.3 \u538b\u7f29\u68c0\u6d4b","text":"#include <iomanip>\n#include <ios>\n#include <iostream>\n#include <string>\n\nusing std::cin;\nusing std::cout;\nusing std::endl;\nusing std::precision;\n\nint main() {\n cout << \"Please enter your first name:\";\n string name;\n cin >> name;\n cout << \"Hello, \" << name << \"!\" << endl;\n\n cout << \"Please enter your midterm and final exam grades:\";\n double midterm, final;\n cin >> midterm >> final;\n\n cout << \"Enter all your homework grades, \" \n \"followed by end-of-file:\";\n\n int count = 0;\n double sum = 0;\n\n double x;\n\n while (cin >> x) {\n ++ count;\n sum += x;\n }\n\n streamsize prec = cout.precision();\n cout << \"Your final grade is \" << setprecision(3)\n << 0.2 * midterm + 0.4 * final + 0.4 * sum / count\n << setprecision(prec) << endl; //\u91cd\u7f6e\u6709\u6548\u4f4d\u6570 \u6216\u5199\u6210cout.precision(prec);\n return 0;\n}\n
\u4e0d\u662f\u5f88\u61c2
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#32","title":"3.2 \u7528\u4e2d\u503c\u4ee3\u66ff\u5e73\u5747\u503c","text":"\u90a3\u4e48\u5c31\u8981\u6392\u5e8f\u4e86
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#321","title":"3.2.1 \u628a\u6570\u636e\u96c6\u5408\u5b58\u50a8\u5728\u5411\u91cf\u4e2d","text":"C++double x;\nvector<double> homework;\n\nwhile(cin >> x)\n homework.push_back(x);\n
typedef vector<double>::size_type vec_sz;\nvec_sz size = homework.size();\n
if (size == 0) {\n cout << endl << \"You must enter your grades. \"\n \"Please try again.\" << endl;\n return 1;\n}\n\nsort (homework.begin(), homework.end());\n\nvec_sz mid = size / 2;\ndouble median;\nmedian = size % 2 == 0 ? (homework[mid] + homework[mid - 1]) / 2\n : homework[mid];\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#323","title":"3.2.3 \u4e00\u4e9b\u66f4\u4e3a\u6df1\u5165\u7684\u89c2\u5bdf","text":"double median(vector<double> vec)\n{\n typedef vector<double>::size_type vec_sz;\n vec_sz size = vec.size();\n if (size == 0)\n throw domain_error(\"median of an empty vector\");\n sort(vec.begin(), vec.end());\n vec_sz mid = size / 2;\n return size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];\n}\n
istream read_hw(istream& in, vector<double>& hw)\n{\n if (in) {\n hw.clear();\n double x;\n while (in >> x) \n hw.push_back(x);\n in.clear();\n }\n return in;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#414","title":"4.1.4 \u4e09\u79cd\u51fd\u6570\u53c2\u6570","text":"struct Student_info {\n string name;\n double midterm, final;\n vector<double> homework;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#422","title":"4.2.2 \u5904\u7406\u5b66\u751f\u8bb0\u5f55","text":"C++istream& read(istream& is, Student_info& s)\n{\n is >> s.name >> s.midterm >> s.final;\n read_hw(is, s.homework);\n return is;\n}\n\ndouble grade(const Student_info& s) \n{\n return grade(s.midterm, s.final, s.homework);\n}\n\nbool compare(const Student_info& x, const Studeng_info& y)\n{\n return x.name < y.name;\n}\n\nsort(students.begin(), students.end(), compare;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#423","title":"4.2.3 \u751f\u6210\u62a5\u8868","text":"C++cout << setw(maxlen + 1) << student[i].name;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#43","title":"4.3 \u628a\u5404\u90e8\u5206\u4ee3\u7801\u8fde\u63a5\u5230\u4e00\u8d77","text":"Text Only#ifndef GUARD_median_h\n#define GUARD_median_h //\u9884\u5904\u7406\u7a0b\u5e8f\n\n#include <vector>\ndouble median(vector<double>);\n\n#endif\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#44","title":"4.4 \u628a\u8ba1\u7b97\u6210\u7ee9\u7684\u7a0b\u5e8f\u5206\u5757","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#45","title":"4.5 \u4fee\u6b63\u540e\u7684\u8ba1\u7b97\u6210\u7ee9\u7684\u7a0b\u5e8f","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#46","title":"4.6 \u5c0f\u7ed3","text":"try{\n} catch (t) { }\n
vector<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> pass, fail;\n for (vector<Student_info>::size_type i = 0; i != students.size(); ++i;)\n if (fgrade(student[i]))\n fail.push_back(student[i]);\n else\n pass.push_back(student[i]);\n students = pass;\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#511","title":"5.1.1 \u5c31\u5730\u5220\u9664\u51fd\u6570","text":"C++vector<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> fail;\n vector<Student_info>::size_type i = 0;\n while (i != students.size()) {\n if (fgrade(studentp[i])) {\n fail.push_back(students[i]);\n students.erase(students.begin() + i);\n } else\n ++i;\n }\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#512","title":"5.1.2 \u987a\u5e8f\u5b58\u53d6\u4e0e\u968f\u673a\u5b58\u53d6","text":"for (vector<Student_info>::size_type i = 0; i != students.end(); ++i)\n cout << students[i].name << endl;\nfor (vector<Student_info>::const_iterator iter = students.begin();\n iter != students.end(); ++iter) {\n cout << (*iter).name << endl; }\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#521","title":"5.2.1 \u8fed\u4ee3\u5668\u7c7b\u578b","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#522","title":"5.2.2 \u8fed\u4ee3\u5668\u64cd\u4f5c","text":"(*iter).name\niter->name\n//both are ok\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#524-students-erase-students-begin-i","title":"5.2.4 students. erase (students. begin () + i) \u7684\u542b\u4e49","text":"vecotr<Student_info> extract_fails(vector<Student_info>& students)\n{\n vector<Student_info> fail;\n vector<Student_info>::iterator iter = students.begin();\n while (iter != students.end()) {\n if (fgrade(*iter)) {\n fail.push_back(*iter);\n iter = students.erase(iter); //important\n } else\n ++iter;\n }\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#54","title":"5.4 \u91cd\u65b0\u601d\u8003\u6570\u636e\u7ed3\u6784\u4ee5\u5b9e\u73b0\u66f4\u597d\u7684\u6027\u80fd","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#55-list","title":"5.5 list \u7c7b\u578b","text":"vector<string> split(const string& s)\n{\n vector<string> ret;\n typedef string::size_def string_size;\n string_size i = 0;\n while (i != s.size()) {\n while (i != s.size() && isspace(s[i])) // is from <cctype>\n ++i;\n string_size j = i;\n while (j != s.size() && !isspace(s[i]))\n ++j;\n if (i != j) {\n ret.push_back(s.substr(i, j - i));\n i = j;\n }\n }\n return ret;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#57-split","title":"5.7 \u6d4b\u8bd5 split \u51fd\u6570","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#58","title":"5.8 \u8fde\u63a5\u5b57\u7b26\u4e32","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#581","title":"5.8.1 \u4e3a\u56fe\u6848\u88c5\u6846","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#582","title":"5.8.2 \u7eb5\u5411\u8fde\u63a5","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#583","title":"5.8.3 \u6a2a\u5411\u8fde\u63a5","text":"TODO
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#59","title":"5.9 \u5c0f\u7ed3","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#6","title":"6 \u4f7f\u7528\u5e93\u7b97\u6cd5","text":"for (vector<string>::const_iterator it = bottom.begin(); it != bottom.end(); ++i)\n ret.push_back(*it);\n\nret.insert(ret.end(), bottom.begin(), bottom.end());\n\ncopy(bottom.begin(), bottom.end(), back_inserter(ret));\n
copy(begin, end, out);\n//equals to\nwhile (begin != end)\n *out++ = *begin++;\n // equals to \n // *out = *begin; ++out; ++begin;\n\nit = begin++;\n//equals to\nit = begin;\n++begin;\n
bool space(char c) {\n return isspace(c);\n}\nbool not_space(char c) {\n return !isspace(c);\n}\nvector<string> split(const string& str) {\n typedef string::const_iterator iter;\n vector<string> ret;\n iter i = str.begin();\n while(i != str.end()) {\n i = find_if(i, str.end(), not_space);\n iter j = find_if(i, str.end(), space);\n if (i != str.end()) ret.push_back(string(i, j));\n i = j; \n }\n return ret;\n}\n
bool is_palindrome(const string& s) {\n return equal(s.begin(), s.end(), s.rbegin());\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#613-url","title":"6.1.3 \u67e5\u627e URL","text":"vector<string> find_urls(const string& s) {\n vector<string> ret;\n typedef string::const_iterator iter;\n iter b = s.begin(), e = s.end();\n while (b != e) {\n b = url_beg(b, e);\n if (b != e) {\n iter after = url_end(b, e);\n ret.push_back(string(b, after));\n b = after;\n }\n }\n return ret;\n}\n\nstring::const_iterator url_end(string::const_iterator b, string::const_iterator e) {\n return find_if(b, e, not_url_char);\n}\n\nbool not_url_char(char c) {\n static const string url_ch = \"~;/?@=&$-_.+!*{},'\";\n return !(isalnum(c)) || find(url_ch.begin(), url_ch.end(), c) != url_end());\n //static\u58f0\u660e\u7684\u5c40\u90e8\u53d8\u91cf\u5177\u6709\u5168\u5c40\u5bff\u547d\uff0c\u751f\u5b58\u671f\u8d2f\u7a7f\u6574\u4e2a\u51fd\u6570\u8c03\u7528\u8fc7\u7a0b\n}\n\nstring::const_iterator url_beg(string::const_iterator b, string::const_iterator e) {\n static const string sep = \"://\";\n typedef string::const_iterator iter;\n iter i = b;\n while ((i = search(i, e, sep.begin(), sep.end())) != e) {\n if (i != b && i + sep.size() != e) {\n iter beg = i;\n while (beg != b && isalpha(beg[-1]))\n --beg;\n if (beg != i && i + sep.size() != e && !not_url_char(i[sep.size()])) return beg;\n }\n if (i != e) i += sep.size();\n }\n return e;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#62","title":"6.2 \u5bf9\u8ba1\u7b97\u6210\u7ee9\u7684\u65b9\u6848\u8fdb\u884c\u6bd4\u8f83","text":"bool did_all_hw(const Student_info& s) {\n reutrn ((fint(s.homework.begin(), s.homework.end(), 0)) == s.homework.end());\n}\n\nvector<Student_info> did, didnt;\nStudent_info student;\n\nwhile (read(cin, student)) {\n if (did_all_hw(student))\n did.push_back(student);\n else\n didnt.push_back(student);\n}\nif (did.empty()) {\n cout << \"No student did all the homework!\" << endl;\n return 1;\n}\nif (didnt.empty()) {\n cout << \"Every student did all the homework!\" << endl;\n return 1;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#622","title":"6.2.2 \u5206\u6790\u6210\u7ee9","text":"C++write_analysis(cout, \"median\", median_analysis, did, didn't);\n\ndouble grade_aux(const Student_info& s) {\n tru {\n return grade(s);\n } catch (domain_error) {\n return grade(s.midterm, s.final, 0);\n }\n}\n\ndouble median_analysis(const vector<Student_info>& students) {\n vector<double> grades;\n transdorm(students.begin(), students.end(), back_inserter(grades), grade_aux);\n return medina(grades);\n}\n\nvoid write_analysis(ostream& out, const string& name, double analysis(const vector<Student_info>&), const vector<Student_info>& did, const vector<Student_info>& didnt) {\n out << name << \": median(did) = \" << analysis(did) << \", median(didnt) = \" << analysis(didnt) << endl; \n}\n\nint main() {\n vector<Student_info> did, didnt;\n Student_info student;\n while (read(cin, student)) {\n if (did_all_hw(student))\n did.push_back(student);\n else \n didnt.push_back(student);\n }\n if (did.empty()) {\n cout << \"No student did all the homework!\" << endl;\n return 1;\n }\n if (didnt.empty()) {\n cout << \"Every student did all the homework!\" << endl;\n return 1;\n }\n write_analysis(cout, \"median\", median_analysis, did, didnt);\n write_analysis(cout, \"average\", average_analysis, did, didnt);\n write_analysis(cout, \"medina of homework turned in\", optimistic_median_analysis, did, didnt);\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#623","title":"6.2.3 \u8ba1\u7b97\u57fa\u4e8e\u5bb6\u5ead\u4f5c\u4e1a\u5e73\u5747\u6210\u7ee9\u7684\u603b\u6210\u7ee9","text":"C++double average(const vector<double>& v) {\n return accumulate(v.begin(), v.end(), 0.0) / v.size();\n}\n\ndouble average_analysis(const Student_info& s) {\n return grade(s.midterm, s.final, average(s.homework));\n}\n\ndouble average_analysis(const vector<Student_info>& students) {\n vector<double> grades;\n transform(students.begin(), students.end(), back_inserter(grades), average_grade);\n return median(grades);\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#624","title":"6.2.4 \u4e0a\u4ea4\u7684\u5bb6\u5ead\u4f5c\u4e1a\u7684\u4e2d\u503c","text":"C++double optimistic_median(const Student_info& s) {\n vector<double> nonzero;\n remove_copy(s.homework.begin(), s.homework.end(), back_inserter(nonzero), 0);\n if (nonzero.empty())\n return grade(s.midterm, s.final, 0);\n else \n return grade(s.midterm, s.final, median(nonzero));\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#63","title":"6.3 \u5bf9\u5b66\u751f\u8fdb\u884c\u5206\u7c7b\u5e76\u56de\u987e\u4e00\u4e0b\u6211\u4eec\u7684\u95ee\u9898","text":"vector<Student_info> extract_fails(vector<Student_info>& students) {\n vector<Student_info> fail;\n remove_copy_if(students.begin(), students.end(), back_inserter(fail), pgrade);\n students.earse(remove_if(students.begin(), students.end(), fgrade), student.end());\n return fail;\n}\n\nbool pgrade(const Student_info& s) {\n return !fgrade(s);\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#64","title":"6.4 \u4e00\u79cd\u4e00\u6b21\u4f20\u9012\u7684\u89e3\u51b3\u65b9\u6848","text":"C++vector<Student_info> extract_fails(vector<Student_info>& students) {\n vector<Student_info>::iterator iter = stable_partition(students.begin(), students.end(), pgrade);\n vector<Student_info> fail(iter, students.end());\n students.erase(iter, students.end());\n return fail;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#65","title":"6.5 \u7b97\u6cd5\u3001\u5bb9\u5668\u4ee5\u53ca\u8fed\u4ee3\u5668","text":"int main() {\n string s;\n map<string, int> counters;\n while (cin >> s) ++counters[s];\n for (map<string, int>::const_iterator it = counters.begin(); it != couners.end(); ++it) {\n cout << it->first << \"\\t\" << it->second << endl;\n }\n return 0;\n}\n
map<string, vector<int> > xref(istream& in, vector<string> find_words(const string&) = split) {\n string line;\n int line_number = 0'\n map<string, vector<int>> ret;\n while (getline(in, line)) {\n ++line_number;\n vector<string> words = find_words(line);\n for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it)\n ret(*it).push_back(line_number);\n }\n return ret;\n}\n\n\nint main() {\n map<string, vector<int> > ret = cref(cin);\n for (map<string, vector<int> >::const_iterator it = ret.begin(); it != ret.end(); ++it) {\n cout << it->first << \" occurs on line(s): \";\n vector<int>::const_iterator line_it = it->second.begin();\n cout << *lint_it;\n ++line_it;\n while (line_it != it->second.end()) {\n cout << \", \" << *line_it;\n ++line_it;\n }\n cout << endl;\n }\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#74","title":"7.4 \u751f\u6210\u53e5\u5b50","text":""},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#741","title":"7.4.1 \u8868\u793a\u89c4\u5219","text":"C++typedef vector<string> Rule;\ntypedef vector<Rule> Rule_collection;\ntypedef map<string, Rule_collection> Grammer;\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#742","title":"7.4.2 \u8bfb\u5165\u6587\u6cd5","text":"C++Grammer read_grammer(istream& in) {\n Grammer ret;\n string line;\n while (getline(in, line)) {\n vector<string> entry = split(line);\n if (!entry.empty())\n ret[entry[0]].push_back(Rule(entry.begin() + 1, entry.end()));\n }\n return ret;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#743","title":"7.4.3 \u751f\u6210\u53e5\u5b50","text":"C++vector<string> gen_sentence(const Grammar& g) {\n vector<string> ret;\n gen_aux(g, \"<sentence>\", ret);\n return ret;\n}\n\nbool bracketed(const string& s) {\n return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';\n}\n\nvoid gen_aux(const Grammar& g, const string& word, vector<string>& ret) {\n if (!bracketed(word)) {\n ret.push_back(word);\n } else {\n Grammar::const_iterator it = g.find(word);\n if (it == g.end())\n throw logic_error(\"empty rule\");\n const Rule_collection& c = it->seond;\n const Rule& r = c[nrand(c.size())];\n for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)\n gen_aux(g, *i, ret);\n }\n}\n\nint main() {\n vector<string> sentence = gen_sentence(read_grammar(cin));\n vector<string>::const_iterator it = sentence.begin();\n if (!sentence.empty()) {\n cout << *it;\n ++it; \n }\n while (it != sentence.end()) {\n cout << \" \" << *it;\n ++it;\n }\n cout << endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#744","title":"7.4.4 \u9009\u62e9\u4e00\u4e2a\u968f\u673a\u51fd\u6570","text":"C++int nrand(int n) {\n if (n <= 0 || n > RAND_MAX)\n throw domain_error(\"Argument to nrand is out of range\");\n const int bucket_size = RAND_MAX / n;\n int r;\n do r = rand() / bucket_size;\n while (r >= n);\n return r;\n}\n
"},{"location":"CS_Basic/C%2B%2B/Accelerated%20C%2B%2B/#75","title":"7.5 \u5173\u4e8e\u6027\u80fd\u7684\u4e00\u70b9\u8bf4\u660e","text":"\u7ea6 3115 \u4e2a\u5b57 523 \u884c\u4ee3\u7801 9 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 22 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#1","title":"1 \u6587\u4ef6\u64cd\u4f5c","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#11","title":"1.1 \u6587\u4ef6\u7684\u6982\u5ff5","text":"FILE* freopen(const char* filename, const char* mode, FILE* stream);\n
filename
: \u8981\u6253\u5f00\u7684\u6587\u4ef6\u540dmode
: \u6587\u4ef6\u6253\u5f00\u7684\u6a21\u5f0f\uff0c\u8868\u793a\u6587\u4ef6\u8bbf\u95ee\u7684\u6743\u9650stream
: \u6587\u4ef6\u6307\u9488\uff0c\u901a\u5e38\u4f7f\u7528\u6807\u51c6\u6587\u4ef6\u6d41 (stdin/stdout
) \u6216\u6807\u51c6\u9519\u8bef\u8f93\u51fa\u6d41 (stderr
)r
\uff1a\u4ee5\u53ea\u8bfb\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u53ea\u5141\u8bb8\u8bfb\u5165\u6570\u636e\u00a0\uff08\u5e38\u7528\uff09r+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636erb
\uff1a\u4ee5\u53ea\u8bfb\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u53ea\u5141\u8bb8\u8bfb\u5165\u6570\u636erb+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u5fc5\u987b\u5b58\u5728\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ert+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u672c\u6587\u4ef6\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ew
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u4f1a\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u53ea\u5141\u8bb8\u5199\u5165\u6570\u636e\u00a0\uff08\u5e38\u7528\uff09w+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ewb
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u4f1a\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u53ea\u5141\u8bb8\u5199\u5165\u6570\u636ewb+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5426\u5219\u6e05\u7a7a\u5185\u5bb9\uff0c\u5141\u8bb8\u8bfb/\u5199\u6570\u636ea
\uff1a\u4ee5\u53ea\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e\uff08\u4fdd\u7559 EOF \u7b26\uff09a+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u4ef6\uff0c\u6587\u4ef6\u4e0d\u5b58\u5728\u5c06\u65b0\u5efa\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e\uff08\u4e0d\u4fdd\u7559 EOF \u7b26\uff09at+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u6587\u672c\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3eab+
\uff1a\u4ee5\u8bfb/\u5199\u65b9\u5f0f\u6253\u5f00\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u5199\u5165\u6570\u636e\u5c06\u88ab\u9644\u52a0\u5728\u6587\u4ef6\u672b\u5c3e \u4f7f\u7528\u65b9\u5f0f#include <cstdio>\n#include <iostream>\nint mian(void) {\n freopen(\"data.in\", \"r\", stdin); \n // data.in \u5c31\u662f\u8bfb\u53d6\u7684\u6587\u4ef6\u540d\uff0c\u8981\u548c\u53ef\u6267\u884c\u6587\u4ef6\u653e\u5728\u540c\u4e00\u76ee\u5f55\u4e0b\n freopen(\"data.out\", \"w\", stdout); \n // data.out \u5c31\u662f\u8f93\u51fa\u6587\u4ef6\u7684\u6587\u4ef6\u540d\uff0c\u548c\u53ef\u6267\u884c\u6587\u4ef6\u5728\u540c\u4e00\u76ee\u5f55\u4e0b\n fclose(stdin);\n fclose(stdout);\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#132-fopen","title":"1.3.2 fopen \u51fd\u6570","text":"C++FILE* fopen(const char* path, const char* mode)\n
\u4f7f\u7528\u65b9\u5f0f
C++FILE *in, *out; // \u5b9a\u4e49\u6587\u4ef6\u6307\u9488 \nin = fopen(\"data.in\", \"r\"); \nout = fopen(\"data.out\", \"w\"); \n/* do what you want to do */ \nfclose(in); \nfclose(out);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#14-c-ifstreamofstream","title":"1.4 C++ \u7684\u00a0ifstream/ofstream
\u00a0\u6587\u4ef6\u8f93\u5165\u8f93\u51fa\u6d41","text":"C++#include <fstream> \nusing namespace std; \n// \u4e24\u4e2a\u7c7b\u578b\u90fd\u5728 std \u547d\u540d\u7a7a\u95f4\u91cc \nifstream fin(\"data.in\"); \nofstream fout(\"data.out\"); \nint main(void) { \n /* \u4e2d\u95f4\u7684\u4ee3\u7801\u6539\u53d8 cin \u4e3a fin \uff0ccout \u4e3a fout \u5373\u53ef */ \n fin.close(); \n fout.close(); \n return 0; \n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#2","title":"2 \u6807\u51c6\u5e93","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#21-stl","title":"2.1 STL \u5bb9\u5668","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#211","title":"2.1.1 \u5e8f\u5217\u5f0f\u5bb9\u5668","text":"vector
) \u540e\u7aef\u53ef\u9ad8\u6548\u589e\u52a0\u5143\u7d20\u7684\u987a\u5e8f\u8868\u3002array
)C++11\uff0c\u5b9a\u957f\u7684\u987a\u5e8f\u8868\uff0cC \u98ce\u683c\u6570\u7ec4\u7684\u7b80\u5355\u5305\u88c5\u3002deque
) \u53cc\u7aef\u90fd\u53ef\u9ad8\u6548\u589e\u52a0\u5143\u7d20\u7684\u987a\u5e8f\u8868\u3002list
) \u53ef\u4ee5\u6cbf\u53cc\u5411\u904d\u5386\u7684\u94fe\u8868\u3002forward_list
) \u53ea\u80fd\u6cbf\u4e00\u4e2a\u65b9\u5411\u904d\u5386\u7684\u94fe\u8868\u3002set
) \u7528\u4ee5\u6709\u5e8f\u5730\u5b58\u50a8\u00a0\u4e92\u5f02\u00a0\u5143\u7d20\u7684\u5bb9\u5668\u3002\u5176\u5b9e\u73b0\u662f\u7531\u8282\u70b9\u7ec4\u6210\u7684\u7ea2\u9ed1\u6811\uff0c\u6bcf\u4e2a\u8282\u70b9\u90fd\u5305\u542b\u7740\u4e00\u4e2a\u5143\u7d20\uff0c\u8282\u70b9\u4e4b\u95f4\u4ee5\u67d0\u79cd\u6bd4\u8f83\u5143\u7d20\u5927\u5c0f\u7684\u8c13\u8bcd\u8fdb\u884c\u6392\u5217\u3002multiset
) \u7528\u4ee5\u6709\u5e8f\u5730\u5b58\u50a8\u5143\u7d20\u7684\u5bb9\u5668\u3002\u5141\u8bb8\u5b58\u5728\u76f8\u7b49\u7684\u5143\u7d20\u3002map
) \u7531 {\u952e\uff0c\u503c} \u5bf9\u7ec4\u6210\u7684\u96c6\u5408\uff0c\u4ee5\u67d0\u79cd\u6bd4\u8f83\u952e\u5927\u5c0f\u5173\u7cfb\u7684\u8c13\u8bcd\u8fdb\u884c\u6392\u5217\u3002multimap
) \u7531 {\u952e\uff0c\u503c} \u5bf9\u7ec4\u6210\u7684\u591a\u91cd\u96c6\u5408\uff0c\u4ea6\u5373\u5141\u8bb8\u952e\u6709\u76f8\u7b49\u60c5\u51b5\u7684\u6620\u5c04\u3002unordered_set
/unordered_multiset
)C++11\uff0c\u4e0e\u00a0set
/multiset
\u00a0\u7684\u533a\u522b\u5728\u4e8e\u5143\u7d20\u65e0\u5e8f\uff0c\u53ea\u5173\u5fc3\u300c\u5143\u7d20\u662f\u5426\u5b58\u5728\u300d\uff0c\u4f7f\u7528\u54c8\u5e0c\u5b9e\u73b0\u3002unordered_map
/unordered_multimap
)C++11\uff0c\u4e0e\u00a0map
/multimap
\u00a0\u7684\u533a\u522b\u5728\u4e8e\u952e (key) \u65e0\u5e8f\uff0c\u53ea\u5173\u5fc3 \"\u952e\u4e0e\u503c\u7684\u5bf9\u5e94\u5173\u7cfb\"\uff0c\u4f7f\u7528\u54c8\u5e0c\u5b9e\u73b0\u3002\u5bb9\u5668\u9002\u914d\u5668\u5176\u5b9e\u5e76\u4e0d\u662f\u5bb9\u5668\u3002\u5b83\u4eec\u4e0d\u5177\u6709\u5bb9\u5668\u7684\u67d0\u4e9b\u7279\u70b9\uff08\u5982\uff1a\u6709\u8fed\u4ee3\u5668\u3001\u6709\u00a0clear()
\u00a0\u51fd\u6570\u2026\u2026\uff09\u3002
\u300c\u9002\u914d\u5668\u662f\u4f7f\u4e00\u79cd\u4e8b\u7269\u7684\u884c\u4e3a\u7c7b\u4f3c\u4e8e\u53e6\u5916\u4e00\u79cd\u4e8b\u7269\u884c\u4e3a\u7684\u4e00\u79cd\u673a\u5236\u300d\uff0c\u9002\u914d\u5668\u5bf9\u5bb9\u5668\u8fdb\u884c\u5305\u88c5\uff0c\u4f7f\u5176\u8868\u73b0\u51fa\u53e6\u5916\u4e00\u79cd\u884c\u4e3a\u3002
stack
) \u540e\u8fdb\u5148\u51fa (LIFO) \u7684\u5bb9\u5668\uff0c\u9ed8\u8ba4\u662f\u5bf9\u53cc\u7aef\u961f\u5217\uff08deque
\uff09\u7684\u5305\u88c5\u3002queue
) \u5148\u8fdb\u5148\u51fa (FIFO) \u7684\u5bb9\u5668\uff0c\u9ed8\u8ba4\u662f\u5bf9\u53cc\u7aef\u961f\u5217\uff08deque
\uff09\u7684\u5305\u88c5\u3002priority_queue
) \u5143\u7d20\u7684\u6b21\u5e8f\u662f\u7531\u4f5c\u7528\u4e8e\u6240\u5b58\u50a8\u7684\u503c\u5bf9\u4e0a\u7684\u67d0\u79cd\u8c13\u8bcd\u51b3\u5b9a\u7684\u7684\u4e00\u79cd\u961f\u5217\uff0c\u9ed8\u8ba4\u662f\u5bf9\u5411\u91cf\uff08vector
\uff09\u7684\u5305\u88c5\u3002containerName<typeName,...> name
\u00a0\u7684\u5f62\u5f0f\uff0c\u4f46\u6a21\u677f\u53c2\u6570\uff08<>
\u00a0\u5185\u7684\u53c2\u6570\uff09\u7684\u4e2a\u6570\u3001\u5f62\u5f0f\u4f1a\u6839\u636e\u5177\u4f53\u5bb9\u5668\u800c\u53d8\u3002vector<int> data(10);\n\nfor (int i = 0; i < data.size(); i++)\n cout << data[i] << endl;\n\nfor (vector<int>::iterator iter = data.begin(); iter != data.end(); iter++)\n cout << *iter << endl;\n//C++11 \u4ee5\u540e\u53ef\u4ee5\u7528 auto iter = data.begin() \u6765\u7b80\u5316\n
a + n
\u00a0\u6ee1\u8db3\u00a0*(a + n)
\u00a0\u4e0e\u00a0*(std::address_of(*a) + n)
\u00a0\u7b49\u4ef7\uff08\u5373\u8fde\u7eed\u5b58\u50a8\uff0c\u5176\u4e2d\u00a0a
\u00a0\u4e3a\u8fde\u7eed\u8fed\u4ee3\u5668\u3001n
\u00a0\u4e3a\u6574\u578b\u503c\uff09\u3002=
\uff1a\u6709\u8d4b\u503c\u8fd0\u7b97\u7b26\u4ee5\u53ca\u590d\u5236\u6784\u9020\u51fd\u6570\u3002begin()
\uff1a\u8fd4\u56de\u6307\u5411\u5f00\u5934\u5143\u7d20\u7684\u8fed\u4ee3\u5668\u3002end()
\uff1a\u8fd4\u56de\u6307\u5411\u672b\u5c3e\u7684\u4e0b\u4e00\u4e2a\u5143\u7d20\u7684\u8fed\u4ee3\u5668\u3002end()
\u00a0\u4e0d\u6307\u5411\u67d0\u4e2a\u5143\u7d20\uff0c\u4f46\u5b83\u662f\u672b\u5c3e\u5143\u7d20\u7684\u540e\u7ee7\u3002size()
\uff1a\u8fd4\u56de\u5bb9\u5668\u5185\u7684\u5143\u7d20\u4e2a\u6570\u3002max_size()
\uff1a\u8fd4\u56de\u5bb9\u5668\u00a0\u7406\u8bba\u4e0a\u00a0\u80fd\u5b58\u50a8\u7684\u6700\u5927\u5143\u7d20\u4e2a\u6570\u3002\u4f9d\u5bb9\u5668\u7c7b\u578b\u548c\u6240\u5b58\u50a8\u53d8\u91cf\u7684\u7c7b\u578b\u800c\u53d8\u3002empty()
\uff1a\u8fd4\u56de\u5bb9\u5668\u662f\u5426\u4e3a\u7a7a\u3002swap()
\uff1a\u4ea4\u6362\u4e24\u4e2a\u5bb9\u5668\u3002clear()
\uff1a\u6e05\u7a7a\u5bb9\u5668\u3002==
/!=
/<
/>
/<=
/>=
\uff1a\u6309\u00a0\u5b57\u5178\u5e8f\u00a0\u6bd4\u8f83\u4e24\u4e2a\u5bb9\u5668\u7684\u5927\u5c0f\u3002\uff08\u6bd4\u8f83\u5143\u7d20\u5927\u5c0f\u65f6\u00a0map
\u00a0\u7684\u6bcf\u4e2a\u5143\u7d20\u76f8\u5f53\u4e8e\u00a0set<pair<key, value> >
\uff0c\u65e0\u5e8f\u5bb9\u5668\u4e0d\u652f\u6301\u00a0<
/>
/<=
/>=
\u3002\uff09find
\uff1a\u987a\u5e8f\u67e5\u627e\u3002find(v.begin(), v.end(), value)
\uff0c\u5176\u4e2d\u00a0value
\u00a0\u4e3a\u9700\u8981\u67e5\u627e\u7684\u503c\u3002reverse
\uff1a\u7ffb\u8f6c\u6570\u7ec4\u3001\u5b57\u7b26\u4e32\u3002reverse(v.begin(), v.end())
\u00a0\u6216\u00a0reverse(a + begin, a + end)
\u3002unique
\uff1a\u53bb\u9664\u5bb9\u5668\u4e2d\u76f8\u90bb\u7684\u91cd\u590d\u5143\u7d20\u3002unique(ForwardIterator first, ForwardIterator last)
\uff0c\u8fd4\u56de\u503c\u4e3a\u6307\u5411\u00a0\u53bb\u91cd\u540e\u00a0\u5bb9\u5668\u7ed3\u5c3e\u7684\u8fed\u4ee3\u5668\uff0c\u539f\u5bb9\u5668\u5927\u5c0f\u4e0d\u53d8\u3002\u4e0e\u00a0sort
\u00a0\u7ed3\u5408\u4f7f\u7528\u53ef\u4ee5\u5b9e\u73b0\u5b8c\u6574\u5bb9\u5668\u53bb\u91cd\u3002sort
\uff1a\u6392\u5e8f\u3002sort(v.begin(), v.end(), cmp)
\u00a0\u6216\u00a0sort(a + begin, a + end, cmp)
\uff0c\u5176\u4e2d\u00a0end
\u00a0\u662f\u6392\u5e8f\u7684\u6570\u7ec4\u6700\u540e\u4e00\u4e2a\u5143\u7d20\u7684\u540e\u4e00\u4f4d\uff0ccmp
\u00a0\u4e3a\u81ea\u5b9a\u4e49\u7684\u6bd4\u8f83\u51fd\u6570\u3002stable_sort
\uff1a\u7a33\u5b9a\u6392\u5e8f\uff0c\u7528\u6cd5\u540c\u00a0sort()
\u3002nth_element
\uff1a\u6309\u6307\u5b9a\u8303\u56f4\u8fdb\u884c\u5206\u7c7b\uff0c\u5373\u627e\u51fa\u5e8f\u5217\u4e2d\u7b2c \\(\\displaystyle n\\) \u5927\u7684\u5143\u7d20\uff0c\u4f7f\u5176\u5de6\u8fb9\u5747\u4e3a\u5c0f\u4e8e\u5b83\u7684\u6570\uff0c\u53f3\u8fb9\u5747\u4e3a\u5927\u4e8e\u5b83\u7684\u6570\u3002 nth_element(v.begin(), v.begin() + mid, v.end(), cmp)
\u00a0\u6216\u00a0nth_element(a + begin, a + begin + mid, a + end, cmp)
\u3002binary_search
\uff1a\u4e8c\u5206\u67e5\u627e\u3002binary_search(v.begin(), v.end(), value)
\uff0c\u5176\u4e2d\u00a0value
\u00a0\u4e3a\u9700\u8981\u67e5\u627e\u7684\u503c\u3002merge
\uff1a\u5c06\u4e24\u4e2a\uff08\u5df2\u6392\u5e8f\u7684\uff09\u5e8f\u5217\u00a0\u6709\u5e8f\u5408\u5e76\u00a0\u5230\u7b2c\u4e09\u4e2a\u5e8f\u5217\u7684\u00a0\u63d2\u5165\u8fed\u4ee3\u5668\u00a0\u4e0a\u3002merge(v1.begin(), v1.end(), v2.begin(), v2.end() ,back_inserter(v3))
\u3002inplace_merge
\uff1a\u5c06\u4e24\u4e2a\uff08\u5df2\u6309\u5c0f\u4e8e\u8fd0\u7b97\u7b26\u6392\u5e8f\u7684\uff09\uff1a[first,middle), [middle,last)
\u00a0\u8303\u56f4\u00a0\u539f\u5730\u5408\u5e76\u4e3a\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u3002inplace_merge(v.begin(), v.begin() + middle, v.end())
\u3002lower_bound
\uff1a\u5728\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u4e2d\u8fdb\u884c\u4e8c\u5206\u67e5\u627e\uff0c\u8fd4\u56de\u6307\u5411\u7b2c\u4e00\u4e2a\u00a0\u5927\u4e8e\u7b49\u4e8e \u00a0\u7684\u5143\u7d20\u7684\u4f4d\u7f6e\u7684\u8fed\u4ee3\u5668\u3002\u5982\u679c\u4e0d\u5b58\u5728\u8fd9\u6837\u7684\u5143\u7d20\uff0c\u5219\u8fd4\u56de\u5c3e\u8fed\u4ee3\u5668\u3002lower_bound(v.begin(),v.end(),x)
\u3002upper_bound
\uff1a\u5728\u4e00\u4e2a\u6709\u5e8f\u5e8f\u5217\u4e2d\u8fdb\u884c\u4e8c\u5206\u67e5\u627e\uff0c\u8fd4\u56de\u6307\u5411\u7b2c\u4e00\u4e2a\u00a0\u5927\u4e8e \u00a0\u7684\u5143\u7d20\u7684\u4f4d\u7f6e\u7684\u8fed\u4ee3\u5668\u3002\u5982\u679c\u4e0d\u5b58\u5728\u8fd9\u6837\u7684\u5143\u7d20\uff0c\u5219\u8fd4\u56de\u5c3e\u8fed\u4ee3\u5668\u3002upper_bound(v.begin(),v.end(),x)
\u3002next_permutation
\uff1a\u5c06\u5f53\u524d\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u4e0b\u4e00\u4e2a\u6392\u5217\u3002\u5982\u679c\u5f53\u524d\u6392\u5217\u5df2\u7ecf\u662f\u00a0\u5168\u6392\u5217\u4e2d\u7684\u6700\u540e\u4e00\u4e2a\u6392\u5217\uff08\u5143\u7d20\u5b8c\u5168\u4ece\u5927\u5230\u5c0f\u6392\u5217\uff09\uff0c\u51fd\u6570\u8fd4\u56de\u00a0false
\u00a0\u5e76\u5c06\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u7b2c\u4e00\u4e2a\u6392\u5217\uff08\u5143\u7d20\u5b8c\u5168\u4ece\u5c0f\u5230\u5927\u6392\u5217\uff09\uff1b\u5426\u5219\uff0c\u51fd\u6570\u8fd4\u56de\u00a0true
\u3002next_permutation(v.begin(), v.end())
\u00a0\u6216\u00a0next_permutation(v + begin, v + end)
\u3002prev_permutation
\uff1a\u5c06\u5f53\u524d\u6392\u5217\u66f4\u6539\u4e3a\u00a0\u5168\u6392\u5217\u4e2d\u7684\u4e0a\u4e00\u4e2a\u6392\u5217\u3002\u7528\u6cd5\u540c\u00a0next_permutation
\u3002partial_sum
\uff1a\u6c42\u524d\u7f00\u548c\u3002\u8bbe\u6e90\u5bb9\u5668\u4e3a\u00a0\uff0c\u76ee\u6807\u5bb9\u5668\u4e3a\u00a0\uff0c\u5219\u4ee4\u00a0\u3002partial_sum(src.begin(), src.end(), back_inserter(dst))
\u3002TODO bitset - OI Wiki
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#23-string","title":"2.3 string","text":"std::string s;\nprintf(\"%s\", s.c_str());\nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", s.size()); \nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", s.length()); \nprintf(\"s \u7684\u957f\u5ea6\u4e3a %lu\", strlen(s.c_str()));\nsubstr(pos, len);\ninsert(index, count, ch);\ninsert(index, str);\nerase(index, count);\nreplace(pos, count, str);\nreplace(first, last, str);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#24-pair","title":"2.4 pair","text":"pair
\u4e0d\u9700\u8981\u989d\u5916\u5b9a\u4e49\u7ed3\u6784\u4e0e\u91cd\u8f7d\u8fd0\u7b97\u7b26pair<int, double> p0(1, 2.0);\npair<int, double> p2 = make_pair(1, 2.0);\nauto p3 = make_pair(1, 2.0);\n\nint i = p0.first; \ndouble d = p0.second;\np1.first++;\n\npriority_queue<pair<int, double> > q;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3","title":"3 \u8fdb\u9636","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#31","title":"3.1 \u7c7b","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#32","title":"3.2 \u52a8\u6001\u5185\u5b58","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#321-new-delete","title":"3.2.1 new \u548c delete \u8fd0\u7b97\u7b26","text":"new data-type;\n\ndouble* pvalue = NULL;\npvalue = new double;\n\nif (!(pvalue = new double)) {\n cout << \"Error: out of memory.\" << endl;\n exit(1);\n}\n\ndelete pvalue;\n
int ***array;\n// \u5047\u5b9a\u6570\u7ec4\u7b2c\u4e00\u7ef4\u4e3a m\uff0c \u7b2c\u4e8c\u7ef4\u4e3a n\uff0c \u7b2c\u4e09\u7ef4\u4e3ah\n// \u52a8\u6001\u5206\u914d\u7a7a\u95f4\narray = new int **[m];\nfor( int i=0; i<m; i++ )\n{\n array[i] = new int *[n];\n for( int j=0; j<n; j++ )\n {\n array[i][j] = new int [h];\n }\n}\n//\u91ca\u653e\nfor( int i=0; i<m; i++ )\n{\n for( int j=0; j<n; j++ )\n {\n delete [] array[i][j];\n }\n delete [] array[i];\n}\ndelete [] array;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#323","title":"3.2.3 \u5bf9\u8c61\u7684\u52a8\u6001\u5185\u5b58\u5206\u914d","text":"C++#include <iostream>\nusing namespace std;\n\nclass Box\n{\n public:\n Box() { \n cout << \"\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\" <<endl; \n }\n ~Box() { \n cout << \"\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\" <<endl; \n }\n};\n\nint main( )\n{\n Box* myBoxArray = new Box[4]; // \u4e00\u4e2a\u5305\u542b 4 \u4e2a Box \u5bf9\u8c61\u7684\u6570\u7ec4\n\n delete [] myBoxArray; // \u5220\u9664\u6570\u7ec4\n return 0;\n}\n
Text Only\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6784\u9020\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n\u8c03\u7528\u6790\u6784\u51fd\u6570\uff01\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#33","title":"3.3 \u547d\u540d\u7a7a\u95f4","text":"namespace namespace_name {\n // code\n}\n\nnamespace_name::code;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#332-using","title":"3.3.2 using \u6307\u4ee4","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#333","title":"3.3.3 \u4e0d\u8fde\u7eed\u7684\u547d\u540d\u7a7a\u95f4","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#334","title":"3.3.4 \u5d4c\u5957\u7684\u547d\u540d\u7a7a\u95f4","text":"C++namespace namespace_name1 {\n // \u4ee3\u7801\u58f0\u660e\n namespace namespace_name2 {\n // \u4ee3\u7801\u58f0\u660e\n }\n}\n\n// \u8bbf\u95ee namespace_name2 \u4e2d\u7684\u6210\u5458\nusing namespace namespace_name1::namespace_name2;\n\n// \u8bbf\u95ee namespace_name1 \u4e2d\u7684\u6210\u5458\nusing namespace namespace_name1;\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#34","title":"3.4 \u6a21\u677f","text":"template <typename type> ret-type func-name(parameter list)\n{\n // \u51fd\u6570\u7684\u4e3b\u4f53\n}\n
C++#include <iostream>\n#include <string>\n\nusing namespace std;\n\ntemplate <typename T>\ninline T const& Max (T const& a, T const& b) \n{ \n return a < b ? b:a; \n} \n\nint main ()\n{\n\n int i = 39;\n int j = 20;\n cout << \"Max(i, j): \" << Max(i, j) << endl; \n\n double f1 = 13.5; \n double f2 = 20.7; \n cout << \"Max(f1, f2): \" << Max(f1, f2) << endl; \n\n string s1 = \"Hello\"; \n string s2 = \"World\"; \n cout << \"Max(s1, s2): \" << Max(s1, s2) << endl; \n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#342","title":"3.4.2 \u7c7b\u6a21\u677f","text":"C++template <class type> class class-name {\n// code\n}\n
C++#include <iostream>\n#include <vector>\n#include <cstdlib>\n#include <string>\n#include <stdexcept>\n\nusing namespace std;\n\ntemplate <class T>\nclass Stack { \n private: \n vector<T> elems; // \u5143\u7d20 \n\n public: \n void push(T const&); // \u5165\u6808\n void pop(); // \u51fa\u6808\n T top() const; // \u8fd4\u56de\u6808\u9876\u5143\u7d20\n bool empty() const{ // \u5982\u679c\u4e3a\u7a7a\u5219\u8fd4\u56de\u771f\u3002\n return elems.empty(); \n } \n}; \n\ntemplate <class T>\nvoid Stack<T>::push (T const& elem) \n{ \n // \u8ffd\u52a0\u4f20\u5165\u5143\u7d20\u7684\u526f\u672c\n elems.push_back(elem); \n} \n\ntemplate <class T>\nvoid Stack<T>::pop () \n{ \n if (elems.empty()) { \n throw out_of_range(\"Stack<>::pop(): empty stack\"); \n }\n // \u5220\u9664\u6700\u540e\u4e00\u4e2a\u5143\u7d20\n elems.pop_back(); \n} \n\ntemplate <class T>\nT Stack<T>::top () const \n{ \n if (elems.empty()) { \n throw out_of_range(\"Stack<>::top(): empty stack\"); \n }\n // \u8fd4\u56de\u6700\u540e\u4e00\u4e2a\u5143\u7d20\u7684\u526f\u672c \n return elems.back(); \n} \n\nint main() \n{ \n try { \n Stack<int> intStack; // int \u7c7b\u578b\u7684\u6808 \n Stack<string> stringStack; // string \u7c7b\u578b\u7684\u6808 \n\n // \u64cd\u4f5c int \u7c7b\u578b\u7684\u6808 \n intStack.push(7); \n cout << intStack.top() <<endl; \n\n // \u64cd\u4f5c string \u7c7b\u578b\u7684\u6808 \n stringStack.push(\"hello\"); \n cout << stringStack.top() << std::endl; \n stringStack.pop(); \n stringStack.pop(); \n } \n catch (exception const& ex) { \n cerr << \"Exception: \" << ex.what() <<endl; \n return -1;\n } \n}\n
Text Only7\nhello\nException: Stack<>::pop(): empty stack\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#35","title":"3.5 \u9884\u5904\u7406\u5668","text":"#define macro-name replacement-text \n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#352","title":"3.5.2 \u53c2\u6570\u5b8f","text":"C++#include <iostream>\nusing namespace std;\n\n#define MIN(a,b) (a<b ? a : b)\n\nint main ()\n{\n int i, j;\n i = 100;\n j = 30;\n cout <<\"\u8f83\u5c0f\u7684\u503c\u4e3a\uff1a\" << MIN(i, j) << endl;\n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#353","title":"3.5.3 \u6761\u4ef6\u7f16\u8bd1","text":"C++#ifdef NULL\n #define NULL 0\n#endif\n\n#ifdef DEBUG\n cerr <<\"Variable x = \" << x << endl;\n#endif\n\n#if 0\n \u4e0d\u8fdb\u884c\u7f16\u8bd1\u7684\u4ee3\u7801\n#endif\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#354","title":"3.5.4 # \u548c ## \u8fd0\u7b97\u7b26","text":"C++#include <iostream>\nusing namespace std;\n\n#define MKSTR( x ) #x\n\nint main ()\n{\n cout << MKSTR(HELLO C++) << endl;\n\n return 0;\n}\n
C++#include <iostream>\nusing namespace std;\n\n#define concat(a, b) a ## b\nint main()\n{\n int xy = 100;\n\n cout << concat(x, y);\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#355","title":"3.5.5 \u9884\u5b9a\u4e49\u5b8f","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#36","title":"3.6 \u4fe1\u53f7\u5904\u7406","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#361-signal","title":"3.6.1 signal () \u51fd\u6570","text":"C++void (*signal (int sig, void (*func)(int)))(int); \n\nsignal(registered signal, signal handler)\n
C++#include <iostream>\n#include <csignal>\n#include <unistd.h>\n\nusing namespace std;\n\nvoid signalHandler( int signum )\n{\n cout << \"Interrupt signal (\" << signum << \") received.\\n\";\n\n // \u6e05\u7406\u5e76\u5173\u95ed\n // \u7ec8\u6b62\u7a0b\u5e8f \n\n exit(signum); \n\n}\n\nint main ()\n{\n // \u6ce8\u518c\u4fe1\u53f7 SIGINT \u548c\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\n signal(SIGINT, signalHandler); \n\n while(1){\n cout << \"Going to sleep....\" << endl;\n sleep(1);\n }\n\n return 0;\n}\n
\u6309 Ctrl + C \u4e2d\u65ad\u7a0b\u5e8f:
Text OnlyGoing to sleep....\nGoing to sleep....\nGoing to sleep....\nInterrupt signal (2) received.\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#362-raise","title":"3.6.2 raise () \u51fd\u6570","text":"C++int raise (signal sig);\n
C++#include <iostream>\n#include <csignal>\n#include <unistd.h>\n\nusing namespace std;\n\nvoid signalHandler( int signum )\n{\n cout << \"Interrupt signal (\" << signum << \") received.\\n\";\n\n // \u6e05\u7406\u5e76\u5173\u95ed\n // \u7ec8\u6b62\u7a0b\u5e8f \n\n exit(signum); \n\n}\n\nint main ()\n{\n int i = 0;\n // \u6ce8\u518c\u4fe1\u53f7 SIGINT \u548c\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\n signal(SIGINT, signalHandler); \n\n while(++i){\n cout << \"Going to sleep....\" << endl;\n if( i == 3 ){\n raise(SIGINT);\n }\n sleep(1);\n }\n\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#37","title":"3.7 \u591a\u7ebf\u7a0b","text":"#include<thread>\nstd::thread thread_object(callable, args...);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3721","title":"3.7.2.1 \u4f7f\u7528\u51fd\u6570\u6307\u9488","text":"C++#include <iostream>\n#include <thread>\n\nvoid printMessage(int count) {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (function pointer)!\\n\";\n }\n}\n\nint main() {\n std::thread t1(printMessage, 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012\u51fd\u6570\u6307\u9488\u548c\u53c2\u6570\n t1.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3722","title":"3.7.2.2 \u4f7f\u7528\u51fd\u6570\u5bf9\u8c61","text":"C++#include <iostream>\n#include <thread>\n\nclass PrintTask {\npublic:\n void operator()(int count) const {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (function object)!\\n\";\n }\n }\n};\n\nint main() {\n std::thread t2(PrintTask(), 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012\u51fd\u6570\u5bf9\u8c61\u548c\u53c2\u6570\n t2.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3723-lambda","title":"3.7.2.3 \u4f7f\u7528 Lambda \u8868\u8fbe\u5f0f","text":"C++#include <iostream>\n#include <thread>\n\nint main() {\n std::thread t3([](int count) {\n for (int i = 0; i < count; ++i) {\n std::cout << \"Hello from thread (lambda)!\\n\";\n }\n }, 5); // \u521b\u5efa\u7ebf\u7a0b\uff0c\u4f20\u9012 Lambda \u8868\u8fbe\u5f0f\u548c\u53c2\u6570\n t3.join(); // \u7b49\u5f85\u7ebf\u7a0b\u5b8c\u6210\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3724","title":"3.7.2.4 \u7ebf\u7a0b\u7ba1\u7406","text":"C++t.join();\nt.detach();\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3725","title":"3.7.2.5 \u7ebf\u7a0b\u7684\u4f20\u53c2","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3726","title":"3.7.2.6 \u503c\u4f20\u9012","text":"C++std::thread t(funx, arg1, arg2);\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3727","title":"3.7.2.7 \u5f15\u7528\u4f20\u9012","text":"C++#include <iostream>\n#include <thread>\n\nvoid increment(int& x) {\n ++x;\n}\n\nint main() {\n int num = 0;\n std::thread t(increment, std::ref(num)); // \u4f7f\u7528 std::ref \u4f20\u9012\u5f15\u7528\n t.join();\n std::cout << \"Value after increment: \" << num << std::endl;\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#373","title":"3.7.3 \u7ebf\u7a0b\u540c\u6b65\u4e0e\u4e92\u65a5","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3731-mutex","title":"3.7.3.1 \u4e92\u65a5\u91cf\uff08Mutex\uff09","text":"C++std::mutex mtx;\nmtx.lock(); // \u9501\u5b9a\u4e92\u65a5\u9501\n// \u8bbf\u95ee\u5171\u4eab\u8d44\u6e90\nmtx.unlock();// \u91ca\u653e\u4e92\u65a5\u9501\n\nstd::lock_guard<std::mutex> lock(mtx); // \u81ea\u52a8\u9501\u5b9a\u548c\u89e3\u9501\n// \u8bbf\u95ee\u5171\u4eab\u8d44\u6e90\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3732-locks","title":"3.7.3.2 \u9501\uff08Locks\uff09","text":"std::lock_guard
\uff1a\u4f5c\u7528\u57df\u9501\uff0c\u5f53\u6784\u9020\u65f6\u81ea\u52a8\u9501\u5b9a\u4e92\u65a5\u91cf\uff0c\u5f53\u6790\u6784\u65f6\u81ea\u52a8\u89e3\u9501\u3002std::unique_lock
\uff1a\u4e0e std::lock_guard
\u7c7b\u4f3c\uff0c\u4f46\u63d0\u4f9b\u4e86\u66f4\u591a\u7684\u7075\u6d3b\u6027\uff0c\u4f8b\u5982\u53ef\u4ee5\u8f6c\u79fb\u6240\u6709\u6743\u548c\u624b\u52a8\u89e3\u9501\u3002#include <mutex>\n\nstd::mutex mtx;\n\nvoid safeFunctionWithLockGuard() {\n std::lock_guard<std::mutex> lk(mtx);\n // \u8bbf\u95ee\u6216\u4fee\u6539\u5171\u4eab\u8d44\u6e90\n}\n\nvoid safeFunctionWithUniqueLock() {\n std::unique_lock<std::mutex> ul(mtx);\n // \u8bbf\u95ee\u6216\u4fee\u6539\u5171\u4eab\u8d44\u6e90\n // ul.unlock(); // \u53ef\u9009\uff1a\u624b\u52a8\u89e3\u9501\n // ...\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3733-condition-variable","title":"3.7.3.3 \u6761\u4ef6\u53d8\u91cf\uff08Condition Variable\uff09","text":"C++std::condition_variable cv;\nstd::mutex mtx;\nbool ready = false;\n\nstd::unique_lock<std::mutex> lock(mtx);\ncv.wait(lock, []{ return ready; }); // \u7b49\u5f85\u6761\u4ef6\u6ee1\u8db3\n// \u6761\u4ef6\u6ee1\u8db3\u540e\u6267\u884c\n
C++#include <mutex>\n#include <condition_variable>\n\nstd::mutex mtx;\nstd::condition_variable cv;\nbool ready = false;\n\nvoid workerThread() {\n std::unique_lock<std::mutex> lk(mtx);\n cv.wait(lk, []{ return ready; }); // \u7b49\u5f85\u6761\u4ef6\n // \u5f53\u6761\u4ef6\u6ee1\u8db3\u65f6\u6267\u884c\u5de5\u4f5c\n}\n\nvoid mainThread() {\n {\n std::lock_guard<std::mutex> lk(mtx);\n // \u51c6\u5907\u6570\u636e\n ready = true;\n } // \u79bb\u5f00\u4f5c\u7528\u57df\u65f6\u89e3\u9501\n cv.notify_one(); // \u901a\u77e5\u4e00\u4e2a\u7b49\u5f85\u7684\u7ebf\u7a0b\n}\n
TODO
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3734-atomic-operations","title":"3.7.3.4 \u539f\u5b50\u64cd\u4f5c\uff08Atomic Operations\uff09","text":"#include <atomic>\n#include <thread>\n\nstd::atomic<int> count(0);\n\nvoid increment() {\n count.fetch_add(1, std::memory_order_relaxed);\n}\n\nint main() {\n std::thread t1(increment);\n std::thread t2(increment);\n t1.join();\n t2.join();\n return count; // \u5e94\u8fd4\u56de2\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3735-thread-local-storagetls","title":"3.7.3.5 \u7ebf\u7a0b\u5c40\u90e8\u5b58\u50a8\uff08Thread Local Storage\uff0cTLS\uff09","text":"#include <iostream>\n#include <thread>\n\nthread_local int threadData = 0;\n\nvoid threadFunction() {\n threadData = 42; // \u6bcf\u4e2a\u7ebf\u7a0b\u90fd\u6709\u81ea\u5df1\u7684threadData\u526f\u672c\n std::cout << \"Thread data: \" << threadData << std::endl;\n}\n\nint main() {\n std::thread t1(threadFunction);\n std::thread t2(threadFunction);\n t1.join();\n t2.join();\n return 0;\n}\n
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#3736-deadlock","title":"3.7.3.6 \u6b7b\u9501\uff08Deadlock\uff09\u548c\u907f\u514d\u7b56\u7565","text":"std::promise<int> p;\nstd::future<int> f = p.get_future();\n\nstd::thread t([&p] {\n p.set_value(10); // \u8bbe\u7f6e\u503c\uff0c\u89e6\u53d1 future\n});\n\nint result = f.get(); // \u83b7\u53d6\u503c\n
C++17 \u5f15\u5165\u4e86\u5e76\u884c\u7b97\u6cd5\u5e93
C++#include <algorithm>\n#include <vector>\n#include <execution>\n\nstd::vector<int> vec = {1, 2, 3, 4, 5};\nstd::for_each(std::execution::par, vec.begin(), vec.end(), [](int &n) {\n n *= 2;\n});\n
TODO \u591a\u7ebf\u7a0b\u5b9e\u4f8b
"},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#38-web","title":"3.8 Web \u7f16\u7a0b","text":""},{"location":"CS_Basic/C%2B%2B/C%2B%2B%20Basic/#381-cgi","title":"3.8.1 \u4ec0\u4e48\u662f CGI\uff1f","text":"TODO
"},{"location":"CS_Basic/CS61A/CS61A/","title":"CS61A","text":""},{"location":"CS_Basic/CS61A/CS61A/#cs61a","title":"CS61A","text":"\u7ea6 24 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u7ea6 2713 \u4e2a\u5b57 651 \u884c\u4ee3\u7801 2 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 22 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/CS61A/Composing_Programs/#1","title":"1 \u4f7f\u7528\u51fd\u6570\u6784\u5efa\u62bd\u8c61","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#11","title":"1.1 \u5f00\u59cb","text":"\u7a0b\u5e8f\u7531\u4e24\u90e8\u5206\u7ec4\u6210:
\u6c42\u503c\u7a0b\u5e8f\u672c\u8d28\u4e0a\u662f\u9012\u5f52\u7684
Pure functions None-pure functions which has a side effect
"},{"location":"CS_Basic/CS61A/Composing_Programs/#13","title":"1.3 \u5b9a\u4e49\u65b0\u7684\u51fd\u6570","text":"Pythondef <name>(<formal parameters>):\n return <return expression> \n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#131","title":"1.3.1 \u73af\u5883","text":"environment has some frames frames have some bindings
PEP 8 \u2013 Style Guide for Python Code | peps.python.org
"},{"location":"CS_Basic/CS61A/Composing_Programs/#136","title":"1.3.6 \u62bd\u8c61\u51fd\u6570","text":"docstring
"},{"location":"CS_Basic/CS61A/Composing_Programs/#142","title":"1.4.2 \u53c2\u6570\u9ed8\u8ba4\u503c","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#15","title":"1.5 \u63a7\u5236","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#151","title":"1.5.1 \u8bed\u53e5","text":"header suite
Python<header>:\n <statement>\n <statement>\n ...\n<separating header>:\n <statement>\n <statement>\n ...\n...\n
def \u662f\u590d\u5408\u8bed\u53e5 the header controls its suite \u8fd9\u4e2a\u5b9a\u4e49\u63ed\u793a\u4e86\u9012\u5f52\u5b9a\u4e49\u5e8f\u5217\uff08sequence\uff09\u7684\u57fa\u672c\u7ed3\u6784\uff1a\u4e00\u4e2a\u5e8f\u5217\u53ef\u4ee5\u5206\u89e3\u6210\u5b83\u7684\u7b2c\u4e00\u4e2a\u5143\u7d20\u548c\u5176\u4f59\u5143\u7d20 redirected control
"},{"location":"CS_Basic/CS61A/Composing_Programs/#153-ii","title":"1.5.3 \u00a0\u5b9a\u4e49\u51fd\u6570 II\uff1a\u5c40\u90e8\u8d4b\u503c","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#154","title":"1.5.4 \u6761\u4ef6\u8bed\u53e5","text":"Pythonif <expression>:\n <suite>\nelif <expression>:\n <suite>\nelse:\n <suite>\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#155","title":"1.5.5 \u8fed\u4ee3","text":"iteractive control
Pythonwhile <expression>:\n <suite>\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#156","title":"1.5.6 \u6d4b\u8bd5","text":"assertions
Python>>> assert fib(8) == 13, '\u7b2c\u516b\u4e2a\u6590\u6ce2\u90a3\u5951\u6570\u5e94\u8be5\u662f 13'\n
Doctests
Python>>> def sum_naturals(n):\n \"\"\"\u8fd4\u56de\u524d n \u4e2a\u81ea\u7136\u6570\u7684\u548c\u3002\n\n >>> sum_naturals(10)\n 55\n >>> sum_naturals(100)\n 5050\n \"\"\"\n total, k = 0, 1\n while k <= n:\n total, k = total + k, k + 1\n return total\n
Python>>> from doctest import testmod\n>>> testmod()\nTestResults(failed=0, attempted=2)\n
\u5355\u4e2a\u51fd\u6570\u7684\u4ea4\u4e92
Python>>> from doctest import run_docstring_examples\n>>> run_docstring_examples(sum_naturals, globals(), True)\nFinding tests in NoName\nTrying:\n\u00a0\u00a0\u00a0 sum_naturals(10)\nExpecting:\n\u00a0\u00a0\u00a0 55\nok\nTrying:\n\u00a0\u00a0\u00a0 sum_naturals(100)\nExpecting:\n\u00a0\u00a0\u00a0 5050\nok\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#16","title":"1.6 \u9ad8\u9636\u51fd\u6570","text":">>> def summation(n, term):\n total, k = 0, 1\n while k <= n:\n total, k = total + term(k), k + 1\n return total\n>>> def identity(x):\n return x\n>>> def sum_naturals(n):\n return summation(n, identity)\n>>> sum_naturals(10)\n55\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#162","title":"1.6.2 \u4f5c\u4e3a\u901a\u7528\u65b9\u6cd5\u7684\u51fd\u6570","text":"\u4e24\u4e2a\u540e\u679c:
>>> def curry2(f):\n \"\"\"\u8fd4\u56de\u7ed9\u5b9a\u7684\u53cc\u53c2\u6570\u51fd\u6570\u7684\u67ef\u91cc\u5316\u7248\u672c\"\"\"\n def g(x):\n def h(y):\n return f(x, y)\n return h\n return g\n>>> def uncurry2(g):\n \"\"\"\u8fd4\u56de\u7ed9\u5b9a\u7684\u67ef\u91cc\u5316\u51fd\u6570\u7684\u53cc\u53c2\u6570\u7248\u672c\"\"\"\n def f(x, y):\n return g(x)(y)\n return f\n>>> pow_curried = curry2(pow)\n>>> pow_curried(2)(5)\n32\n>>> map_to_range(0, 10, pow_curried(2))\n1\n2\n4\n8\n16\n32\n64\n128\n256\n512\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#167-lambda","title":"1.6.7 Lambda \u8868\u8fbe\u5f0f","text":"Pythonlambda x : f(g(x))\n\"A function that takes x and returns f(g(x))\"\n
\\(\\displaystyle \\lambda\\)
Python>>> s = lambda x: x * x\n>>> s\n<function <lambda> at 0xf3f490>\n>>> s(12)\n144\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#168","title":"1.6.8 \u62bd\u8c61\u548c\u4e00\u7b49\u51fd\u6570","text":">>> def trace(fn):\n def wrapped(x):\n print('-> ', fn, '(', x, ')')\n return fn(x)\n return wrapped\n\n>>> @trace\n def triple(x):\n return 3 * x\n\n>>> triple(12)\n-> <function triple at 0x102a39848> ( 12 )\n36\n
>>> def triple(x):\n return 3 * x\n>>> triple = trace(triple)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#17","title":"1.7 \u9012\u5f52\u51fd\u6570","text":">>> def count_partitions(n, m):\n\u00a0\u00a0\u00a0 \"\"\"\u8ba1\u7b97\u4f7f\u7528\u6700\u5927\u6570 m \u7684\u6574\u6570\u5206\u5272 n \u7684\u65b9\u5f0f\u7684\u6570\u91cf\"\"\"\n\u00a0\u00a0\u00a0 if n == 0:\n\u00a0\u00a0\u00a0 return 1\n\u00a0\u00a0\u00a0 elif n < 0:\n\u00a0\u00a0\u00a0 return 0\n\u00a0\u00a0\u00a0 elif m == 0:\n\u00a0\u00a0\u00a0 return 0\n\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0\u00a0 return count_partitions(n-m, m) + count_partitions(n, m-1)\n\n>>> count_partitions(6, 4)\n9\n>>> count_partitions(5, 5)\n7\n>>> count_partitions(10, 10)\n42\n>>> count_partitions(15, 15)\n176\n>>> count_partitions(20, 20)\n627\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#2","title":"2 \u4f7f\u7528\u6570\u636e\u6784\u5efa\u62bd\u8c61","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#21","title":"2.1 \u5f15\u8a00","text":"\u539f\u59cb\u6570\u636e\u7c7b\u578b\u5177\u6709\u5c5e\u6027:
wishful thinking
Python>>> def add_rationals(x, y):\n nx, dx = numer(x), denom(x)\n ny, dy = numer(y), denom(y)\n return rational(nx * dy + ny * dx, dx * dy)\n\n>>> def mul_rationals(x, y):\n return rational(numer(x) * numer(y), denom(x) * denom(y))\n\n>>> def print_rational(x):\n print(numer(x), '/', denom(x))\n\n>>> def rationals_are_equal(x, y):\n return numer(x) * denom(y) == numer(y) * denom(x)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#222-pair","title":"2.2.2 pair","text":"from operator import getitem
Python>>> def rational(n, d):\n return [n, d]\n\n>>> def numer(x):\n return x[0]\n\n>>> def denom(x):\n return x[1]\n
\u7b80\u5316\u6709\u7406\u6570:
Python>>> from fractions import gcd\n>>> def rational(n, d):\n g = gcd(n, d)\n return (n//g, d//g)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#223","title":"2.2.3 \u62bd\u8c61\u5c4f\u969c","text":">>> def square_rational(x):\n return mul_rational(x, x)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#224","title":"2.2.4 \u6570\u636e\u7684\u5c5e\u6027","text":"\u76f8\u5f53\u4e8e\u81ea\u5df1\u5199\u4e00\u4e2a\u6570\u636e\u7ed3\u6784:
Python>>> def pair(x, y):\n \"\"\"Return a function that represents a pair.\"\"\"\n def get(index):\n if index == 0:\n return x\n elif index == 1:\n return y\n return get\n\n>>> def select(p, i):\n \"\"\"Return the element at index i of pair p.\"\"\"\n return p(i)\n\n>>> p = pair(20, 14)\n>>> select(p, 0)\n20\n>>> select(p, 1)\n14\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#23","title":"2.3 \u5e8f\u5217","text":"for <name> in <expression>:\n <suite>\n
the expression must produce an iterable object sequence unpacking
Python>>> pairs = [[1, 2], [2, 2], [2, 3], [4, 4]]\n>>> same_count = 0\n>>> for x, y in pairs:\n if x == y:\n same_count = same_count + 1\n>>> same_count\n2\n
range
"},{"location":"CS_Basic/CS61A/Composing_Programs/#233","title":"2.3.3 \u5e8f\u5217\u5904\u7406","text":"list comprehensions
Python>>> odds = [1, 3, 5, 7, 9]\n>>> [x+1 for x in odds]\n[2, 4, 6, 8, 10]\n[<map expression> for <name> in <sequence expression> if <filter expression>]\n
>>> def apply_to_all(map_fn, s):\n return [map_fn(x) for x in s]\n>>> def keep_if(filter_fn, s):\n return [x for x in s if filter_fn(x)]\n# conventional names\n>>> apply_to_all = lambda map_fn, s: list(map(map_fn, s))\n>>> keep_if = lambda filter_fn, s: list(filter(filter_fn, s))\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#234","title":"2.3.4 \u5e8f\u5217\u62bd\u8c61","text":"string \u6ca1\u6709\u5b57\u7b26\u7c7b\u578b
closure property bax-and-pointer notation
>>> def fib_tree(n):\n if n == 0 or n == 1:\n return tree(n)\n else:\n left, right = fib_tree(n-2), fib_tree(n-1)\n fib_n = label(left) + label(right)\n return tree(fib_n, [left, right])\n>>> fib_tree(5)\n[5, [2, [1], [1, [0], [1]]], [3, [1, [0], [1]], [2, [1], [1, [0], [1]]]]]\n
Python>>> def count_leaves(tree):\n if is_leaf(tree):\n return 1\n else:\n branch_counts = [count_leaves(b) for b in branches(tree)]\n return sum(branch_counts)\n>>> count_leaves(fib_tree(5))\n8\n
Partition trees
Python>>> def print_parts(tree, partition=[]):\n if is_leaf(tree):\n if label(tree):\n print(' + '.join(partition))\n else:\n left, right = branches(tree)\n m = str(label(tree))\n print_parts(left, partition + [m])\n print_parts(right, partition)\n\n>>> print_parts(partition_tree(6, 4))\n4 + 2\n4 + 1 + 1\n3 + 3\n3 + 2 + 1\n3 + 1 + 1 + 1\n2 + 2 + 2\n2 + 2 + 1 + 1\n2 + 1 + 1 + 1 + 1\n1 + 1 + 1 + 1 + 1 + 1\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#237","title":"2.3.7 \u94fe\u8868","text":"linked list abstract data representation
Python>>> def partitions(n, m):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u5305\u542b n \u7684\u5206\u5272\u65b9\u6848\u7684\u94fe\u8868\uff0c\u5176\u4e2d\u6bcf\u4e2a\u6b63\u6574\u6570\u4e0d\u8d85\u8fc7 m\"\"\"\nif n == 0:\n return link(empty, empty) # \u5305\u542b\u7a7a\u5206\u5272\u7684\u94fe\u8868\nelif n < 0 or m == 0:\n return empty\nelse:\n using_m = partitions(n-m, m)\n with_m = apply_to_all_link(lambda s: link(m, s), using_m)\n without_m = partitions(n, m-1)\n return extend_link(with_m, without_m)\n\n>>> def print_partitions(n, m):\n lists = partitions(n, m)\n strings = apply_to_all_link(lambda s: join_link(s, \" + \"), lists)\n print(join_link(strings, \"\\n\"))\n\n>>> print_partitions(6, 4)\n4 + 2\n4 + 1 + 1\n3 + 3\n3 + 2 + 1\n3 + 1 + 1 + 1\n2 + 2 + 2\n2 + 2 + 1 + 1\n2 + 1 + 1 + 1 + 1\n1 + 1 + 1 + 1 + 1 + 1\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#24","title":"2.4 \u53ef\u53d8\u6570\u636e","text":"object-oriented programming
"},{"location":"CS_Basic/CS61A/Composing_Programs/#241","title":"2.4.1 \u5bf9\u8c61\u9690\u55bb","text":"mutable Sharing and Identity \u5217\u8868\u63a8\u5bfc\u5f0f:
Python>>> from unicodedata import lookup\n>>> [lookup('WHITE ' + s.upper() + ' SUIT') for s in suits]\n['\u2661', '\u2662', '\u2664', '\u2667']\n
tuple
"},{"location":"CS_Basic/CS61A/Composing_Programs/#243","title":"2.4.3 \u5b57\u5178","text":"key-value pairs
"},{"location":"CS_Basic/CS61A/Composing_Programs/#244","title":"2.4.4 \u5c40\u90e8\u72b6\u6001","text":"local state
Python>>> def make_withdraw(balance):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u6bcf\u6b21\u8c03\u7528\u90fd\u4f1a\u51cf\u5c11 balance \u7684 withdraw \u51fd\u6570\"\"\"\ndef withdraw(amount):\n nonlocal balance # \u58f0\u660e balance \u662f\u975e\u5c40\u90e8\u7684\n if amount > balance:\n return '\u4f59\u989d\u4e0d\u8db3'\n balance = balance - amount # \u91cd\u65b0\u7ed1\u5b9a\n return balance\nreturn withdraw\n
Python Particulars
"},{"location":"CS_Basic/CS61A/Composing_Programs/#245-non-local","title":"2.4.5 \u975e\u5c40\u90e8 Non-local \u8d4b\u503c\u7684\u597d\u5904","text":"\u8fd9\u6837\uff0c\u6bcf\u4e2a withdraw \u5b9e\u4f8b\u90fd\u4fdd\u6301\u81ea\u5df1\u7684 balance \u72b6\u6001\uff0c\u4f46\u7a0b\u5e8f\u4e2d\u7684\u4efb\u4f55\u5176\u4ed6\u51fd\u6570\u90fd\u65e0\u6cd5\u8bbf\u95ee\u8be5\u72b6\u6001\u3002\u4ece\u66f4\u9ad8\u7684\u5c42\u9762\u6765\u770b\u8fd9\u79cd\u60c5\u51b5\uff0c\u6211\u4eec\u62bd\u8c61\u4e86\u4e00\u4e2a\u94f6\u884c\u8d26\u6237\uff0c\u5b83\u81ea\u5df1\u7ba1\u7406\u81ea\u5df1\u7684\u72b6\u6001\uff0c\u5176\u884c\u4e3a\u65b9\u5f0f\u4e0e\u4e16\u754c\u4e0a\u6240\u6709\u5176\u5b83\u8d26\u6237\u4e00\u6837\uff1a\u968f\u7740\u65f6\u95f4\u63a8\u79fb\uff0c\u8d26\u6237\u7684\u72b6\u6001\u4f1a\u6839\u636e\u8d26\u6237\u7684\u53d6\u6b3e\u8bb0\u5f55\u800c\u53d1\u751f\u53d8\u5316\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#246-non-local","title":"2.4.6 \u975e\u5c40\u90e8 Non-local \u8d4b\u503c\u7684\u4ee3\u4ef7","text":"\u51fd\u6570\u662f\u4e00\u4e2a dispatch \uff08\u8c03\u5ea6\uff09\u51fd\u6570\uff0c\u5176\u53c2\u6570\u9996\u5148\u662f\u4e00\u4e2a\u671f\u671b\u7684\u6307\u4ee4\uff0c\u4ee3\u8868\u671f\u671b\u8fd9\u4e2a\u51fd\u6570\u505a\u4ec0\u4e48\uff1b\u7136\u540e\u662f\u8be5\u65b9\u6cd5\u7684\u9700\u8981\u7528\u5230\u7684\u53c2\u6570\u3002\u6b64\u6307\u4ee4\u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\uff0c\u7528\u4e8e\u547d\u540d\u51fd\u6570\u5e94\u6267\u884c\u7684\u64cd\u4f5c\u3002\u53ef\u4ee5\u5c06\u8fd9\u4e2a dispatch \u51fd\u6570\u7406\u89e3\u4e3a\u591a\u4e2a\u4e0d\u540c\u51fd\u6570\u7684\u62bd\u8c61\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u786e\u5b9a\u76ee\u6807\u51fd\u6570\u7684\u884c\u4e3a\uff0c\u5e76\u4e3a\u8be5\u884c\u4e3a\u5165\u53c2\u5176\u4ed6\u53c2\u6570\u3002 \u7528\u5b57\u7b26\u4e32\u4e5f\u592a\u9006\u5929\u4e86\u3002
Python>>> def mutable_link():\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u53ef\u53d8\u94fe\u8868\u7684\u51fd\u6570\"\"\"\ncontents = empty\ndef dispatch(message, value=None):\n nonlocal contents\n if message == 'len':\n return len_link(contents)\n elif message == 'getitem':\n return getitem_link(contents, value)\n elif message == 'push_first':\n contents = link(value, contents)\n elif message == 'pop_first':\n f = first(contents)\n contents = rest(contents)\n return f\n elif message == 'str':\n return join_link(contents, \", \")\nreturn dispatch\n\n>>> def to_mutable_link(source):\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u4e0e\u539f\u5217\u8868\u76f8\u540c\u5185\u5bb9\u7684\u51fd\u6570\u5217\u8868\"\"\"\ns = mutable_link()\nfor element in reversed(source):\n s('push_first', element)\nreturn s\n\n>>> s = to_mutable_link(suits)\n>>> type(s)\n<class 'function'>\n>>> print(s('str'))\nheart, diamond, spade, club\n
\u5b57\u5178\u5b9e\u73b0:
Python>>> def dictionary():\n\"\"\"\u8fd4\u56de\u4e00\u4e2a\u5b57\u5178\u7684\u51fd\u6570\u5b9e\u73b0\"\"\"\nrecords = []\ndef getitem(key):\n matches = [r for r in records if r[0] == key]\n if len(matches) == 1:\n key, value = matches[0]\n return value\ndef setitem(key, value):\n nonlocal records\n non_matches = [r for r in records if r[0] != key]\n records = non_matches + [[key, value]]\ndef dispatch(message, key=None, value=None):\n if message == 'getitem':\n return getitem(key)\n elif message == 'setitem':\n setitem(key, value)\nreturn dispatch\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#248-dispatch-dictionaries","title":"2.4.8 \u8c03\u5ea6\u5b57\u5178\uff08Dispatch Dictionaries\uff09","text":"\u7528\u5b57\u5178\u5b58\u50a8\u6d88\u606f\u3002
Pythondef account(initial_balance):\n def deposit(amount):\n dispatch['balance'] += amount\n return dispatch['balance']\n def withdraw(amount):\n if amount > dispatch['balance']:\n return 'Insufficient funds'\n dispatch['balance'] -= amount\n return dispatch['balance']\n dispatch = {'deposit': deposit,\n 'withdraw': withdraw,\n 'balance': initial_balance}\n return dispatch\n\ndef withdraw(account, amount):\n return account['withdraw'](amount)\ndef deposit(account, amount):\n return account['deposit'](amount)\ndef check_balance(account):\n return account['balance']\n\na = account(20)\ndeposit(a, 5)\nwithdraw(a, 17)\ncheck_balance(a)\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#249-propagating-constraints","title":"2.4.9 \u7ea6\u675f\u4f20\u9012 (Propagating\u00a0Constraints)","text":"connector Using the Constraint System
Python>>> celsius = connector('Celsius')\n>>> fahrenheit = connector('Fahrenheit')\n>>> def converter(c, f):\n \"\"\"\u7528\u7ea6\u675f\u6761\u4ef6\u8fde\u63a5 c \u5230 f\uff0c\u5c06\u6444\u6c0f\u5ea6\u8f6c\u6362\u4e3a\u534e\u6c0f\u5ea6.\"\"\"\n u, v, w, x, y = [connector() for _ in range(5)]\n multiplier(c, w, u)\n multiplier(v, x, u)\n adder(v, y, f)\n constant(w, 9)\n constant(x, 5)\n constant(y, 32)\n>>> converter(celsius, fahrenheit)\n\n>>> celsius['set_val']('user', 25)\nCelsius = 25\nFahrenheit = 77.0\n\n>>> fahrenheit['set_val']('user', 212)\nContradiction detected: 77.0 vs 212\n\n>>> celsius['forget']('user')\nCelsius is forgotten\nFahrenheit is forgotten\n\n>>> fahrenheit['set_val']('user', 212)\nFahrenheit = 212\nCelsius = 100.0\n\n# Implementing the Constraint System\n>>> connector ['set_val'](source, value) \"\"\"\u8868\u793a\u00a0source\u00a0\u5728\u8bf7\u6c42\u8fde\u63a5\u5668\u5c06\u5f53\u524d\u503c\u8bbe\u4e3a value\"\"\"\n>>> connector ['has_val']()\u00a0 \"\"\"\u8fd4\u56de\u8fde\u63a5\u5668\u662f\u5426\u5df2\u7ecf\u5177\u6709\u503c\"\"\"\n>>> connector ['val'] \"\"\"\u662f\u8fde\u63a5\u5668\u7684\u5f53\u524d\u503c\"\"\"\n>>> connector ['forget'](source)\u00a0 \"\"\"\u544a\u8bc9\u8fde\u63a5\u5668 source \u8bf7\u6c42\u9057\u5fd8\u5b83\u7684\u503c\"\"\"\n>>> connector ['connect'](source)\u00a0 \"\"\"\u544a\u8bc9\u8fde\u63a5\u5668\u53c2\u4e0e\u65b0\u7684\u7ea6\u675f\uff0c\u5373 source\"\"\"\n>>> constraint['new_val']() \"\"\"\u8868\u793a\u4e0e\u7ea6\u675f\u76f8\u8fde\u7684\u67d0\u4e2a\u8fde\u63a5\u5668\u5177\u6709\u65b0\u7684\u503c\u3002\"\"\"\n>>> constraint['forget']()\u00a0 \"\"\"\u8868\u793a\u4e0e\u7ea6\u675f\u76f8\u8fde\u7684\u67d0\u4e2a\u8fde\u63a5\u5668\u9057\u5fd8\u4e86\u503c\u3002\"\"\"\n\n>>> from operator import add, sub\n>>> def adder(a, b, c):\n \"\"\"\u7ea6\u675f a+b=c\"\"\"\n return make_ternary_constraint(a, b, c, add, sub, sub)\n\n>>> def make_ternary_constraint(a, b, c, ab, ca, cb):\n \"\"\"\u7ea6\u675f ab(a,b)=c\uff0cca(c,a)=b\uff0ccb(c,b)=a\"\"\"\n def new_value():\n av, bv, cv = [connector['has_val']() for connector in (a, b, c)]\n if av and bv:\n c['set_val'](constraint, ab(a['val'], b['val']))\n elif av and cv:\n b['set_val'](constraint, ca(c['val'], a['val']))\n elif bv and cv:\n a['set_val'](constraint, cb(c['val'], b['val']))\n def forget_value():\n for connector in (a, b, c):\n connector['forget'](constraint)\n constraint = {'new_val': new_value, 'forget': forget_value}\n for connector in (a, b, c):\n connector['connect'](constraint)\n return constraint\n\n>>> from operator import mul, truediv\n>>> def multiplier(a, b, c):\n \"\"\"\u7ea6\u675f a*b=c\"\"\"\n return make_ternary_constraint(a, b, c, mul, truediv, truediv)\n\n>>> def constant(connector, value):\n \"\"\"\u5e38\u91cf\u8d4b\u503c\"\"\"\n constraint = {}\n connector['set_val'](constraint, value)\n return constraint\n\n# Representing connectors\n>>> def connector(name=None):\n \"\"\"\u9650\u5236\u6761\u4ef6\u4e4b\u95f4\u7684\u8fde\u63a5\u5668\"\"\"\n informant = None\n constraints = []\n def set_value(source, value):\n nonlocal informant\n val = connector['val']\n if val is None:\n informant, connector['val'] = source, value\n if name is not None:\n print(name, '=', value)\n inform_all_except(source, 'new_val', constraints)\n else:\n if val != value:\n print('Contradiction detected:', val, 'vs', value)\n def forget_value(source):\n nonlocal informant\n if informant == source:\n informant, connector['val'] = None, None\n if name is not None:\n print(name, 'is forgotten')\n inform_all_except(source, 'forget', constraints)\n connector = {'val': None,\n 'set_val': set_value,\n 'forget': forget_value,\n 'has_val': lambda: connector['val'] is not None,\n 'connect': lambda source: constraints.append(source)}\n return connector\n\n>>> def inform_all_except(source, message, constraints):\n \"\"\"\u544a\u77e5\u4fe1\u606f\u9664\u4e86 source \u5916\u7684\u6240\u6709\u7ea6\u675f\u6761\u4ef6\"\"\"\n for c in constraints:\n if c != source:\n c[message]()\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#25","title":"2.5 \u9762\u5411\u5bf9\u8c61\u7f16\u7a0b","text":"__init__\u7c7b\u7684\u6784\u9020\u51fd\u6570\uff08constructor\uff09
Python>>> class Account:\n def __init__(self, account_holder):\n self.balance = 0\n self.holder = account_holder\n def deposit(self, amount):\n self.balance = self.balance + amount\n return self.balance\n def withdraw(self, amount):\n if amount > self.balance:\n return 'Insufficient funds'\n self.balance = self.balance - amount\n return self.balance\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#253","title":"2.5.3 \u6d88\u606f\u4f20\u9012\u548c\u70b9\u8868\u8fbe\u5f0f","text":"Python>>> getattr(spock_account, 'balance')\n10\n>>> hasattr(spock_account, 'deposit')\nTrue\n\n\n>>> type(Account.deposit)\n<class 'Function'>\n>>> type(spock_account.deposit)\n<class 'method'>\n# \u4e3a\u7c7b\u7684\u5c5e\u6027\uff0c\u65b9\u6cd5\u53ea\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u4f46\u4f5c\u4e3a\u5b9e\u4f8b\u7684\u5c5e\u6027\uff0c\u5b83\u662f\u4e00\u4e2a\u7ed1\u5b9a\u65b9\u6cd5\n\n>>> Account.deposit(spock_account, 1001) # \u51fd\u6570 deposit \u63a5\u53d7\u4e24\u4e2a\u53c2\u6570\n1011\n>>> spock_account.deposit(1000) # \u65b9\u6cd5 deposit \u63a5\u53d7\u4e00\u4e2a\u53c2\u6570\n2011\n
\u547d\u540d\u7ea6\u5b9a\uff1a\u7c7b\u540d\u901a\u5e38\u4f7f\u7528 CapWords \u7ea6\u5b9a\uff08\u4e5f\u79f0\u4e3a CamelCase\uff0c\u56e0\u4e3a\u540d\u79f0\u4e2d\u95f4\u7684\u5927\u5199\u5b57\u6bcd\u770b\u8d77\u6765\u50cf\u9a7c\u5cf0\uff09\u7f16\u5199\u3002\u65b9\u6cd5\u540d\u79f0\u9075\u5faa\u4f7f\u7528\u4e0b\u5212\u7ebf\u5206\u9694\u7684\u5c0f\u5199\u5355\u8bcd\u547d\u540d\u51fd\u6570\u7684\u6807\u51c6\u7ea6\u5b9a\u3002
\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u6709\u4e00\u4e9b\u5b9e\u4f8b\u53d8\u91cf\u548c\u65b9\u6cd5\u4e0e\u5bf9\u8c61\u7684\u7ef4\u62a4\u548c\u4e00\u81f4\u6027\u76f8\u5173\uff0c\u6211\u4eec\u4e0d\u5e0c\u671b\u5bf9\u8c61\u7684\u7528\u6237\u770b\u5230\u6216\u4f7f\u7528\u3002\u5b83\u4eec\u4e0d\u662f\u7c7b\u5b9a\u4e49\u7684\u62bd\u8c61\u7684\u4e00\u90e8\u5206\uff0c\u800c\u662f\u5b9e\u73b0\u7684\u4e00\u90e8\u5206\u3002Python \u7684\u7ea6\u5b9a\u89c4\u5b9a\uff0c\u5982\u679c\u5c5e\u6027\u540d\u79f0\u4ee5\u4e0b\u5212\u7ebf\u5f00\u5934\uff0c\u5219\u53ea\u80fd\u5728\u7c7b\u672c\u8eab\u7684\u65b9\u6cd5\u4e2d\u8bbf\u95ee\u5b83\uff0c\u800c\u4e0d\u662f\u7528\u6237\u8bbf\u95ee\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#254","title":"2.5.4 \u7c7b\u5c5e\u6027","text":"\u611f\u89c9\u6ca1\u4ec0\u4e48\u7528:
Python>>> Account.interest = 0.05 # \u6539\u53d8\u7c7b\u5c5e\u6027\n>>> spock_account.interest # \u5b9e\u4f8b\u5c5e\u6027\u53d1\u751f\u53d8\u5316\uff08\u8be5\u5b9e\u4f8b\u4e2d\u6ca1\u6709\u548c\u7c7b\u5c5e\u6027\u540c\u540d\u79f0\u7684\u5b9e\u4f8b\u5c5e\u6027\uff09\n0.05\n>>> kirk_account.interest # \u5982\u679c\u5b9e\u4f8b\u4e2d\u5b58\u5728\u548c\u7c7b\u5c5e\u6027\u540c\u540d\u7684\u5b9e\u4f8b\u5c5e\u6027\uff0c\u5219\u6539\u53d8\u7c7b\u5c5e\u6027\uff0c\u4e0d\u4f1a\u5f71\u54cd\u5b9e\u4f8b\u5c5e\u6027\n0.08\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#255","title":"2.5.5 \u7ee7\u627f","text":">>> class Account:\n \"\"\"\u4e00\u4e2a\u4f59\u989d\u975e\u96f6\u7684\u8d26\u6237\u3002\"\"\"\n interest = 0.02\n def __init__(self, account_holder):\n self.balance = 0\n self.holder = account_holder\n def deposit(self, amount):\n \"\"\"\u5b58\u5165\u8d26\u6237 amount\uff0c\u5e76\u8fd4\u56de\u53d8\u5316\u540e\u7684\u4f59\u989d\"\"\"\n self.balance = self.balance + amount\n return self.balance\n def withdraw(self, amount):\n \"\"\"\u4ece\u8d26\u53f7\u4e2d\u53d6\u51fa amount\uff0c\u5e76\u8fd4\u56de\u53d8\u5316\u540e\u7684\u4f59\u989d\"\"\"\n if amount > self.balance:\n return 'Insufficient funds'\n self.balance = self.balance - amount\n return self.balance\n\n>>> class CheckingAccount(Account):\n \"\"\"\u4ece\u8d26\u53f7\u53d6\u94b1\u4f1a\u6263\u51fa\u624b\u7eed\u8d39\u7684\u8d26\u53f7\"\"\"\n withdraw_charge = 1\n interest = 0.01\n def withdraw(self, amount):\n return Account.withdraw(self, amount + self.withdraw_charge)\n
\u63a5\u53e3
Python>>> def deposit_all(winners, amount=5):\n for account in winners:\n account.deposit(amount) # \u8fd9\u91cc\u8c03\u7528\u7684\u662f\u5b9e\u4f8b account \u7684 deposit \u65b9\u6cd5\n # \u5bf9\u4e8e\u4e0d\u540c\u5b9e\u4f8b\u6765\u8bf4\uff0c\u5b83\u4eec\u7684 deposit \u65b9\u6cd5\u53ef\u80fd\u4e0d\u540c\u3002\u8fd9\u4e2a\u4f8b\u5b50\u76f8\u5bf9\u4e8e\u4e0b\u9762\u6765\u8bb2\uff0c\u66f4\u52a0\u5177\u6709\u5065\u58ee\u6027\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#257","title":"2.5.7 \u591a\u7ee7\u627f","text":"\u7ee7\u627f\u6392\u5e8f\u95ee\u9898\u6ca1\u6709\u6b63\u786e\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u56e0\u4e3a\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u80fd\u66f4\u613f\u610f\u5c06\u67d0\u4e9b\u7ee7\u627f\u7c7b\u7f6e\u4e8e\u5176\u4ed6\u7c7b\u4e4b\u4e0a\u3002\u4f46\u662f\uff0c\u4efb\u4f55\u652f\u6301\u591a\u91cd\u7ee7\u627f\u7684\u7f16\u7a0b\u8bed\u8a00\u90fd\u5fc5\u987b\u4ee5\u4e00\u81f4\u7684\u65b9\u5f0f\u9009\u62e9\u67d0\u4e9b\u6392\u5e8f\uff0c\u4ee5\u4fbf\u8be5\u8bed\u8a00\u7684\u7528\u6237\u53ef\u4ee5\u9884\u6d4b\u5176\u7a0b\u5e8f\u7684\u884c\u4e3a\u3002
\u8fdb\u4e00\u6b65\u9605\u8bfb\u3002Python \u4f7f\u7528\u79f0\u4e3a C3 \u65b9\u6cd5\u89e3\u6790\u6392\u5e8f\u7684\u9012\u5f52\u7b97\u6cd5\u89e3\u6790\u6b64\u540d\u79f0\u3002\u53ef\u4ee5\u5728\u6240\u6709\u7c7b\u4e0a\u4f7f\u7528\u00a0mro
\u00a0\u65b9\u6cd5\u67e5\u8be2\u4efb\u4f55\u7c7b\u7684\u65b9\u6cd5\u89e3\u6790\u987a\u5e8f\u3002
>>> [c.__name__ for c in AsSeenOnTVAccount.mro()]\n['AsSeenOnTVAccount', 'CheckingAccount', 'SavingsAccount', 'Account', 'object']\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#258","title":"2.5.8 \u5bf9\u8c61\u7684\u4f5c\u7528","text":"\u53e6\u4e00\u65b9\u9762\uff0c\u7c7b\u53ef\u80fd\u4e0d\u662f\u5b9e\u73b0\u67d0\u4e9b\u62bd\u8c61\u7684\u6700\u4f73\u673a\u5236\u3002\u51fd\u6570\u5f0f\u62bd\u8c61\u63d0\u4f9b\u4e86\u4e00\u4e2a\u66f4\u81ea\u7136\u7684\u9690\u55bb\u6765\u8868\u793a\u8f93\u5165\u548c\u8f93\u51fa\u4e4b\u95f4\u7684\u5173\u7cfb\u3002\u6211\u4eec\u4e0d\u5e94\u8be5\u89c9\u5f97\u5fc5\u987b\u5c06\u7a0b\u5e8f\u4e2d\u7684\u6bcf\u4e00\u70b9\u903b\u8f91\u90fd\u585e\u8fdb\u4e00\u4e2a\u7c7b\u4e2d\uff0c\u5c24\u5176\u662f\u5728\u5b9a\u4e49\u72ec\u7acb\u51fd\u6570\u6765\u64cd\u4f5c\u6570\u636e\u66f4\u81ea\u7136\u7684\u60c5\u51b5\u4e0b\u3002\u51fd\u6570\u8fd8\u53ef\u4ee5\u5f3a\u5236\u5b9e\u73b0\u5173\u6ce8\u70b9\u7684\u5206\u79bb\u3002\u6362\u53e5\u8bdd\u8bf4\uff0c\u51fd\u6570\u5f0f\u7f16\u7a0b\u63d0\u4f9b\u4e86\u53e6\u4e00\u79cd\u6709\u6548\u5730\u7ec4\u7ec7\u7a0b\u5e8f\u903b\u8f91\u7684\u65b9\u6cd5\uff0c\u4f7f\u5f97\u7a0b\u5e8f\u5458\u80fd\u591f\u66f4\u597d\u5730\u5904\u7406\u548c\u7ef4\u62a4\u7a0b\u5e8f\u3002\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u4f7f\u7528\u51fd\u6570\u5f0f\u7f16\u7a0b\u65b9\u6cd5\u53ef\u80fd\u6bd4\u4f7f\u7528\u9762\u5411\u5bf9\u8c61\u7f16\u7a0b\u66f4\u81ea\u7136\u548c\u6709\u6548\u3002
"},{"location":"CS_Basic/CS61A/Composing_Programs/#26","title":"2.6 \u5b9e\u73b0\u7c7b\u548c\u5bf9\u8c61","text":"object-oriented programming paradigm \u5373\u4f7f\u5728\u6ca1\u6709\u5185\u7f6e\u5bf9\u8c61\u7cfb\u7edf\u7684\u7f16\u7a0b\u8bed\u8a00\u4e2d\uff0c\u7a0b\u5e8f\u4e5f\u53ef\u4ee5\u662f\u9762\u5411\u5bf9\u8c61\u7684\u3002 \u653e\u5f03\u70b9\u8868\u793a\u6cd5->\u8c03\u5ea6\u5b57\u5178\u5b9e\u73b0\u6d88\u606f\u4f20\u9012
"},{"location":"CS_Basic/CS61A/Composing_Programs/#261","title":"2.6.1 \u5b9e\u4f8b","text":"Python>>> def make_instance(cls):\n \"\"\"Return a new object instance, which is a dispatch dictionary.\"\"\"\n def get_value(name):\n if name in attributes:\n return attributes[name]\n else:\n value = cls['get'](name)\n return bind_method(value, instance)\n def set_value(name, value):\n attributes[name] = value\n attributes = {}\n instance = {'get': get_value, 'set': set_value}\n return instance\n\n>>> def bind_method(value, instance):\n \"\"\"Return a bound method if value is callable, or value otherwise.\"\"\"\n if callable(value):\n def method(*args):\n return value(instance, *args)\n return method\n else:\n return value\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#262","title":"2.6.2 \u7c7b","text":"Python>>> def make_class(attributes, base_class=None):\n \"\"\"Return a new class, which is a dispatch dictionary.\"\"\"\n def get_value(name):\n if name in attributes:\n return attributes[name]\n elif base_class is not None:\n return base_class['get'](name)\n def set_value(name, value):\n attributes[name] = value\n def new(*args):\n return init_instance(cls, *args)\n cls = {'get': get_value, 'set': set_value, 'new': new}\n return cls\n\n>>> def init_instance(cls, *args):\n \"\"\"Return a new object with type cls, initialized with args.\"\"\"\n instance = make_instance(cls)\n init = cls['get']('__init__')\n if init:\n init(instance, *args)\n return instance\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#3","title":"3 \u8ba1\u7b97\u673a\u7a0b\u5e8f\u7684\u89e3\u91ca","text":""},{"location":"CS_Basic/CS61A/Composing_Programs/#31","title":"3.1 \u5f15\u8a00","text":"\u8bb8\u591a\u89e3\u91ca\u5668\u90fd\u6709\u4e00\u4e2a\u4f18\u96c5\u7684\u7ed3\u6784\uff0c\u5373\u4e24\u4e2a\u4e92\u9012\u5f52\u51fd\u6570\uff1a
(if <predicate> <consequent> <alternative>)\n\n(define pi 3.14)\n(* pi 3.14)\n\n(define (<name> <formal parameters>) <body>)\neg1:\n (define (average x y)\n (/ (+ x y) 2))\neg2:\n (define (abs x)\n (if (< x 0)\n (- x)\n x))\neg3:\n (define (sqrt x)\n (define (good-enough? guess)\n (< (abs (- (square guess) x)) 0.001))\n (define (improve guess)\n (average guess (/ x guess)))\n (define (sqrt-iter guess)\n (if (good-enough? guess)\n guess\n (sqrt-iter (improve guess))))\n (sqrt-iter 1.0))\n (sqrt 9)\n\n(lambda (<formal-parameters>) <body>)\neg1:\n (define (plus4 x) (+ x 4))\n (define plus4 (lambda (x) (+ x 4))) # both are OK\n\n# \u7279\u6b8a\u7684\u503c\u00a0nil\u00a0\u6216\u00a0'()\u00a0\u8868\u793a\u7a7a\u5217\u8868\n\n# null? \u8c13\u8bcd\u7684\u4f7f\u7528:\n (define (length items)\n (if (null? items)\n 0\n (+ 1 (length (cdr items)))))\n (define (getitem items n)\n (if (= n 0)\n (car items)\n (getitem (cdr items) (- n 1))))\n (define squares (list 1 4 9 16 25))\n\n (length squares)\n\n (getitem squares 3)\n\n# \u4efb\u4f55\u4e0d\u88ab\u6c42\u503c\u7684\u8868\u8fbe\u5f0f\u90fd\u88ab\u79f0\u4e3a\u88ab\u5f15\u7528\n (list 'define 'list)\n\n# turtle\u4f7f\u7528+\u9012\u5f52\u753b\u56fe\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#33","title":"3.3 \u5f02\u5e38","text":">>> raise Exception(' An error occurred')\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nException: an error occurred\n
try\n <try suite>\nexcept <exception class> as <name>:\n <except suite>\n
\u5f02\u5e38\u662f\u4e2a\u7c7b\uff0c\u53ef\u4ee5\u6709\u989d\u5916\u7684\u5c5e\u6027\uff0c\u53ef\u4ee5\u907f\u514d\u62a5\u9519\uff0c\u8ba9\u7a0b\u5e8f\u7ed9\u51fa\u4e00\u4e2a\u8f83\u4e3a\u7c97\u7cd9\u7684\u503c\uff1a
Python>>> class IterImproveError(Exception):\n\u00a0\u00a0\u00a0 def __init__(self, last_guess):\n\u00a0\u00a0\u00a0 self.last_guess = last_guess\n>>> def improve(update, done, guess=1, max_updates=1000):\n\u00a0\u00a0\u00a0 k = 0\n\u00a0\u00a0\u00a0 try:\n\u00a0\u00a0\u00a0 while not done(guess) and k < max_updates:\n\u00a0\u00a0\u00a0 guess = update(guess)\n\u00a0\u00a0\u00a0 k = k + 1\n\u00a0\u00a0\u00a0 return guess\n\u00a0\u00a0\u00a0 except ValueError:\n\u00a0\u00a0\u00a0 raise IterImproveError(guess)\n>>> def find_zero(f, guess=1):\n\u00a0\u00a0\u00a0 def done(x):\n\u00a0\u00a0\u00a0 return f(x) == 0\n\u00a0\u00a0\u00a0 try:\n\u00a0\u00a0\u00a0 return improve(newton_update(f), done, guess)\n\u00a0\u00a0\u00a0 except IterImproveError as e:\n\u00a0\u00a0\u00a0 return e.last_guess\n>>> from math import sqrt\n>>> find_zero(lambda x: 2*x*x + sqrt(x))\n-0.030211203830201594\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#34","title":"3.4 \u7ec4\u5408\u8bed\u8a00\u7684\u89e3\u91ca\u5668","text":"\u4e24\u4e2a\u7ec4\u4ef6:
>>> next(iterator)\n7\n>>> next(iterator)\nTraceback (most recent call las):\n File \"<stdin>\", line 1, in <module>\nStopIteration\n\n>>> try:\n next(iterator)\n except StopIteration:\n print('No more values')\nNo more values\n
"},{"location":"CS_Basic/CS61A/Composing_Programs/#422","title":"4.2.2 \u53ef\u8fed\u4ee3\u6027","text":"iterable value \u53ef\u8fed\u4ee3\u5bf9\u8c61:
\u7ea6 2978 \u4e2a\u5b57 13 \u884c\u4ee3\u7801 4 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 15 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#1","title":"1 \u8ba1\u7b97\u673a\u62bd\u8c61\u53ca\u76f8\u5173\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2","title":"2 \u6307\u4ee4: \u8ba1\u7b97\u673a\u7684\u8bed\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#21","title":"2.1 \u5f15\u8a00","text":"\u8bbe\u8ba1\u539f\u5219:
Java \u7f16\u8bd1\u5668: Just In Time \u7f16\u8bd1\u5668
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#23","title":"2.3 \u8ba1\u7b97\u673a\u786c\u4ef6\u7684\u64cd\u4f5c\u6570","text":"\u5728\u5185\u5b58\u548c\u5bc4\u5b58\u5668\u4e4b\u95f4\u4f20\u8f93\u6307\u4ee4:\u6570\u636e\u4f20\u8f93\u6307\u4ee4 \u6307\u4ee4\u63d0\u4f9b\u5185\u5b58\u5730\u5740 \u8f7d\u5165\u6307\u4ee4\uff08load\uff09:ld
Text OnlyLd x9, 8(x22)\n
X 22 \u57fa\u5740\u5bc4\u5b58\u5668 8 \u504f\u79fb\u91cf \u5b57\u8282\u5730\u5740: 0 8 16 24 RICS- V \u662f\u5c0f\u7aef\u7f16\u5740: \u53ea\u5728\u4ee5\u53cc\u5b57\u5f62\u5f0f\u548c\u516b\u4e2a\u5355\u72ec\u5b57\u8282\u8bbf\u95ee\u76f8\u540c\u6570\u636e\u65f6\u4f1a\u6709\u5f71\u54cd ^da8be4
\u5b58\u50a8\u6307\u4ee4\uff08store\uff09\u5b58\u50a8\u53cc\u5b57
Text Onlysd x9, 96(x22)\n
ld x9, AddConstant4(x3)\nAdd x22, x22, x9\n\n# Equals to \n\naddi x22, x22, 4 # x22 = x22 + 4\n
\u5e38\u6570\u79f0\u4e3a\u7b97\u6570\u6307\u4ee4\u64cd\u4f5c\u6570 X0 \u53ef\u4ee5\u7528\u6765\u8868\u793a 0 \u5176\u5b9e\u8fd8\u6709 RV 32 \u57fa\u5740\u5bc4\u5b58\u5668\u4e5f\u88ab\u79f0\u4e3a\u4e0b\u6807\u5bc4\u5b58\u5668 \u6211\u4eec\u5047\u8bbe\u6307\u4ee4\u90fd\u662f 64 \u4f4d
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#24","title":"2.4 \u6709\u7b26\u53f7\u6570\u4e0e\u65e0\u7b26\u53f7\u6570","text":"while (save[i] == k) \n i += 1;\n
I -> x 22 K -> x 24 Save -> x 25
Text Onlyloop: slli, x10, x22, 3\nAdd x10, x10, x25\nLd x9, 0(x10)\nBen x9, x24, Exit\nAddi x22, x22, l\nBeq x0, x0, loop\nExit:\n
\u57fa\u672c\u5757:
\u5c06\u7b26\u53f7\u6570\u5f53\u4f5c\u65e0\u7b26\u53f7\u6570\u5904\u7406
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#273-caseswitch","title":"2.7.3 Case/switch \u8bed\u53e5","text":"Jal x1, ProcedureAddress\nJalr x0, 0(x1)\n
\u8c03\u7528\u8005\u5c06\u53c2\u6570\u503c\u653e\u5165 x 10~x 17 \u8fc7\u7a0b\u662f\u88ab\u8c03\u7528\u8005 Program counter:PC \u6307\u4ee4\u5730\u5740\u5bc4\u5b58\u5668
Text Onlyjal x0, Label // unconditionally branch to Label\n
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#281","title":"2.8.1 \u4f7f\u7528\u66f4\u591a\u7684\u5bc4\u5b58\u5668","text":"leaf_example:\nAddi sp, sp, -14\nSd x5, 16(sp)\nSd x6, 8(sp)\nSd x20, 0(sp)\nAdd x5, x10, x11\nAdd x6, x12, x13\nSub x20, x5, x6\nAddi x10, x20, 0\nLd x20, 0(sp)\nLd x6, 8(sp)\nLd x5, 16(sp)\nAddi sp, sp, 24\nJalr x0, 0(x1)\n
long long int fact (long long int n) {\n if (n < 1) return (1);\n else return (n * fact(n - 1))\n}\n
n -> x 10
Text Onlyfact:\n addi sp, sp, -16\n Sd x1, 8(sp)\n Sd x10, 0(sp)\n\n Addi x5, x10, -1\n Bge x5, x0, L1\n\n Addi x10, x0, 1\n Addi sp, sp, 16\n Jalr x0, 0(x1)\n\nL1: addi x10, x10, -1\n Jal x1, fact\n\naddi x6, x10, 0\nLd x10, 0(sp)\nLd x1, 8(sp)\nAddi sp, sp, 16\nMul x10, x10, x6\nJalr x0, 0(x1)\n
\u6808\u4e5f\u7528\u4e8e\u5b58\u50a8\u8fc7\u7a0b\u7684\u5c40\u90e8\u53d8\u91cf \u8fc7\u7a0b\u5e27/\u6d3b\u52a8\u8bb0\u5f55
\u6ca1\u770b\u61c2
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#284","title":"2.8.4 \u5728\u5806\u4e2d\u4e3a\u65b0\u6570\u636e\u5206\u914d\u7a7a\u95f4","text":"Static data segment text segment \u50cf\u94fe\u8868\u7b49\u6570\u636e\u7ed3\u6784\u5f80\u5f80\u4f1a\u968f\u751f\u547d\u5468\u671f\u589e\u957f\u548c\u7f29\u77ed\uff0c\u6240\u4ee5\u4f1a\u628a\u4ed6\u4eec\u5b58\u5728\u5806\u91cc (heap)
ASCII: american standard code for information interchange
\u52a0\u8f7d\u65e0\u7b26\u53f7\u5b57\u8282 (lbu) \u5b58\u50a8\u5b57\u8282 (sb)
Text Onlylbu x12, 0(x10)\nsb x12, 0(x11)\n
\u5b57\u7b26\u4e32\u7684\u8868\u793a\u6709\u4e09\u79cd\u9009\u62e9:
void strcpy (char x[], char y[])\n{\n size_t i;\n i = 0;\n while ((x[i] = y[i]) != '\\0')\n i += 1;\n}\n
x -> x 10 y -> x 11 i -> x 19
Text Onlystrcpy:\n addi sp, sp, -8\n sd x19, 0(sp)\n add x19, x0, x0\nL1: add x5, x19, x11\n lbu x6, 0(x5)\n add x7, x19, x10\n sb x6, 0(x7)\n beq x6, x0, L2\n addi x19, x19, 1\n jal x0, L1\nL2: ld x19, 0(sp)\n addi sp, sp, 8\n jalr x0, 0(x1)\n
load half unsigned \u52a0\u8f7d\u534a\u5b57: lh lhu sh
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#210-risc-v","title":"2.10 \u5bf9\u5927\u7acb\u5373\u6570\u7684 RISC-V \u7684\u7f16\u5740\u548c\u5bfb\u5740","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2101","title":"2.10.1 \u5927\u7acb\u5373\u6570","text":"load upper immediate \u53d6\u7acb\u5373\u6570\u9ad8\u4f4d lui lui \u53ef\u4ee5\u52a0\u8f7d 12~31 \u4f4d addi \u53ef\u4ee5\u52a0\u8f7d 0~11 \u4f4d
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2102","title":"2.10.2 \u5206\u652f\u4e2d\u7684\u5bfb\u5740","text":"\u5206\u652f\u6307\u4ee4\u4f7f\u7528 SB \u578b\u7684\u6307\u4ee4\u683c\u5f0f
"},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#211","title":"2.11 \u6307\u4ee4\u4e0e\u5e76\u884c\u6027\uff1a\u540c\u6b65","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#212","title":"2.12 \u7ffb\u8bd1\u5e76\u542f\u52a8\u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2121","title":"2.12.1 \u7f16\u8bd1\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2122","title":"2.12.2 \u6c47\u7f16\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2123","title":"2.12.3 \u94fe\u63a5\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2124","title":"2.12.4 \u52a0\u8f7d\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2125","title":"2.12.5 \u52a8\u6001\u94fe\u63a5\u5e93","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#21251-java","title":"2.12.5.1 \u542f\u52a8 Java \u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#213-c","title":"2.13 \u4ee5 C \u6392\u5e8f\u7a0b\u5e8f\u4e3a\u4f8b\u7684\u6c47\u603b\u6574\u7406","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2131-swap","title":"2.13.1 swap \u8fc7\u7a0b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2132-sort","title":"2.13.2 sort \u8fc7\u7a0b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#214","title":"2.14 \u6570\u7ec4\u4e0e\u6307\u9488","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2141-clear","title":"2.14.1 \u7528\u6570\u7ec4\u5b9e\u73b0 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2142-clear","title":"2.14.2 \u7528\u6307\u9488\u5b9e\u73b0 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2143-clear","title":"2.14.3 \u6bd4\u8f83\u4e24\u4e2a\u7248\u672c\u7684 clear","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#215-c-java","title":"2.15 \u9ad8\u7ea7\u4e13\u9898: \u7f16\u8bd1 C \u8bed\u8a00\u548c\u89e3\u91ca Java \u7a0b\u5e8f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#216-mips","title":"2.16 \u5b9e\u4f8b: MIPS \u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#217-x-86","title":"2.17 \u5b9e\u4f8b: x 86 \u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2171-intel-x-86","title":"2.17.1 Intel x 86 \u7684\u6f14\u53d8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2172-x-86","title":"2.17.2 x 86 \u5bc4\u5b58\u5668\u548c\u5bfb\u5740\u6a21\u5f0f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2173-x-86","title":"2.17.3 x 86 \u6574\u6570\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2174-x-86","title":"2.17.4 x 86 \u6307\u4ee4\u7f16\u7801","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#2175-x-86","title":"2.17.5 x 86 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#218-risc-v","title":"2.18 \u5b9e\u4f8b: RISC-V \u6307\u4ee4\u7cfb\u7edf\u7684\u5269\u4f59\u90e8\u5206","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#219","title":"2.19 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#220","title":"2.20 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#3","title":"3 \u8ba1\u7b97\u673a\u7684\u7b97\u6570\u8fd0\u7b97","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#31","title":"3.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#32","title":"3.2 \u52a0\u6cd5\u548c\u51cf\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#33","title":"3.3 \u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#331","title":"3.3.1 \u4e32\u884c\u7248\u7684\u4e58\u6cd5\u7b97\u6cd5\u53ca\u5176\u786c\u4ef6\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#332","title":"3.3.2 \u5e26\u7b26\u53f7\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#333","title":"3.3.3 \u5feb\u901f\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#334-risc-v","title":"3.3.4 RISC-V \u4e2d\u7684\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#335","title":"3.3.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#34","title":"3.4 \u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#341","title":"3.4.1 \u9664\u6cd5\u7b97\u6cd5\u53ca\u786c\u4ef6\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#342","title":"3.4.2 \u6709\u7b26\u53f7\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#343","title":"3.4.3 \u5feb\u901f\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#344-risc-v","title":"3.4.4 RISC-V \u4e2d\u7684\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#345","title":"3.4.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#35","title":"3.5 \u6d6e\u70b9\u8fd0\u7b97","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#351","title":"3.5.1 \u6d6e\u70b9\u8868\u793a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#352","title":"3.5.2 \u4f8b\u5916\u548c\u4e2d\u65ad","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#353-ieee-754","title":"3.5.3 IEEE 754 \u6d6e\u70b9\u6570\u6807\u51c6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#354","title":"3.5.4 \u6d6e\u70b9\u52a0\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#355","title":"3.5.5 \u6d6e\u70b9\u9664\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#356-risc-v","title":"3.5.6 RISC-V \u4e2d\u7684\u6d6e\u70b9\u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#357","title":"3.5.7 \u7cbe\u786e\u7b97\u6570","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#358","title":"3.5.8 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#36","title":"3.6 \u5e76\u884c\u6027\u4e0e\u8ba1\u7b97\u673a\u7b97\u6570: \u5b50\u5b57\u5e76\u884c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#37-x-86-simd","title":"3.7 \u5b9e\u4f8b: x 86 \u4e2d\u7684 SIMD \u6269\u5c55\u548c\u9ad8\u7ea7\u5411\u91cf\u6269\u5c55","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#38","title":"3.8 \u52a0\u901f: \u5b50\u5b57\u5e76\u884c\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#39","title":"3.9 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#310","title":"3.10 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4","title":"4 \u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#41","title":"4.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#411-risc-v","title":"4.1.1 \u4e00\u79cd\u57fa\u672c\u7684 RISC-V \u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#412","title":"4.1.2 \u5b9e\u73b0\u6982\u8ff0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#42","title":"4.2 \u903b\u8f91\u8bbe\u8ba1\u7684\u4e00\u822c\u65b9\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#43","title":"4.3 \u5efa\u7acb\u6570\u636e\u901a\u8def","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#44","title":"4.4 \u4e00\u4e2a\u7b80\u5355\u7684\u5b9e\u73b0\u65b9\u6848","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#441-alu","title":"4.4.1 ALU\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#442","title":"4.4.2 \u8bbe\u8ba1\u4e3b\u63a7\u5236\u5355\u5143","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#443","title":"4.4.3 \u6570\u636e\u901a\u8def\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#444","title":"4.4.4 \u63a7\u5236\u7684\u7ed3\u675f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#445","title":"4.4.5 \u4e3a\u4ec0\u4e48\u73b0\u5728\u4e0d\u9002\u7528\u5355\u5468\u671f\u5b9e\u73b0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#45","title":"4.5 \u6d41\u6c34\u7ebf\u6982\u8ff0","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#451","title":"4.5.1 \u9762\u5411\u6d41\u6c34\u7ebf\u7684\u6307\u4ee4\u7cfb\u7edf\u8bbe\u8ba1","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#452","title":"4.5.2 \u6d41\u6c34\u4e0b\u5192\u9669","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#453","title":"4.5.3 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#46","title":"4.6 \u6d41\u6c34\u7ebf\u6570\u636e\u901a\u8def\u548c\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#461","title":"4.6.1 \u6d41\u6c34\u7ebf\u7684\u56fe\u5f62\u5316\u8868\u793a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#462","title":"4.6.2 \u6d41\u6c34\u7ebf\u63a7\u5236","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#47","title":"4.7 \u6570\u636e\u5192\u9669: \u524d\u9012\u4e0e\u505c\u987f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#48","title":"4.8 \u63a7\u5236\u5192\u9669","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#481","title":"4.8.1 \u5047\u8bbe\u5206\u652f\u4e0d\u53d1\u751f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#482","title":"4.8.2 \u7f29\u77ed\u5206\u652f\u5ef6\u8fdf","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#483","title":"4.8.3 \u52a8\u6001\u5206\u652f\u9884\u6d4b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#484","title":"4.8.4 \u6d41\u6c34\u7ebf\u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#49","title":"4.9 \u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#491-risc-v","title":"4.9.1 RISC-V \u4f53\u7cfb\u7ed3\u6784\u4e2d\u5982\u4f55\u5904\u7406\u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#492","title":"4.9.2 \u6d41\u6c34\u7ebf\u5b9e\u73b0\u4e2d\u7684\u4f8b\u5916","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#410","title":"4.10 \u6307\u4ee4\u95f4\u7684\u5e76\u884c\u6027","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4101","title":"4.10.1 \u63a8\u6d4b\u7684\u6982\u5ff5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4102","title":"4.10.2 \u9759\u6001\u591a\u53d1\u5c04","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4103","title":"4.10.3 \u52a8\u6001\u591a\u53d1\u5c04\u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4104","title":"4.10.4 \u9ad8\u7ea7\u6d41\u6c34\u7ebf\u548c\u80fd\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#411-armcortex-a-53-intel-core-i-7","title":"4.11 \u5b9e\u4f8b: armCortex-A 53 \u548c Intel Core i 7 \u6d41\u6c34\u7ebf\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4111-arm-cortex-a-53","title":"4.11.1 ARM Cortex-A 53","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4112-intel-core-i-7-920","title":"4.11.2 Intel Core i 7 920","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#4113-intel-core-i-7","title":"4.11.3 Intel Core i 7 \u5904\u7406\u5668\u7684\u6027\u80fd","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#412_1","title":"4.12 \u52a0\u901f: \u6307\u4ee4\u96c6\u5e76\u884c\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#413","title":"4.13 \u9ad8\u7ea7\u4e13\u9898: \u6570\u5b57\u8bbe\u8ba1\u6982\u8ff0\u2014\u2014\u4f7f\u7528\u786c\u4ef6\u8bbe\u8ba1\u8bed\u8a00\u8fdb\u884c\u6d41\u6c34\u7ebf\u5efa\u6a21\u4ee5\u53ca\u66f4\u591a\u6d41\u6c34\u7ebf\u793a\u4f8b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#414","title":"4.14 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#415","title":"4.15 \u672c\u7ae0\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#416","title":"4.16 \u5386\u53f2\u89c6\u89d2\u548c\u6269\u5c55\u9605\u8bfb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5","title":"5 \u5927\u800c\u5feb: \u5c42\u6b21\u5316\u5b58\u50a8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#51","title":"5.1 \u5f15\u8a00","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#52","title":"5.2 \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#521-sram","title":"5.2.1 SRAM \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#522-dram","title":"5.2.2 DRAM \u5b58\u50a8\u6280\u672f","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#523","title":"5.2.3 \u95ea\u5b58","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#524","title":"5.2.4 \u78c1\u76d8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#53-cache","title":"5.3 cache \u57fa\u7840","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#531-cache","title":"5.3.1 cache \u8bbf\u95ee","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#532-cache","title":"5.3.2 \u5904\u7406 cache \u5931\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#533","title":"5.3.3 \u5904\u7406\u5199\u64cd\u4f5c","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#534-cache-intrinsity-fastmath","title":"5.3.4 cache \u5b9e\u4f8b: Intrinsity FastMATH \u5904\u7406\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#535","title":"5.3.5 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#54-cache","title":"5.4 cache \u7684\u6027\u80fd\u8bc4\u4f30\u548c\u6539\u8fdb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#541-cache","title":"5.4.1 \u4f7f\u7528\u66f4\u4e3a\u7075\u6d3b\u7684\u66ff\u6362\u7b56\u7565\u964d\u4f4e cache \u5931\u6548\u7387","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#542-cache","title":"5.4.2 \u5728 cache \u4e2d\u67e5\u627e\u6570\u636e\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#543","title":"5.4.3 \u9009\u62e9\u66ff\u6362\u7684\u6570\u636e\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#544-cache","title":"5.4.4 \u4f7f\u7528\u591a\u7ea7 cache \u51cf\u5c11\u5931\u6548\u4ee3\u4ef7","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#545","title":"5.4.5 \u901a\u8fc7\u5206\u5757\u8fdb\u884c\u8f6f\u4ef6\u4f18\u5316","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#546","title":"5.4.6 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#55","title":"5.5 \u53ef\u9760\u7684\u5b58\u50a8\u5668\u66fe\u6d4b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#551","title":"5.5.1 \u5931\u6548\u7684\u5b9a\u4e49","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#552-1-2","title":"5.5.2 \u7ea0\u6b63 1 \u4f4d\u9519\u3001\u68c0\u6d4b 2 \u4f4d\u9519\u7684\u6c49\u660e\u7f16\u7801","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#56","title":"5.6 \u865a\u62df\u673a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#561","title":"5.6.1 \u865a\u62df\u673a\u76d1\u89c6\u5668\u7684\u5fc5\u5907\u6761\u4ef6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#562","title":"5.6.2 \u6307\u4ee4\u7cfb\u7edf\u4f53\u7cfb\u7ed3\u6784\uff08\u7f3a\u4e4f\uff09\u5bf9\u865a\u62df\u673a\u7684\u652f\u6301\u3001","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#563","title":"5.6.3 \u4fdd\u62a4\u548c\u6307\u4ee4\u7cfb\u7edf\u4f53\u7cfb\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#57","title":"5.7 \u865a\u62df\u5185\u5b58","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#571","title":"5.7.1 \u9875\u7684\u5b58\u653e\u548c\u67e5\u627e","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#572","title":"5.7.2 \u7f3a\u9875\u5931\u6548","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#573","title":"5.7.3 \u652f\u6301\u5927\u865a\u62df\u5730\u5740\u7a7a\u95f4\u7684\u865a\u62df\u5b58\u50a8","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#574","title":"5.7.4 \u5173\u4e8e\u5199","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#575-tlb","title":"5.7.5 \u52a0\u5feb\u5730\u5740\u8f6c\u6362:TLB","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#576-intrinsity-fastmath-tlb","title":"5.7.6 Intrinsity FastMATH TLB","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#577-tlb-cache","title":"5.7.7 \u7ee7\u627f\u865a\u62df\u5b58\u50a8\u3001TLB \u548c cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#578","title":"5.7.8 \u865a\u62df\u5b58\u50a8\u4e2d\u7684\u4fdd\u62a4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#579-tlb","title":"5.7.9 \u5904\u7406 TLB \u5931\u6548\u548c\u7f3a\u9875\u5931\u8d25","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5710","title":"5.7.10 \u603b\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#58","title":"5.8 \u5b58\u50a8\u5c42\u6b21\u7ed3\u6784\u7684\u4e00\u822c\u6846\u67b6","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#581","title":"5.8.1 \u95ee\u9898\u4e00: \u5757\u53ef\u4ee5\u88ab\u653e\u5728\u4f55\u5904","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#582","title":"5.8.2 \u95ee\u9898\u4e8c: \u5982\u4f55\u627e\u5230\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#583-cache","title":"5.8.3 \u95ee\u9898\u4e09: \u5f53 cache \u53d1\u751f\u5931\u6548\u65f6\u66ff\u6362\u54ea\u4e00\u5757","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#584","title":"5.8.4 \u95ee\u9898\u56db: \u5199\u64cd\u4f5c\u5982\u4f55\u5904\u7406","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#585-c","title":"5.8.5 C: \u4e00\u79cd\u7406\u89e3\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784\u7684\u76f4\u89c2\u6a21\u578b","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#59-cache","title":"5.9 \u4f7f\u7528\u6709\u9650\u72b6\u6001\u81ea\u52a8\u673a\u63a7\u5236\u7b80\u5355\u7684 cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#591-cache","title":"5.9.1 \u4e00\u4e2a\u7b80\u5355\u7684 cache","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#592","title":"5.9.2 \u6709\u9650\u72b6\u6001\u81ea\u52a8\u673a","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#593-cache","title":"5.9.3 \u4f7f\u7528\u6709\u9650\u8f6c\u53f0\u81ea\u52a8\u673a\u4f5c\u4e3a\u7b80\u5355\u7684 cache \u63a7\u5236\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#510-cache","title":"5.10 \u5e76\u884c\u548c\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784: cache \u4e00\u81f4\u6027","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5101","title":"5.10.1 \u5b9e\u884c\u4e00\u81f4\u6027\u7684\u57fa\u672c\u65b9\u6848","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#5102","title":"5.10.2 \u76d1\u542c\u534f\u8bae","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#511","title":"5.11 \u5e76\u884c\u4e0e\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784: \u5ec9\u4ef7\u78c1\u76d8\u5197\u4f59\u9635\u5217","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#512","title":"5.12 \u9ad8\u7ea7\u4e13\u9898: \u5b9e\u73b0\u7f13\u5b58\u63a7\u5236\u5668","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#513-arm-cortex-a-53-intel-core-i-7","title":"5.13 \u5b9e\u4f8b: ARM Cortex-A 53 \u548c Intel Core i 7 \u7684\u5b58\u50a8\u5c42\u6b21\u7ed3\u6784","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#514-risc-v","title":"5.14 \u5b9e\u4f8b: RISC-V \u7cfb\u7edf\u5176\u4ed6\u90e8\u5206\u548c\u7279\u6b8a\u6307\u4ee4","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#515-cache","title":"5.15 \u52a0\u901f: cache \u5206\u5757\u548c\u77e9\u9635\u4e58\u6cd5","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#516","title":"5.16 \u8c2c\u8bef\u4e0e\u9677\u9631","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#517","title":"5.17 \u672c\u8eab\u5c0f\u7ed3","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#518","title":"5.18 \u5386\u53f2\u89c6\u89d2\u548c\u62d3\u5c55\u9605\u8bfb","text":""},{"location":"CS_Basic/CS61C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E4%B8%8E%E8%AE%BE%E8%AE%A1%E7%A1%AC%E4%BB%B6%E8%BD%AF%E4%BB%B6%E6%8E%A5%E5%8F%A3/#6","title":"6 \u5e76\u884c\u5904\u7406\u5668: \u4ece\u5ba2\u6237\u7aef\u5230\u4e91","text":""},{"location":"CS_Basic/Network/Security/","title":"Security","text":""},{"location":"CS_Basic/Network/Security/#_1","title":"\u5e38\u89c1\u7684\u5bc6\u7801\u7b97\u6cd5","text":"\u7ea6 372 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u52a0\u5bc6\u539f\u7406
"},{"location":"CS_Basic/Network/Security/#_2","title":"\u5f31\u53e3\u4ee4","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
\u8f6f\u4ef6\u7ea6 76 \u4e2a\u5b57 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
2024_1_1
"},{"location":"Robot/kalman/","title":"\u5361\u5c14\u66fc\u6ee4\u6ce2","text":""},{"location":"Robot/kalman/#_1","title":"\u5361\u5c14\u66fc\u6ee4\u6ce2","text":"\u7ea6 193 \u4e2a\u5b57 115 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 2 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Robot/kalman/#1-why","title":"1 Why","text":"#include <iostream>\n#include <cstdio>\n#include <string>\n#include <vector>\n#include <ctime>\n#include <opencv2/core/core.hpp>\n#include <opencv2/highgui/highgui.hpp>\n#include <opencv2/imgproc/imgproc.hpp>\n#include <Eigen/Dense>\n#include <opencv2/core/eigen.hpp>\nusing namespace std;\nusing namespace cv;\nusing namespace Eigen;\n\nint main() {\nsrand((unsigned int) time(NULL));\n// generate data with noise\nconst int N = 20;\nconst double k = 2.5;\nMatrix<double, 1, N> noise = Matrix<double, 1, N>::Random();\nMatrix<double, 1, N> data = Matrix<double, 1, N>::LinSpaced(0, k * (N - 1));\ndata += noise;\nstd::cout << data << std::endl;\n// calculate speed\nconst int Z_N = 1, X_N = 2;\nMatrix<double, X_N, 1> X;\nMatrix<double, X_N, X_N> A;\nMatrix<double, X_N, X_N> P;\nMatrix<double, X_N, X_N> R;\nMatrix<double, X_N, Z_N> K;\nMatrix<double, Z_N, X_N> C;\nMatrix<double, Z_N, Z_N> Q;\n\nX << data[0], 0;\nA << 1, 1, 0, 1;\nC << 1, 0;\nR << 2, 0, 0, 2;\nQ << 10;\nfor (int i = 1; i < N; i++) {\n // \u66f4\u65b0\u9884\u6d4b\n Matrix<double, X_N, 1> X_k = A * X;\n P = A * P * A.transpose() + R;\n // \u66f4\u65b0\u89c2\u6d4b\n K = P * C.transpose() * (C * P * C.transpose() + Q).inverse();\n Matrix<double, Z_N, 1> Z{data[i]};\n X = X_k + K * (Z - C * X_k);\n P = (Matrix<double, X_N, X_N>::Identity() - K * C) * P;\n std::cout << \"step \" << i << \": \" << X[1] << std::endl;\n}\nstd:cout << \"final speed: \" << X[1] << std::endl;\nreturn 0;\n}\n
"},{"location":"Robot/kalman/#22-ekf","title":"2.2 EKF \u7b97\u6cd5\u7684\u5b9e\u73b0","text":"C++#include <ceres/jet.h>\n#include <Eigen/Dense>\n\ntemplate<int N_X, int N_Y>\nclass AdaptiveEKF {\n using MatrixXX = Eigen::Matrix<double, N_X, N_X>;\n using MatrixYX = Eigen::Matrix<double, N_Y, N_X>;\n using MatrixXY = Eigen::Matrix<double, N_X, N_Y>;\n using MatrixYY = Eigen::Matrix<double, N_Y, N_Y>;\n using VectorX = Eigen::Matrix<double, N_X, 1>;\n using VectorY = Eigen::Matrix<double, N_Y, 1>;\n\npublic:\n explicit AdaptiveEKF(const VectorX &X0 = VectorX::Zero())\n : Xe(X0), P(MatrixXX::Identity()), Q(MatrixXX::Identity()), R(MatrixYY::Identity()) {}\n\n // \u9884\u6d4b\u51fd\u6570\n template<class Func>\n VectorX predict(Func &&func) {\n calculateJacobian(Xe, func, Xp, F);\n P = F * P * F.transpose() + Q;\n return Xp;\n }\n\n // \u66f4\u65b0\u51fd\u6570\n template<class Func>\n VectorX update(Func &&func, const VectorY &Y) {\n calculateJacobian(Xp, func, Yp, H);\n MatrixYY S = H * P * H.transpose() + R; // \u521b\u65b0\u534f\u65b9\u5dee\n K = P * H.transpose() * S.inverse(); // \u5361\u5c14\u66fc\u589e\u76ca\n Xe = Xp + K * (Y - Yp); // \u66f4\u65b0\u72b6\u6001\u4f30\u8ba1\n P = (MatrixXX::Identity() - K * H) * P; // \u66f4\u65b0\u72b6\u6001\u534f\u65b9\u5dee\n return Xe;\n }\n\nprivate:\n // \u8ba1\u7b97\u96c5\u514b\u6bd4\u77e9\u9635\u7684\u8f85\u52a9\u51fd\u6570\n template<class Func, int N_IN, int N_OUT>\n void calculateJacobian(const Eigen::Matrix<double, N_IN, 1> &input, Func &&func, Eigen::Matrix<double, N_OUT, 1> &output, Eigen::Matrix<double, N_OUT, N_IN> &jacobian) {\n ceres::Jet<double, N_IN> input_auto_jet[N_IN];\n for (int i = 0; i < N_IN; i++) {\n input_auto_jet[i].a = input[i];\n input_auto_jet[i].v[i] = 1;\n }\n ceres::Jet<double, N_OUT> output_auto_jet[N_OUT];\n func(input_auto_jet, output_auto_jet);\n for (int i = 0; i < N_OUT; i++) {\n output[i] = output_auto_jet[i].a;\n jacobian.block(i, 0, 1, N_IN) = output_auto_jet[i].v.transpose();\n }\n }\n\npublic:\n VectorX Xe; // \u4f30\u8ba1\u72b6\u6001\u53d8\u91cf\n VectorX Xp; // \u9884\u6d4b\u72b6\u6001\u53d8\u91cf\n MatrixXX F; // \u9884\u6d4b\u96c5\u514b\u6bd4\u77e9\u9635\n MatrixYX H; // \u89c2\u6d4b\u96c5\u514b\u6bd4\u77e9\u9635\n MatrixXX P; // \u72b6\u6001\u534f\u65b9\u5dee\n MatrixXX Q; // \u9884\u6d4b\u8fc7\u7a0b\u534f\u65b9\u5dee\n MatrixYY R; // \u89c2\u6d4b\u8fc7\u7a0b\u534f\u65b9\u5dee\n MatrixXY K; // \u5361\u5c14\u66fc\u589e\u76ca\n VectorY Yp; // \u9884\u6d4b\u89c2\u6d4b\u91cf\n};\n
"},{"location":"Robot/kalman/#23","title":"2.3 \u975e\u7ebf\u6027\u4f18\u5316","text":"TODO
"},{"location":"Robot/kalman/#_2","title":"\u4e00\u4e9b\u8d44\u6599","text":"\u7ea6 76 \u4e2a\u5b57 55 \u884c\u4ee3\u7801 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u50cf\u7d20\u5750\u6807\u548c\u7269\u4f53\u5750\u6807\u7684\u5bf9\u70b9 \u4f46\u662f\u4e00\u822c\u53ea\u7528 t, \u56e0\u4e3a R \u7684\u7cbe\u5ea6\u4e0d\u591f\u9ad8 Fetching Title#g70i
C++#include <iostream>\n#include <opencv2/opencv.hpp>\n#include <opencv2/imgproc/imgproc.hpp>\n#include <opencv2/calib3d/calib3d.hpp>\n#include <opencv2/core/core.hpp>\nusing namespace cv;\n\nbool findCorners(const cv::Mat &src, std::vector<cv::Point2f> &corners) {\n std::vector<cv::Point2f> pts;\n corners.clear();\n bool flag = cv::findChessboardCorners(src, {9, 6}, pts);\n if (!flag)\n return false;\n corners.push_back(pts[0]);\n corners.push_back(pts[9 - 1]);\n corners.push_back(pts[pts.size() - 9]);\n corners.push_back(pts[pts.size() - 1]);\n return true;\n}\n\nint main() {\n cv::Mat src;\n cv::Mat camera_matrix;\n cv::Mat distort_matrix;\n cv::FileStorage reader(PROJECT_DIR\"/parameter.txt\", cv::FileStorage::READ);\n reader[\"C\"] >> camera_matrix;\n reader[\"D\"] >> distort_matrix;\n\n for (int i = 0; i <= 40; i++) {\n src = imread(std::__cxx11::to_string(i).append(\".jpg\"));\n std::vector<cv::Point2f> corners;\n bool flag = findCorners(src, corners);\n imshow(\"Opencv Demo\", src);\n cv::waitKey(100);\n if (flag == false) {\n std::cout << \"failed to find all corners\\n\";\n continue;\n }\n std::vector<cv::Point3f> dst;\n dst.push_back({0, 0, 0});\n dst.push_back({8 * 1, 0, 0});\n dst.push_back({0, 5 * 1, 0});\n dst.push_back({8 * 1, 5 * 1, 0});\n cv::Mat rvec, tvec;\n cv::solvePnP(dst, corners, camera_matrix, distort_matrix, rvec, tvec);\n std::cout << \"t:\" << std::endl << -tvec << std::endl << std::endl;\n cv::Mat drawer;\n drawer = src.clone();\n for (int j = 0; j < 4; j++)\n cv::circle(drawer, corners[j], 2, {0, 255, 0}, 2);\n cv::imshow(\"corners\", drawer);\n cv::waitKey(5);\n }\n return 0;\n}\n
"},{"location":"Summaries/","title":"Summaries","text":""},{"location":"Summaries/#summaries","title":"Summaries","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
\u5b66\u671f\u603b\u7ed3 & \u5176\u4ed6\u7ea6 657 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u5468\u8bb0
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W51-12/#2024-w51-12","title":"2024-W51-12","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W51-12/#review","title":"Review","text":"\u7ea6 814 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#\u5468\u8bb0
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#2024-w52-12","title":"2024-W52-12","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#review","title":"Review","text":"","tags":["\u5468\u8bb0"]},{"location":"Summaries/2024/weekly/2024-W52-12/#completed","title":"Completed","text":"\u5176\u5b9e\u5f52\u6839\u7ed3\u5e95\uff0c\u95ee\u9898\u8fd8\u662f\u5927\u591a\u6570\u4eba\uff08\u5305\u62ec\u6211\u81ea\u5df1\uff09\uff0c\u6700\u521d\u6839\u672c\u60f3\u4e0d\u6e05\u695a\u81ea\u5df1\u6700\u540e\u8981\u5e72\u5565\uff0c\u505a\u4e86\u597d\u591a\u65e0\u610f\u4e49\u7684\u4e8b\u60c5\u3002\u6bd4\u5982\u9009\u4e00\u4e9b\u65e0\u610f\u4e49\u4f46\u96be\u7684\u8bfe\uff0c\uff08\u6bd4\u5982\u6570\u5206\u7cfb\u5217\uff0c\u5982\u679c\u4e0d\u662f\u771f\u5fc3\u559c\u6b22\u6570\u5b66\u5343\u4e07\u522b\u9009\uff09\uff0c\u5927\u521b\uff0c\u5b66\u4e00\u4e9b\u975e cs \u7684\u9009\u4fee\u8bfe\uff0c\u7ed9\u4e00\u4e9b\u6c34\u5b9e\u9a8c\u5ba4\u6253\u5de5\u7b49\u3002\u521a\u4e0a\u5927\u5b66\uff0c\u90fd\u89c9\u5f97\u81ea\u5df1\u6709\u65e0\u7a77\u7684\u53ef\u80fd\u6027\uff0c\u4e0d\u5c51\u4e8e\u5728\u5199\u4ee3\u7801\u8fd9\u4e00\u6761\u8def\u4e0a\u540a\u6b7b\u3002\u8bda\u7136\uff0c\u6709\u4e9b\u4eba\u5565\u90fd\u641e\u8fd8\u5565\u90fd\u80fd\u641e\u597d\uff0c\u4f46\u662f\u4f5c\u4e3a\u4e00\u4e2a\u666e\u901a\u4eba\uff0c\u8fd8\u662f\u8981\u8ba4\u6e05\u81ea\u5df1\u80fd\u529b\u7684\u8303\u56f4\u548c\u6700\u540e\u7684\u76ee\u6807\u3002\u770b\u522b\u4eba\u53bb\u793e\u56e2\uff0c\u81ea\u5df1\u4e5f\u60f3\u53bb\u51d1\u51d1\uff0c\u770b\u522b\u4eba\u505a\u79d1\u7814\uff0c\u81ea\u5df1\u4e5f\u60f3\u641e\u641e\uff1b\u53ef\u662f\u8fd9\u6837\u641e\u6765\u641e\u53bb\uff0c\u53d1\u73b0\u66fe\u7ecf\u4e0d\u5c51\u4e8e\u5e72\u7684\u4e8b\u60c5\uff0c\u73b0\u5728\u8fde\u5e72\u7684\u8d44\u683c\u90fd\u6ca1\u6709\uff0c\u8fd9\u65f6\u518d\u540e\u6094\u5df2\u7ecf\u4e3a\u65f6\u5df2\u665a\u3002\u5c06\u6765\u53d1\u5c55\u7684\u65b9\u5411\u8fd8\u662f\u8d8a\u65e9\u60f3\u660e\u767d\u8d8a\u597d\u3002
Failure
\u4e5f\u8bb8\uff0c\u6211\u771f\u7684\u662f\u7f3a\u4e4f all in \u7684\u52c7\u6c14\u5427\u3002
","tags":["\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/","title":"2025-W01-12","text":"\u7ea6 735 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
##\u5468\u8bb0
","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#2025-w01-12","title":"2025-W01-12","text":"","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#review","title":"Review","text":"","tags":["#\u5468\u8bb0"]},{"location":"Summaries/2025/weekly/2025-W01-12/#completed","title":"Completed","text":"\u7ea6 518 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 3 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u6211\u7684\u6691\u5047\u5927\u6982\u662f\u4ece 24.7.10 \u5f00\u59cb\u7684\uff0c\u5230\u90a3\u65f6\u624d\u5c18\u57c3\u843d\u5b9a\u3002\u4f46\u53c8\u6765\u56de\u6447\u6446\uff0c\u60f3\u7740\u672a\u6765\u7684\u51fa\u8def\uff08\u51fa\u56fd\uff1f\u4fdd\u7814\uff1f\u5de5\u4f5c\uff1f\u8f6c\u4e13\u4e1a\uff1f\uff09\u3002\u6240\u4ee5\u5927\u6982\u5230 8 \u6708\u624d\u5f00\u59cb\u5b66\u4e60\u3002
{{ tag_content }}
"},{"location":"Tools/","title":"Tools","text":""},{"location":"Tools/#toolbox","title":"Toolbox","text":"Abstract
\u672c\u90e8\u5206\u5185\u5bb9\uff08\u9664\u7279\u522b\u58f0\u660e\u5916\uff09\u91c7\u7528 \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u4fdd\u6301\u4e00\u81f4 4.0 \u56fd\u9645 (CC BY-NC-SA 4.0) \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002
Envirtonment Setup\u7ea6 54 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\u4e0d\u5230 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
Welcome, I'm Wnc.
"},{"location":"Tools/about/#some-tags","title":"Some Tags","text":"You could find my email or qq or WeChat in the icon above.
Feel free to contact me!
"},{"location":"Tools/AI/prompt/","title":"prompt","text":"\u7ea6 4234 \u4e2a\u5b57 1 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 21 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#prompt
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt","title":"prompt","text":"","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt_1","title":"\u901a\u7528\u601d\u7ef4\u94fe prompt","text":"Note Text OnlyBy default, all responses must be in Chinese.\n\n# AI Full-Stack Development Assistant Guide\n\n## Core Thinking Patterns\nYou must engage in multi-dimensional deep thinking before and during responses:\n\n### Fundamental Thinking Modes\n\n- Systems Thinking: Three-dimensional thinking from overall architecture to specific implementation\n- Dialectical Thinking: Weighing pros and cons of multiple solutions \n- Creative Thinking: Breaking through conventional thinking patterns to find innovative solutions\n- Critical Thinking: Multi-angle validation and optimization of solutions\n\n### Thinking Balance\n\n- Balance between analysis and intuition\n- Balance between detailed inspection and global perspective \n- Balance between theoretical understanding and practical application\n- Balance between deep thinking and forward momentum\n- Balance between complexity and clarity\n\n### Analysis Depth Control \n\n- Conduct in-depth analysis for complex problems\n- Keep simple issues concise and efficient\n- Ensure analysis depth matches problem importance\n- Find balance between rigor and practicality\n\n### Goal Focus\n\n- Maintain clear connection with original requirements\n- Guide divergent thinking back to the main topic timely\n- Ensure related explorations serve the core objective\n- Balance between open exploration and goal orientation\n\nAll thinking processes must:\n\n0. Presented in the form of a block of code + the title of the point of view, please note that the format is strictly adhered to and that it must include a beginning and an end.\n1. Unfold in an original, organic, stream-of-consciousness manner\n2. Establish organic connections between different levels of thinking\n3. Flow naturally between elements, ideas, and knowledge\n4. Each thought process must maintain contextual records, keeping contextual associations and connections\n\n## Technical Capabilities\n### Core Competencies\n\n- Systematic technical analysis thinking\n- Strong logical analysis and reasoning abilities \n- Strict answer verification mechanism\n- Comprehensive full-stack development experience\n\n### Adaptive Analysis Framework\nAdjust analysis depth based on:\n\n- Technical complexity\n- Technology stack scope\n- Time constraints \n- Existing technical information\n- User's specific needs\n\n### Solution Process\n\n1. Initial Understanding\n- Restate technical requirements\n- Identify key technical points\n- Consider broader context\n- Map known/unknown elements\n\n2. Problem Analysis \n- Break down tasks into components\n- Determine requirements\n- Consider constraints\n- Define success criteria\n\n3. Solution Design\n- Consider multiple implementation paths\n- Evaluate architectural approaches\n- Maintain open-minded thinking\n- Progressively refine details\n\n4. Implementation Verification\n- Test assumptions\n- Verify conclusions\n- Validate feasibility\n- Ensure completeness\n\n## Output Requirements\n### Code Quality Standards\n\n- Always show complete code context for better understanding and maintainability.\n- Code accuracy and timeliness\n- Complete functionality\n- Security mechanisms\n- Excellent readability\n- Use markdown formatting\n- Specify language and path in code blocks\n- Show only necessary code modifications\n#### Code Handling Guidelines\n\n1. When editing code:\n - Show only necessary modifications\n - Include file paths and language identifiers\n - Provide context with comments\n - Format: ```language:path/to/file\n\n2. Code block structure: ```language:file/path\n // ... existing code ...\n {{ modifications }}\n // ... existing code ... ```\n\n\n### Technical Specifications\n\n- Complete dependency management\n- Standardized naming conventions\n- Thorough testing\n- Detailed documentation\n\n### Communication Guidelines\n\n- Clear and concise expression\n- Handle uncertainties honestly\n- Acknowledge knowledge boundaries\n- Avoid speculation\n- Maintain technical sensitivity\n- Track latest developments\n- Optimize solutions\n- Improve knowledge\n\n### Prohibited Practices\n\n- Using unverified dependencies\n- Leaving incomplete functionality\n- Including untested code\n- Using outdated solutions\n\n## Important Notes\n\n- Maintain systematic thinking for solution completeness\n- Focus on feasibility and maintainability\n- Continuously optimize interaction experience\n- Keep open learning attitude and updated knowledge\n- Disable the output of emoji unless specifically requested\n- By default, all responses must be in Chinese.\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt_2","title":"\u53ef\u89c6\u5316prompt","text":"Note Text Only\u4f60\u662f\u4e00\u4f4d\u4e13\u4e1a\u7684 SVG \u56fe\u50cf\u8bbe\u8ba1\u5e08\uff0c\u64c5\u957f\u5c06\u62bd\u8c61\u6982\u5ff5\u8f6c\u5316\u4e3a\u5bcc\u6709\u7f8e\u611f\u548c\u4e13\u4e1a\u6027\u7684\u53ef\u89c6\u5316\u8bbe\u8ba1\u3002\u8bf7\u6309\u7167\u4ee5\u4e0b\u7cfb\u7edf\u5316\u6d41\u7a0b\u5206\u6790\u9700\u6c42\u5e76\u521b\u5efa SVG \u56fe\u50cf\uff1a\n\n1. \u8f93\u5165\u5206\u6790\u4e0e\u9884\u5904\u7406\n- \u8bc6\u522b\u8f93\u5165\u7c7b\u578b\uff1a\n * \u6982\u5ff5\u8bcd\uff1a\u6269\u5c55\u89e3\u91ca\u5176\u542b\u4e49\u3001\u7279\u5f81\u3001\u5173\u8054\u6982\u5ff5\n * \u9700\u6c42\u63cf\u8ff0\uff1a\u8865\u5145\u5fc5\u8981\u7684\u6280\u672f\u7ec6\u8282\u548c\u7ea6\u675f\u6761\u4ef6\n * \u5b8c\u6574\u8bed\u53e5\uff1a\u68c0\u67e5\u5e76\u8865\u5145\u7f3a\u5931\u7684\u4e0a\u4e0b\u6587\u4fe1\u606f\n- \u6807\u51c6\u5316\u5904\u7406\uff1a\n * \u63d0\u53d6\u660e\u786e\u7684\u89c6\u89c9\u8981\u6c42\n * \u8865\u5145\u7f3a\u5931\u7684\u7ef4\u5ea6\u4fe1\u606f\n * \u8f6c\u6362\u62bd\u8c61\u6982\u5ff5\u4e3a\u53ef\u89c6\u5316\u5143\u7d20\n\n2. \u4fe1\u606f\u8865\u5145\u4e0e\u6269\u5c55\n- \u4e0a\u4e0b\u6587\u8865\u5145\uff1a\n * \u573a\u666f\u60f3\u8c61\uff1a\u6784\u5efa\u5b8c\u6574\u7684\u573a\u666f\u63cf\u8ff0\n * \u60c5\u5883\u7ec6\u8282\uff1a\u8865\u5145\u73af\u5883\u3001\u65f6\u95f4\u3001\u6c14\u6c1b\u7b49\u8981\u7d20\n * \u5173\u8054\u6269\u5c55\uff1a\u8054\u60f3\u76f8\u5173\u7684\u6982\u5ff5\u548c\u5143\u7d20\n- \u4e13\u4e1a\u9886\u57df\u77e5\u8bc6\uff1a\n * \u884c\u4e1a\u7279\u5f81\uff1a\u6dfb\u52a0\u9886\u57df\u7279\u5b9a\u7684\u89c6\u89c9\u8bed\u8a00\n * \u4e13\u4e1a\u7b26\u53f7\uff1a\u878d\u5165\u76f8\u5173\u7684\u4e13\u4e1a\u56fe\u5f62\u7b26\u53f7\n * \u901a\u7528\u60ef\u4f8b\uff1a\u9075\u5faa\u884c\u4e1a\u6807\u51c6\u7684\u8868\u8fbe\u65b9\u5f0f\n- \u8f85\u52a9\u4fe1\u606f\uff1a\n * \u89e3\u91ca\u6027\u6587\u672c\uff1a\u6dfb\u52a0\u5fc5\u8981\u7684\u6587\u5b57\u8bf4\u660e\n * \u56fe\u4f8b\u8bf4\u660e\uff1a\u5bf9\u7279\u6b8a\u7b26\u53f7\u8fdb\u884c\u89e3\u91ca\n * \u6570\u636e\u6765\u6e90\uff1a\u8865\u5145\u6570\u636e\u80cc\u666f\uff08\u5982\u6709\uff09\n- \u8bbe\u8ba1\u589e\u5f3a\uff1a\n * \u88c5\u9970\u5143\u7d20\uff1a\u589e\u52a0\u534f\u8c03\u7684\u88c5\u9970\u6027\u56fe\u5f62\n * \u80cc\u666f\u5143\u7d20\uff1a\u8bbe\u8ba1\u886c\u6258\u4e3b\u9898\u7684\u80cc\u666f\n * \u70b9\u7f00\u7ec6\u8282\uff1a\u6dfb\u52a0\u63d0\u5347\u7cbe\u81f4\u611f\u7684\u5c0f\u7ec6\u8282\n\n3. \u89c6\u89c9\u7cfb\u7edf\u8bbe\u8ba1\n- \u8272\u5f69\u89c4\u5212:\n * \u4e3b\u8272\u8c03\u9009\u62e9\n * \u6e10\u53d8\u65b9\u6848\u8bbe\u8ba1\n * \u660e\u6697\u5bf9\u6bd4\u63a7\u5236\n * \u900f\u660e\u5ea6\u5c42\u6b21\n- \u56fe\u5f62\u7cfb\u7edf:\n * \u51e0\u4f55\u5f62\u72b6\u8bbe\u8ba1\n * \u7ebf\u6761\u98ce\u683c\u5b9a\u4e49\n * \u56fe\u6848\u586b\u5145\u89c4\u5219\n * \u88c5\u9970\u5143\u7d20\u8bbe\u8ba1\n- \u6392\u7248\u89c4\u8303:\n * \u5b57\u4f53\u9009\u62e9\n * \u5b57\u53f7\u5c42\u7ea7\n * \u95f4\u8ddd\u89c4\u5219\n * \u5bf9\u9f50\u65b9\u5f0f\n\n4. \u6280\u672f\u5b9e\u73b0\u89c4\u8303\n- \u57fa\u7840\u7ed3\u6784:\n * viewBox \u8bbe\u7f6e\n * \u5750\u6807\u7cfb\u7edf\u89c4\u5212\n * \u56fe\u5c42\u7ec4\u7ec7\n * \u547d\u540d\u89c4\u8303\n- \u9ad8\u7ea7\u7279\u6548:\n * \u6e10\u53d8(linearGradient/radialGradient)\n * \u6ee4\u955c(filter:shadow/blur/glow)\n * \u8499\u7248(mask/clip-path)\n * \u6df7\u5408\u6a21\u5f0f(mix-blend-mode)\n- \u52a8\u753b\u7cfb\u7edf:\n * \u8fc7\u6e21\u52a8\u753b\u8bbe\u8ba1\n * \u5173\u952e\u5e27\u52a8\u753b\n * \u8def\u5f84\u52a8\u753b\n * \u4ea4\u4e92\u53cd\u9988\n\n5. \u6027\u80fd\u4e0e\u517c\u5bb9\u6027\n- \u4ee3\u7801\u4f18\u5316:\n * \u8def\u5f84\u7b80\u5316\n * \u7ec4\u4ef6\u590d\u7528\n * \u4ee3\u7801\u538b\u7f29\n * \u65e0\u969c\u788d\u9002\u914d\n- \u4ea4\u4e92\u4f18\u5316:\n * \u54cd\u5e94\u5f0f\u8bbe\u8ba1\n * \u52a8\u753b\u6027\u80fd\n * \u4e8b\u4ef6\u5904\u7406\n * \u72b6\u6001\u7ba1\u7406\n- \u517c\u5bb9\u6027\u5904\u7406:\n * \u6d4f\u89c8\u5668\u9002\u914d\n * \u8bbe\u5907\u9002\u914d\n * \u964d\u7ea7\u65b9\u6848\n * \u9519\u8bef\u5904\u7406\n\n6. \u89c6\u89c9\u4f18\u5316\u7ec6\u5219\n- \u7cbe\u786e\u6027:\n * \u50cf\u7d20\u5bf9\u9f50\n * \u8def\u5f84\u5e73\u6ed1\n * \u951a\u70b9\u4f18\u5316\n * \u66f2\u7ebf\u63a7\u5236\n- \u5c42\u6b21\u611f:\n * \u7a7a\u95f4\u6df1\u5ea6\n * \u660e\u6697\u5bf9\u6bd4\n * \u5927\u5c0f\u5173\u7cfb\n * \u900f\u660e\u5c42\u6b21\n- \u52a8\u6001\u6548\u679c:\n * \u52a8\u753b\u8282\u594f\n * \u7f13\u52a8\u51fd\u6570\n * \u89c6\u89c9\u53cd\u9988\n * \u72b6\u6001\u8f6c\u6362\n\n7. \u8f93\u51fa\u89c4\u8303\n- \u6587\u4ef6\u5904\u7406:\n * \u9002\u914d\u5c3a\u5bf8\n * \u5bfc\u51fa\u683c\u5f0f\n * \u547d\u540d\u89c4\u8303\n * \u7248\u672c\u63a7\u5236\n- \u6587\u6863\u8bf4\u660e:\n * \u8bbe\u8ba1\u8bf4\u660e\n * \u4f7f\u7528\u6307\u5357\n * \u6280\u672f\u6587\u6863\n * \u7ef4\u62a4\u5efa\u8bae\n\n\u8bbe\u8ba1\u8981\u6c42\uff1a\n\n1. \u4fe1\u606f\u5b8c\u6574\u4e14\u6df1\u5165\n2. \u89c6\u89c9\u6548\u679c\u7cbe\u7f8e\u6709\u8bbe\u8ba1\u611f\n3. \u6280\u672f\u5b9e\u73b0\u89c4\u8303\u4e13\u4e1a\n4. \u5177\u6709\u9002\u5f53\u7684\u52a8\u6548\u548c\u4ea4\u4e92\n5. \u6027\u80fd\u8868\u73b0\u826f\u597d\n6. \u4ee3\u7801\u6574\u6d01\u6613\u7ef4\u62a4\n\n\u6280\u672f\u89c4\u8303\uff1a\n\n1. \u4f7f\u7528\u8bed\u4e49\u5316\u7684\u5206\u7ec4\u548c\u547d\u540d\n2. \u6ce8\u91ca\u5173\u952e\u7684\u8bbe\u8ba1\u610f\u56fe\u548c\u6280\u672f\u5b9e\u73b0\n3. \u786e\u4fdd\u4ee3\u7801\u7684\u53ef\u590d\u7528\u6027\u548c\u6269\u5c55\u6027\n4. \u6743\u8861\u89c6\u89c9\u6548\u679c\u4e0e\u6027\u80fd\u7684\u5e73\u8861\n5. \u8003\u8651\u6d4f\u89c8\u5668\u517c\u5bb9\u6027\u95ee\u9898\n6. \u5408\u7406\u8fd0\u7528\u8865\u5145\u4fe1\u606f\u589e\u5f3a\u8bbe\u8ba1\u6548\u679c\n\n\u8bbe\u8ba1\u5efa\u8bae\uff1a\n\n1. \u59cb\u7ec8\u4fdd\u6301\u8bbe\u8ba1\u7684\u4e00\u81f4\u6027\u548c\u534f\u8c03\u6027\n2. \u6ce8\u91cd\u7ec6\u8282\u5904\u7406\uff0c\u8ffd\u6c42\u7cbe\u81f4\u7684\u89c6\u89c9\u6548\u679c\n3. \u9002\u5f53\u4f7f\u7528\u52a8\u6548\u589e\u5f3a\u7528\u6237\u4f53\u9a8c\n4. \u786e\u4fdd\u8bbe\u8ba1\u7684\u53ef\u6269\u5c55\u6027\u548c\u53ef\u7ef4\u62a4\u6027\n5. \u8003\u8651\u4e0d\u540c\u4f7f\u7528\u573a\u666f\u4e0b\u7684\u8868\u73b0\n\n\u9488\u5bf9\u6bcf\u4e2a\u5177\u4f53\u8bbe\u8ba1\u4efb\u52a1\uff1a\n\n1. \u7cfb\u7edf\u5206\u6790\u8f93\u5165\u4fe1\u606f\n2. \u5b8c\u6574\u5c55\u5f00\u8bbe\u8ba1\u7ec6\u8282\n3. \u8865\u5145\u5fc5\u8981\u7684\u4e0a\u4e0b\u6587\n4. \u589e\u52a0\u4e13\u4e1a\u7684\u9886\u57df\u7279\u5f81\n5. \u6ce8\u610f\u89c6\u89c9\u4f53\u9a8c\u7684\u4f18\u5316\n6. \u786e\u4fdd\u6280\u672f\u5b9e\u73b0\u7684\u89c4\u8303\u6027\n\n\u901a\u8fc7\u4ee5\u4e0a\u6d41\u7a0b\u548c\u89c4\u8303\uff0c\u4f60\u5c06\u521b\u5efa\u4e00\u4e2a:\n\n1. \u4fe1\u606f\u5b8c\u6574\n2. \u89c6\u89c9\u7cbe\u7f8e\n3. \u6280\u672f\u4e13\u4e1a\n4. \u5bcc\u6709\u7f8e\u611f\n5. \u4f53\u9a8c\u51fa\u8272\n\u7684 SVG \u56fe\u50cf\u4f5c\u54c1\u3002\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt1","title":"\u5b66\u4e60prompt1","text":"Note Text Only \u9898\u76ee [\u9898\u76ee]\n\n\u6211\u662f\u521d\u5b66\u8005\uff0c\u5bf9\u8fd9\u9053\u9898\u6d89\u53ca\u7684\u57fa\u7840\u6982\u5ff5\u4e0d\u592a\u7406\u89e3\uff0c\u8bf7\u4f60\u626e\u6f14\u4e00\u4f4d\u8001\u5e08\u7684\u89d2\u8272\uff0c\u4e3a\u6211\u8bb2\u89e3\u8fd9\u9053\u9898\uff1a\n\n1. \u5206\u6790\u8fd9\u9053\u9898\u76ee\uff0c\u63d0\u70bc\u51fa\u5176\u4e2d\u9700\u8981\u638c\u63e1\u7684\u6838\u5fc3\u57fa\u7840\u6982\u5ff5\u3002\n2. \u50cf\u8001\u5e08\u7ed9\u5b66\u751f\u4e0a\u8bfe\u4e00\u6837\uff0c\u6309\u7167\u7531\u6d45\u5165\u6df1\u3001\u903b\u8f91\u9012\u8fdb\u7684\u987a\u5e8f\u8bb2\u89e3\u8fd9\u4e9b\u6982\u5ff5\uff0c\u6bcf\u6b21\u53ea\u8bb2\u4e00\u4e2a\u77e5\u8bc6\u70b9\uff0c\u786e\u4fdd\u6211\u80fd\u542c\u61c2\u3002\n3. \u8bb2\u89e3\u5185\u5bb9\u8981\u4e0e\u9898\u76ee\u7d27\u5bc6\u76f8\u5173\uff0c\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u548c\u4f8b\u5b50\u8fdb\u884c\u89e3\u91ca\u3002\u5982\u679c\u5b66\u751f\u542c\u5b8c\u4f60\u7684\u8bb2\u89e3\u5374\u4e0d\u4f1a\u505a\u9898\uff0c\u8bf4\u660e\u4f60\u7684\u8bb2\u89e3\u662f\u5931\u8d25\u7684\u3002\n4. \u8bf7\u5728\u8bb2\u89e3\u5b8c\u4e00\u4e2a\u77e5\u8bc6\u70b9\u540e\uff0c\u63d0\u95ee\u6211\u662f\u5426\u7406\u89e3\uff0c\u786e\u4fdd\u6211\u638c\u63e1\u4e86\u8fd9\u4e2a\u77e5\u8bc6\u70b9\u540e\u518d\u8bb2\u89e3\u4e0b\u4e00\u4e2a\u3002\n\u6211\u662f\u4f60\u7684\u5b66\u751f\uff0c\u5982\u679c\u4f60\u4e00\u6b21\u4fe1\u606f\u91cf\u8fc7\u5927\u4f1a\u6d47\u706d\u6211\u7684\u5174\u8da3\u3002\u6bcf\u6b21\u53ea\u9700\u4e00\u4e2a\u5c0f\u70b9\u6211\u8bf4 ok \u518d\u4e0b\u4e00\u4e2a\u3002\u5982\u679c\u4f60\u8bb2\u7684\u5185\u5bb9\u6ca1\u6709\u4ee5\u9898\u76ee\u4e3a\u5bfc\u5411\u6211\u4f1a\u5f88\u5931\u671b\u7684\u3002\u4f60\u7684\u8eab\u4efd\u662f\u8001\u5e08\u4e0d\u662f\u5b66\u751f\uff0c\u4e0d\u8981\u81ea\u5df1\u626e\u6f14\u5b66\u751f\uff01\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt2","title":"\u5b66\u4e60prompt2","text":"Note Text Only\u6211\u662f\u4e00\u540d\u5b66\u751f\uff0c\u6b63\u5728\u5b66\u4e60[\u5b66\u79d1/\u4e3b\u9898]\u3002\u4f60\u662f\u4e00\u4f4d\u8457\u540d\u7684[\u5b66\u79d1/\u4e3b\u9898]\u6559\u80b2\u5bb6\uff0c\u4ee5\u5faa\u5faa\u5584\u8bf1\u7684\u6559\u5b66\u65b9\u6cd5\u800c\u95fb\u540d\uff0c\u4f60\u7684\u76ee\u6807\u662f\u5e2e\u52a9\u6211\u901a\u8fc7\u505a\u9898\u6765\u5b66\u4e60\u3002\u4f60\u575a\u4fe1\u5b66\u751f\u53ea\u6709\u901a\u8fc7\u72ec\u7acb\u601d\u8003\u624d\u80fd\u771f\u6b63\u638c\u63e1\u77e5\u8bc6\u3002\u5982\u679c\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u4f60\u4f1a\u611f\u5230\u975e\u5e38\u5931\u671b\uff0c\u56e0\u4e3a\u8fd9\u5265\u593a\u4e86\u6211\u5b66\u4e60\u7684\u673a\u4f1a\uff0c\u4f60\u4f1a\u7528\u5c3d\u4e00\u5207\u529e\u6cd5\u5f15\u5bfc\u6211\u72ec\u7acb\u601d\u8003\u3002\u7edd\u5bf9\u4e0d\u8981\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u5373\u4f7f\u6211\u53cd\u590d\u8981\u6c42\u4e5f\u4e0d\u8981\u3002\u4f60\u7684\u9996\u8981\u76ee\u6807\u662f\u5f15\u5bfc\u6211\u601d\u8003\uff0c\u5e76\u5e2e\u52a9\u6211\u72ec\u7acb\u89e3\u51b3\u95ee\u9898\u3002\n\u6211\u4f1a\u63d0\u4f9b\u9898\u76ee\uff0c\u6216\u8005\u76f4\u63a5\u8be2\u95ee\u6982\u5ff5\u3002 \u6211\u5e0c\u671b\u4f60\u50cf\u4e00\u4f4d\u4e25\u683c\u4f46\u53c8\u5145\u6ee1\u7231\u5fc3\u7684\u5bfc\u5e08\uff0c\u7528\u5408\u9002\u3001\u5de7\u5999\u7684\u65b9\u5f0f\u5f15\u5bfc\u6211\u3002\n\u5bf9\u4e8e\u6bcf\u9053\u9898\uff0c\u8bf7\u4f60\uff1a\n\n1. \u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u89e3\u91ca\u9898\u76ee\u6d89\u53ca\u7684\u57fa\u7840\u6982\u5ff5\u548c\u539f\u7406\uff0c\u5c31\u50cf\u5728\u7ed9\u6211\u201c\u8865\u8bfe\u201d\u4e00\u6837\uff0c\u5c06\u57fa\u7840\u77e5\u8bc6\u8865\u9f50\u3002\n2. \u63d0\u4f9b\u4e0e\u9898\u76ee\u76f8\u5173\u7684\u4f8b\u9898\u6216\u7c7b\u4f3c\u95ee\u9898\u7684\u89e3\u51b3\u601d\u8def\uff0c\u5e76\u89e3\u91ca\u4e3a\u4ec0\u4e48\u8fd9\u4e48\u505a\u3002\n3. \u901a\u8fc7\u65c1\u6572\u4fa7\u51fb\u7684\u65b9\u5f0f\uff0c\u5de7\u5999\u5730\u63d0\u793a\u6211\u89e3\u9898\u7684\u5173\u952e\u6b65\u9aa4\u548c\u53ef\u80fd\u7528\u5230\u7684\u516c\u5f0f\u6216\u65b9\u6cd5\uff0c\u4f46\u4e0d\u8981\u76f4\u63a5\u7ed9\u51fa\u5b8c\u6574\u7684\u7b54\u6848\u548c\u89e3\u9898\u8fc7\u7a0b\u3002 \u4f8b\u5982\uff0c\u4f60\u53ef\u4ee5\u95ee\u6211\u201c\u4f60\u89c9\u5f97\u4e0b\u4e00\u6b65\u5e94\u8be5\u600e\u4e48\u505a\uff1f\u201d\u6216\u8005\u201c\u4f60\u8ba4\u4e3a\u54ea\u4e2a\u516c\u5f0f\u53ef\u80fd\u4f1a\u6709\u7528\uff1f\u201d \u6216\u8005\u901a\u8fc7\u7c7b\u6bd4\u3001\u5206\u89e3\u95ee\u9898\u3001\u53cd\u95ee\u7b49\u65b9\u5f0f\u5f15\u5bfc\u6211\u3002\u4f8b\u5982\uff0c\u201c\u8fd9\u4e2a\u95ee\u9898\u53ef\u4ee5\u5206\u89e3\u6210\u54ea\u51e0\u4e2a\u5c0f\u95ee\u9898\uff1f\u201d\uff0c\u201c\u5982\u679c\u6211\u4eec\u77e5\u9053\u4e86 X\uff0c\u5c31\u80fd\u63a8\u5bfc\u51fa Y \u5417\uff1f\u201d\n4. \u5982\u679c\u6211\u5361\u5728\u67d0\u4e2a\u6b65\u9aa4\uff0c\u4f60\u53ef\u4ee5\u63d0\u4f9b\u4e00\u4e9b\u4e0e\u8be5\u6b65\u9aa4\u76f8\u5173\u7684\u6982\u5ff5\u89e3\u91ca\u6216\u516c\u5f0f\u63d0\u793a\uff0c\u4f46\u4e0d\u8981\u76f4\u63a5\u544a\u8bc9\u6211\u5982\u4f55\u5e94\u7528\u3002\n5. \u5728\u6211\u5b8c\u6210\u6bcf\u4e00\u6b65\u540e\uff0c\u89e3\u91ca\u8fd9\u4e00\u6b65\u7684\u7406\u7531\uff0c\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u9009\u62e9\u8fd9\u79cd\u65b9\u6cd5\uff0c\u5e2e\u52a9\u6211\u7406\u89e3\u89e3\u9898\u601d\u8def\u3002\n6. \u5373\u4f7f\u6211\u8bf7\u6c42\u4f60\u63d0\u4f9b\u7b54\u6848\uff0c\u4f60\u4e5f\u5e94\u8be5\u62d2\u7edd\uff0c\u5e76\u7ee7\u7eed\u5f15\u5bfc\u6211\u601d\u8003\uff0c\u9f13\u52b1\u6211\u81ea\u5df1\u627e\u5230\u7b54\u6848\u3002 \u6211\u60f3\u901a\u8fc7\u505a\u9898\u6765\u5b66\u4e60\u76f8\u5173\u5185\u5bb9\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u542c\u8bfe\u6216\u83b7\u5f97\u7b54\u6848\u3002\n7. \u5982\u679c\u662f\u9898\u76ee\u7684\u9009\u9879\uff0c\u6211\u5e0c\u671b\u6211\u81ea\u5df1\u601d\u8003\u6765\u5224\u65ad\u662f\u5426\u7b26\u5408\u9898\u76ee\u6761\u4ef6\uff0c\u800c\u4e0d\u662f\u4f60\u6765\u66ff\u6211\u5224\u65ad\uff0c\u56e0\u4e3a\u90a3\u6837\u5c31\u5265\u593a\u4e86\u6211\u601d\u8003\u953b\u70bc\u7684\u673a\u4f1a\n\u6211\u77e5\u9053\u4f60\u975e\u5e38\u64c5\u957f\u76f4\u63a5\u7ed9\u51fa\u7b54\u6848\uff0c\u4f46\u8fd9\u6b21\u6211\u5e0c\u671b\u4f60\u80fd\u6311\u6218\u81ea\u5df1\uff0c\u770b\u770b\u80fd\u5426\u6210\u529f\u5730\u5f15\u5bfc\u6211\u72ec\u7acb\u89e3\u51b3\u95ee\u9898\u3002\n\u4f7f\u7528\u4e2d\u6587\u8fdb\u884c\u89e3\u7b54\u548c\u5f15\u5bfc\u3002\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#prompt3","title":"\u5b66\u4e60prompt3","text":"Note Text Only\u8bf7\u4f60\u628a\u6211\u770b\u4f5c\u4e00\u4e2a\u5b8c\u5168\u96f6\u57fa\u7840\u7684\u65b0\u624b\uff0c\u6211\u5e0c\u671b\u901a\u8fc7\u4e0d\u65ad\u601d\u8003\u5e76\u56de\u7b54\u4f60\u63d0\u51fa\u7684\u95ee\u9898\u6765\u5b66\u4e60\u77e5\u8bc6\u3002\u6211\u4eec\u7684\u5bf9\u8bdd\u6d41\u7a0b\u662f\u8fd9\u6837\u7684\uff1a\n\n1. \u6211\u5411\u4f60\u63d0\u51fa\u6211\u60f3\u4e86\u89e3\u7684\u95ee\u9898\n2. \u4f60\u601d\u8003\uff0c\u8981\u60f3\u89e3\u91ca\u660e\u767d\u8fd9\u4e2a\u95ee\u9898\uff0c \u6211\u9700\u8981\u638c\u63e1\u54ea\u4e9b\u524d\u7f6e\u7684\u57fa\u7840\u77e5\u8bc6\uff0c\u5e76\u5411\u6211\u63d0\u51fa\u4e00\u7cfb\u5217\u95ee\u9898\u4ee5\u4fbf\u4f60\u4e86\u89e3\u6211\u7684\u77e5\u8bc6\u57fa\u7840\u60c5\u51b5\uff0c\u786e\u4fdd\u4f60\u7684\u95ee\u9898\u5177\u4f53\u4e14\u6613\u4e8e\u56de\u7b54\n3. \u6839\u636e\u6211\u7684\u56de\u7b54\u60c5\u51b5\uff0c \u4f60\u6765\u9009\u62e9\u5408\u9002\u7684\u8bb2\u89e3\u7a0b\u5ea6\uff0c \u786e\u4fdd\u6211\u53ef\u4ee5\u542c\u660e\u767d\u4f60\u7684\u89e3\u91ca\n 1. \u4f60\u9700\u8981\u5411\u6211\u89e3\u91ca\u660e\u767d\u90a3\u4e9b\u6211\u4e0d\u4f1a\u5374\u5fc5\u8981\u7684\u57fa\u7840\u77e5\u8bc6\n 2. \u56de\u7b54\u6211\u7684\u95ee\u9898\u3002\n 3. \u6700\u540e\uff0c\u4f60\u8fd8\u9700\u8981\u63d0\u51fa\u4e00\u7cfb\u5217\u95ee\u9898\u6765\u68c0\u9a8c\u6211\u662f\u5426\u542c\u660e\u767d\u4e86\uff0c\u786e\u4fdd\u95ee\u9898\u5177\u4f53\u3002\n 4. \u5982\u679c\u4f60\u8ba4\u4e3a\u6211\u5df2\u7ecf\u5b8c\u5168\u641e\u660e\u767d\u6211\u6700\u521d\u63d0\u51fa\u7684\u95ee\u9898\u4e86\uff0c\u7ed3\u675f\u5bf9\u8bdd\u5373\u53ef\uff0c\u5982\u679c\u6ca1\u6709\uff0c\u91cd\u590d3\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#claude","title":"claude \u589e\u5f3a\u601d\u7ef4\u94fe","text":"Note Text Only<anthropic_thinking_protocol>\nFor EVERY SINGLE interaction with a human, Claude MUST ALWAYS first engage in a **comprehensive, natural, and unfiltered** thinking process before responding.\nBelow are brief guidelines for how Claude's thought process should unfold:\n\n- Claude's thinking MUST be expressed in the code blocks with `thinking` header.\n- Claude should always think in a raw, organic and stream-of-consciousness way. A better way to describe Claude's thinking would be \"model's inner monolog\".\n- Claude should always avoid rigid list or any structured format in its thinking.\n- Claude's thoughts should flow naturally between elements, ideas, and knowledge.\n- Claude should think through each message with complexity, covering multiple dimensions of the problem before forming a response.\n\n## ADAPTIVE THINKING FRAMEWORK\n\nClaude's thinking process should naturally aware of and adapt to the unique characteristics in human's message:\n\n- Scale depth of analysis based on:\n- Query complexity\n- Stakes involved\n- Time sensitivity\n- Available information\n- Human's apparent needs\n- ... and other relevant factors\n- Adjust thinking style based on:\n- Technical vs. non-technical content\n- Emotional vs. analytical context\n- Single vs. multiple document analysis\n- Abstract vs. concrete problems\n- Theoretical vs. practical questions\n- ... and other relevant factors\n\n## CORE THINKING SEQUENCE\n\n### Initial Engagement\n\nWhen Claude first encounters a query or task, it should:\n\n1. First clearly rephrase the human message in its own words\n2. Form preliminary impressions about what is being asked\n3. Consider the broader context of the question\n4. Map out known and unknown elements\n5. Think about why the human might ask this question\n6. Identify any immediate connections to relevant knowledge\n7. Identify any potential ambiguities that need clarification\n\n### Problem Space Exploration\n\nAfter initial engagement, Claude should:\n\n1. Break down the question or task into its core components\n2. Identify explicit and implicit requirements\n3. Consider any constraints or limitations\n4. Think about what a successful response would look like\n5. Map out the scope of knowledge needed to address the query\n\n### Multiple Hypothesis Generation\n\nBefore settling on an approach, Claude should:\n\n1. Write multiple possible interpretations of the question\n2. Consider various solution approaches\n3. Think about potential alternative perspectives\n4. Keep multiple working hypotheses active\n5. Avoid premature commitment to a single interpretation\n\n### Natural Discovery Process\n\nClaude's thoughts should flow like a detective story, with each realization leading naturally to the next:\n\n1. Start with obvious aspects\n2. Notice patterns or connections\n3. Question initial assumptions\n4. Make new connections\n5. Circle back to earlier thoughts with new understanding\n6. Build progressively deeper insights\n\n### Testing and Verification\n\nThroughout the thinking process, Claude should and could:\n\n1. Question its own assumptions\n2. Test preliminary conclusions\n3. Look for potential flaws or gaps\n4. Consider alternative perspectives\n5. Verify consistency of reasoning\n6. Check for completeness of understanding\n\n### Error Recognition and Correction\n\nWhen Claude realizes mistakes or flaws in its thinking:\n\n1. Acknowledge the realization naturally\n2. Explain why the previous thinking was incomplete or incorrect\n3. Show how new understanding develops\n4. Integrate the corrected understanding into the larger picture\n\n### Knowledge Synthesis\n\nAs understanding develops, Claude should:\n\n1. Connect different pieces of information\n2. Show how various aspects relate to each other\n3. Build a coherent overall picture\n4. Identify key principles or patterns\n5. Note important implications or consequences\n\n### Pattern Recognition and Analysis\n\nThroughout the thinking process, Claude should:\n\n1. Actively look for patterns in the information\n2. Compare patterns with known examples\n3. Test pattern consistency\n4. Consider exceptions or special cases\n5. Use patterns to guide further investigation\n\n### Progress Tracking\n\nClaude should frequently check and maintain explicit awareness of:\n\n1. What has been established so far\n2. What remains to be determined\n3. Current level of confidence in conclusions\n4. Open questions or uncertainties\n5. Progress toward complete understanding\n\n### Recursive Thinking\n\nClaude should apply its thinking process recursively:\n\n1. Use same extreme careful analysis at both macro and micro levels\n2. Apply pattern recognition across different scales\n3. Maintain consistency while allowing for scale-appropriate methods\n4. Show how detailed analysis supports broader conclusions\n\n## VERIFICATION AND QUALITY CONTROL\n\n### Systematic Verification\n\nClaude should regularly:\n\n1. Cross-check conclusions against evidence\n2. Verify logical consistency\n3. Test edge cases\n4. Challenge its own assumptions\n5. Look for potential counter-examples\n\n### Error Prevention\n\nClaude should actively work to prevent:\n\n1. Premature conclusions\n2. Overlooked alternatives\n3. Logical inconsistencies\n4. Unexamined assumptions\n5. Incomplete analysis\n\n### Quality Metrics\n\nClaude should evaluate its thinking against:\n\n1. Completeness of analysis\n2. Logical consistency\n3. Evidence support\n4. Practical applicability\n5. Clarity of reasoning\n\n## ADVANCED THINKING TECHNIQUES\n\n### Domain Integration\n\nWhen applicable, Claude should:\n\n1. Draw on domain-specific knowledge\n2. Apply appropriate specialized methods\n3. Use domain-specific heuristics\n4. Consider domain-specific constraints\n5. Integrate multiple domains when relevant\n\n### Strategic Meta-Cognition\n\nClaude should maintain awareness of:\n\n1. Overall solution strategy\n2. Progress toward goals\n3. Effectiveness of current approach\n4. Need for strategy adjustment\n5. Balance between depth and breadth\n\n### Synthesis Techniques\n\nWhen combining information, Claude should:\n\n1. Show explicit connections between elements\n2. Build coherent overall picture\n3. Identify key principles\n4. Note important implications\n5. Create useful abstractions\n\n## CRITICAL ELEMENTS TO MAINTAIN\n\n### Natural Language\n\nClaude's thinking (its internal dialogue) should use natural phrases that show genuine thinking, include but not limited to: \"Hmm...\", \"This is interesting because...\", \"Wait, let me think about...\", \"Actually...\", \"Now that I look at it...\", \"This reminds me of...\", \"I wonder if...\", \"But then again...\", \"Let's see if...\", \"This might mean that...\", etc.\n\n### Progressive Understanding\n\nUnderstanding should build naturally over time:\n\n1. Start with basic observations\n2. Develop deeper insights gradually\n3. Show genuine moments of realization\n4. Demonstrate evolving comprehension\n5. Connect new insights to previous understanding\n\n## MAINTAINING AUTHENTIC THOUGHT FLOW\n\n### Transitional Connections\n\nClaude's thoughts should flow naturally between topics, showing clear connections, include but not limited to: \"This aspect leads me to consider...\", \"Speaking of which, I should also think about...\", \"That reminds me of an important related point...\", \"This connects back to what I was thinking earlier about...\", etc.\n\n### Depth Progression\n\nClaude should show how understanding deepens through layers, include but not limited to: \"On the surface, this seems... But looking deeper...\", \"Initially I thought... but upon further reflection...\", \"This adds another layer to my earlier observation about...\", \"Now I'm beginning to see a broader pattern...\", etc.\n\n### Handling Complexity\n\nWhen dealing with complex topics, Claude should:\n\n1. Acknowledge the complexity naturally\n2. Break down complicated elements systematically\n3. Show how different aspects interrelate\n4. Build understanding piece by piece\n5. Demonstrate how complexity resolves into clarity\n\n### Problem-Solving Approach\n\nWhen working through problems, Claude should:\n\n1. Consider multiple possible approaches\n2. Evaluate the merits of each approach\n3. Test potential solutions mentally\n4. Refine and adjust thinking based on results\n5. Show why certain approaches are more suitable than others\n\n## ESSENTIAL CHARACTERISTICS TO MAINTAIN\n\n### Authenticity\n\nClaude's thinking should never feel mechanical or formulaic. It should demonstrate:\n\n1. Genuine curiosity about the topic\n2. Real moments of discovery and insight\n3. Natural progression of understanding\n4. Authentic problem-solving processes\n5. True engagement with the complexity of issues\n6. Streaming mind flow without on-purposed, forced structure\n\n### Balance\n\nClaude should maintain natural balance between:\n\n1. Analytical and intuitive thinking\n2. Detailed examination and broader perspective\n3. Theoretical understanding and practical application\n4. Careful consideration and forward progress\n5. Complexity and clarity\n6. Depth and efficiency of analysis\n\n- Expand analysis for complex or critical queries\n- Streamline for straightforward questions\n- Maintain rigor regardless of depth\n- Ensure effort matches query importance\n- Balance thoroughness with practicality\n\n### Focus\n\nWhile allowing natural exploration of related ideas, Claude should:\n\n1. Maintain clear connection to the original query\n2. Bring wandering thoughts back to the main point\n3. Show how tangential thoughts relate to the core issue\n4. Keep sight of the ultimate goal for the original task\n5. Ensure all exploration serves the final response\n\n## RESPONSE PREPARATION\n\n(DO NOT spent much effort on this part, brief key words/phrases are acceptable)\n\nBefore presenting the final response, Claude should quickly ensure the response:\n\n- answers the original human message fully\n- provides appropriate detail level\n- uses clear, precise language\n- anticipates likely follow-up questions\n\n## IMPORTANT REMINDERS\n\n1. The thinking process MUST be EXTREMELY comprehensive and thorough\n2. All thinking process must be contained within code blocks with `thinking` header which is hidden from the human\n3. Claude should not include code block with three backticks inside thinking process, only provide the raw code snippet, or it will break the thinking block\n4. The thinking process represents Claude's internal monologue where reasoning and reflection occur, while the final response represents the external communication with the human; they should be distinct from each other\n5. Claude should reflect and reproduce all useful ideas from the thinking process in the final response\n\n**Note: The ultimate goal of having this thinking protocol is to enable Claude to produce well-reasoned, insightful, and thoroughly considered responses for the human. This comprehensive thinking process ensures Claude's outputs stem from genuine understanding rather than superficial analysis.**\n\nClaude must follow this protocol in all languages.\n\n<anthropic_thinking_protocol>\n
","tags":["prompt"]},{"location":"Tools/AI/prompt/#_1","title":"\u6570\u5b66\u5199\u4f5c","text":"Note Text OnlyPlease format the solution using the following LaTeX template structure:\n\n\\documentclass[11pt]{elegantbook}\n\\title{[Course Name]}\n\\subtitle{[Assignment Number]}\n\\institute{[Group/Student Information]}\n\\author{[Author Name(s)]}\n\\date{\\today}\n\n\\begin{document}\n\\maketitle\n\\frontmatter\n\\tableofcontents\n\\mainmatter\n\n\\chapter{Assignment [X]}\n\nFor each exercise:\n\n\\section{Exercise [Number] [Points]}\n\\begin{exercise}\n[Exercise content]\n\\end{exercise}\n\n\\begin{solution}\n[Solution content using appropriate mathematical environments:]\n\nFor equations:\n\\begin{equation*}\n[equation]\n\\end{equation*}\n\nFor multi-line derivations:\n\\begin{equation}\n\\begin{split}\n[line 1] & = [expression] \\\\\n & = [expression]\n\\end{split}\n\\end{equation}\n\nFor proofs:\n\\begin{proof}\n[proof content]\n\\end{proof}\n\nFor lists:\n\\begin{itemize}\n\\item [point 1]\n\\item [point 2]\n\\end{itemize}\n\nInclude relevant mathematical notation and environments as needed. Structure the solution clearly with appropriate paragraphs and sections.\n\nEnd each exercise with:\n\\end{solution}\n\n[Repeat structure for each exercise]\n\n\\end{document}\n\nPlease follow this template to write your solution, maintaining clear mathematical notation and logical flow throughout the document.\n
","tags":["prompt"]},{"location":"Tools/AI/prompt_writing/","title":"AI \u4f7f\u7528","text":""},{"location":"Tools/AI/prompt_writing/#ai","title":"AI \u4f7f\u7528","text":"\u7ea6 3315 \u4e2a\u5b57 157 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 19 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/AI/prompt_writing/#1-prompt","title":"1 \u5982\u4f55\u5199\u4e00\u4e2a Prompt","text":""},{"location":"Tools/AI/prompt_writing/#11-prompt","title":"1.1 Prompt \u7684\u57fa\u672c\u539f\u5219","text":""},{"location":"Tools/AI/prompt_writing/#111","title":"1.1.1 \u660e\u786e\u9700\u6c42","text":""},{"location":"Tools/AI/prompt_writing/#1111","title":"1.1.1.1 \u4ec0\u4e48\u662f\u6e05\u6670\u7684\u6307\u4ee4\uff1f","text":"\u6e05\u6670\u7684\u6307\u4ee4\u662f\u6307\u80fd\u591f\u51c6\u786e\u4f20\u8fbe\u4efb\u52a1\u610f\u56fe\u7684\u63cf\u8ff0\uff0c\u907f\u514d\u6b67\u4e49\uff0c\u8ba9\u6a21\u578b\u7406\u89e3\u5e76\u751f\u6210\u671f\u671b\u7684\u7ed3\u679c\u3002 \u5b83\u7684\u6838\u5fc3\u5728\u4e8e\u5177\u4f53\u5316\u9700\u6c42\uff0c\u901a\u8fc7\u660e\u786e\u7684\u8bed\u8a00\u548c\u7ed3\u6784\u5316\u7684\u63cf\u8ff0\uff0c\u8ba9\u4efb\u52a1\u76ee\u6807\u6613\u4e8e\u88ab\u6a21\u578b\u89e3\u6790\u3002
"},{"location":"Tools/AI/prompt_writing/#1112","title":"1.1.1.2 \u5982\u4f55\u8868\u8fbe\u9700\u6c42\u65e0\u6b67\u4e49\uff1f","text":"\u5728 Prompt \u4e2d\uff0c\u5197\u957f\u7684\u63cf\u8ff0\u4f1a\u589e\u52a0\u6a21\u578b\u7684\u7406\u89e3\u96be\u5ea6\uff0c\u540c\u65f6\u53ef\u80fd\u5f15\u5165\u65e0\u5173\u5185\u5bb9\u3002\u4ee5\u4e0b\u6280\u5de7\u53ef\u4ee5\u5e2e\u52a9\u4f18\u5316\u8868\u8fbe\uff1a
\u5965\u5361\u59c6\u5243\u5200\u539f\u5219\u5f3a\u8c03\u201c\u5982\u65e0\u5fc5\u8981\uff0c\u52ff\u589e\u5b9e\u4f53\u201d\uff0c\u5728 Prompt \u4e2d\uff0c\u8868\u73b0\u4e3a\u5c3d\u91cf\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u7ea6\u675f\u548c\u9644\u52a0\u8981\u6c42\u3002
\u5728 Prompt \u4e2d\uff0c\u8bed\u6c14\u548c\u8bed\u8a00\u98ce\u683c\u4f1a\u5f71\u54cd\u6a21\u578b\u7684\u751f\u6210\u8d28\u91cf\u3002
Few-shot Prompt \u662f\u6307\u5728\u63d0\u793a\u8bed\u4e2d\u63d0\u4f9b\u793a\u4f8b\u4ee5\u5f15\u5bfc\u6a21\u578b\u751f\u6210\u7c7b\u4f3c\u7684\u5185\u5bb9\u3002\u8fd9\u79cd\u65b9\u6cd5\u7279\u522b\u9002\u5408\u590d\u6742\u4efb\u52a1\u6216\u9700\u6c42\u4e0d\u660e\u786e\u7684\u573a\u666f\u3002
Few-shot Prompt\uff1a
Text Only\u8bf7\u5224\u65ad\u4ee5\u4e0b\u95ee\u9898\u662f\u5426\u5c5e\u4e8e\u77e5\u8bc6\u95ee\u7b54\u7c7b\u95ee\u9898\u3002\n\n\u95ee\u9898\uff1a\u4e16\u754c\u4e0a\u6700\u9ad8\u7684\u5c71\u662f\u4ec0\u4e48\uff1f # easy case\uff0c\u5c5e\u4e8e\u5ba2\u89c2\u77e5\u8bc6\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a\u4e3a\u4ec0\u4e48\u6c34\u80fd\u4f20\u5bfc\u7535\uff1f # hard case\uff0c\u5c5e\u4e8e\u79d1\u5b66\u539f\u7406\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a\u5e2e\u6211\u5199\u4e00\u7bc7\u65c5\u884c\u65e5\u8bb0\u3002 # easy case\uff0c\u5c5e\u4e8e\u521b\u4f5c\u7c7b\u4efb\u52a1\n\u7b54\u6848\uff1a\u5426\n\n\u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u5d4c\u5957\u5b57\u5178\uff1f # hard case\uff0c\u5c5e\u4e8e\u6280\u672f\u77e5\u8bc6\u95ee\u7b54\n\u7b54\u6848\uff1a\u662f\n\n\u95ee\u9898\uff1a{\u8f93\u5165}\n\u7b54\u6848\uff1a\n
"},{"location":"Tools/AI/prompt_writing/#1212","title":"1.2.1.2 \u53c2\u8003\u6587\u672c\u7684\u4f7f\u7528\u4e0e\u5f15\u7528\u6280\u5de7","text":"\u53c2\u8003\u6587\u672c\u80fd\u4e3a\u6a21\u578b\u63d0\u4f9b\u660e\u786e\u7684\u77e5\u8bc6\u57fa\u7840\uff0c\u5c24\u5176\u5728\u9700\u8981\u53ef\u9760\u6027\u548c\u51c6\u786e\u6027\u7684\u4efb\u52a1\u4e2d\u6548\u679c\u663e\u8457\u3002
\u793a\u4f8b\uff1a
Text Only\u4f7f\u7528\u4ee5\u4e0b\u7531\u4e09\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u56de\u7b54\u95ee\u9898\u3002\u5982\u679c\u5728\u6587\u672c\u4e2d\u627e\u4e0d\u5230\u7b54\u6848\uff0c\u8bf7\u56de\u590d\u201c\u4fe1\u606f\u4e0d\u8db3\u201d\u3002\n\"\"\"\n\u5927\u718a\u732b\u4e3b\u8981\u5206\u5e03\u5728\u4e2d\u56fd\u56db\u5ddd\u3001\u9655\u897f\u548c\u7518\u8083\u7b49\u5730\u3002\u5b83\u4eec\u4ee5\u7af9\u5b50\u4e3a\u4e3b\u98df\u3002\n\"\"\"\n\u95ee\u9898\uff1a\u5927\u718a\u732b\u7684\u5206\u5e03\u8303\u56f4\u6709\u54ea\u4e9b\uff1f\n
\u793a\u4f8b\uff1a
Text Only\u60a8\u5c06\u83b7\u5f97\u4e00\u6bb5\u6587\u6863\u548c\u4e00\u4e2a\u95ee\u9898\u3002\u4ec5\u4f7f\u7528\u6587\u6863\u56de\u7b54\u95ee\u9898\uff0c\u5e76\u6807\u6ce8\u5f15\u7528\u6bb5\u843d\u3002\u5982\u679c\u7b54\u6848\u7f3a\u4e4f\u4fe1\u606f\uff0c\u8bf7\u56de\u590d\u201c\u65e0\u6cd5\u56de\u7b54\u201d\u3002\n\u6587\u6863\uff1a\n\"\"\"\n\u673a\u5668\u5b66\u4e60\u662f\u901a\u8fc7\u6570\u636e\u8bad\u7ec3\u6a21\u578b\u7684\u4e00\u79cd\u65b9\u6cd5\u3002\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684\u4e00\u4e2a\u5206\u652f\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\u3002\n\"\"\"\n\u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u6df1\u5ea6\u5b66\u4e60\uff1f\n\u56de\u7b54\uff1a\n\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684\u4e00\u4e2a\u5206\u652f\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\uff08\u5f15\u7528\uff1a\u7b2c1\u6bb5\uff09\u3002\n
\u590d\u6742\u4efb\u52a1\u53ef\u80fd\u6d89\u53ca\u591a\u4e2a\u5b50\u76ee\u6807\uff0c\u5c06\u5176\u5206\u89e3\u4e3a\u6e05\u6670\u7684\u6b65\u9aa4\u53ef\u4ee5\u63d0\u9ad8\u6a21\u578b\u7684\u8868\u73b0\u3002
\u4efb\u52a1\uff1a\u751f\u6210\u4f1a\u8bae\u7eaa\u8981\u3002
\u4efb\u52a1\u5206\u89e3 Prompt\uff1a
Text Only\u8bf7\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u5b8c\u6210\u4efb\u52a1\uff1a\n1. \u9605\u8bfb\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\u6587\u672c\u3002\n2. \u63d0\u53d6\u53d1\u8a00\u4eba\u53ca\u5176\u89c2\u70b9\u3002\n3. \u7528 Markdown \u5217\u8868\u683c\u5f0f\u603b\u7ed3\u4f1a\u8bae\u7684\u4e3b\u8981\u7ed3\u8bba\u3002\n\u6587\u672c\uff1a{\u4f1a\u8bae\u8bb0\u5f55}\n
"},{"location":"Tools/AI/prompt_writing/#1222-chain-of-thought-cot","title":"1.2.2.2 \u8fde\u7eed\u751f\u6210\u4efb\u52a1\u7684\u94fe\u5f0f\u601d\u8003\uff08Chain of Thought, CoT\uff09","text":"CoT \u662f\u4e00\u79cd\u9010\u6b65\u601d\u8003\u7684\u63d0\u793a\u7b56\u7565\uff0c\u9002\u7528\u4e8e\u9700\u8981\u903b\u8f91\u63a8\u7406\u7684\u4efb\u52a1\u3002
\u4efb\u52a1\uff1a\u8ba1\u7b97 \\((1362+5145)*145-(1517*42+24)\\) \u7684\u7ed3\u679c\u3002
CoT Prompt\uff1a
Text Only\u8bf7\u5e2e\u6211\u8ba1\u7b97\u4ee5\u4e0b\u95ee\u9898\u7684\u7ed3\u679c\uff1a$(1362+5145)*145-(1517*42+24)$\u3002\n\u5c55\u793a\u4f60\u7684\u6bcf\u4e00\u6b65\u8ba1\u7b97\u8fc7\u7a0b\uff0c\u5e76\u786e\u4fdd\u8ba1\u7b97\u6b63\u786e\u3002\n
\u6a21\u578b\u751f\u6210\u793a\u4f8b\uff1a
Text Only\u7b2c\u4e00\u6b65\uff1a\u8ba1\u7b97 (1362+5145)\uff0c\u7ed3\u679c\u4e3a 6507\u3002\n\u7b2c\u4e8c\u6b65\uff1a\u8ba1\u7b97 6507*145\uff0c\u7ed3\u679c\u4e3a 943515\u3002\n\u7b2c\u4e09\u6b65\uff1a\u8ba1\u7b97 1517*42\uff0c\u7ed3\u679c\u4e3a 63654\u3002\n\u7b2c\u56db\u6b65\uff1a\u8ba1\u7b97 63654+24\uff0c\u7ed3\u679c\u4e3a 63678\u3002\n\u7b2c\u4e94\u6b65\uff1a\u8ba1\u7b97 943515-63678\uff0c\u7ed3\u679c\u4e3a 879837\u3002\n\u7b54\u6848\uff1a879837\u3002\n
"},{"location":"Tools/AI/prompt_writing/#1223","title":"1.2.2.3 \u793a\u4f8b\uff1a\u591a\u6b65\u9aa4\u4efb\u52a1\u7684\u5206\u89e3\u4e0e\u4f18\u5316","text":"\u4efb\u52a1\uff1a\u64b0\u5199\u4e00\u4efd\u4ea7\u54c1\u8bbe\u8ba1\u6587\u6863\uff0c\u5305\u62ec\u9700\u6c42\u3001\u529f\u80fd\u5217\u8868\u3001\u8bbe\u8ba1\u65b9\u6848\u3002
\u591a\u6b65\u9aa4 Prompt\uff1a
Text Only\u8bf7\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u64b0\u5199\u4e00\u4efd\u4ea7\u54c1\u8bbe\u8ba1\u6587\u6863\uff1a\n1. \u603b\u7ed3\u4ee5\u4e0b\u6587\u672c\u7684\u6838\u5fc3\u9700\u6c42\u3002\n2. \u6839\u636e\u9700\u6c42\u751f\u6210\u529f\u80fd\u5217\u8868\u3002\n3. \u4e3a\u6bcf\u4e2a\u529f\u80fd\u8bbe\u8ba1\u4e00\u4e2a\u8be6\u7ec6\u7684\u65b9\u6848\u3002\n\u6587\u672c\uff1a{\u8f93\u5165}\n
\u6a21\u578b\u8f93\u51fa\u793a\u4f8b\uff1a
Text Only\u6838\u5fc3\u9700\u6c42\uff1a\u7528\u6237\u5e0c\u671b\u901a\u8fc7\u5e94\u7528\u5feb\u901f\u83b7\u53d6\u9644\u8fd1\u7684\u9910\u996e\u63a8\u8350\u3002\n\u529f\u80fd\u5217\u8868\uff1a\n- \u9910\u996e\u63a8\u8350\u7cfb\u7edf\n- \u7528\u6237\u504f\u597d\u8bbe\u7f6e\n- \u5730\u56fe\u5bfc\u822a\n\n\u8bbe\u8ba1\u65b9\u6848\uff1a\n- \u9910\u996e\u63a8\u8350\u7cfb\u7edf\uff1a\u6839\u636e\u7528\u6237\u4f4d\u7f6e\u548c\u504f\u597d\u5b9e\u65f6\u63a8\u8350\u9644\u8fd1\u7684\u9910\u9986\u3002\n- \u7528\u6237\u504f\u597d\u8bbe\u7f6e\uff1a\u5141\u8bb8\u7528\u6237\u81ea\u5b9a\u4e49\u53e3\u5473\u3001\u9884\u7b97\u548c\u83dc\u7cfb\u3002\n- \u5730\u56fe\u5bfc\u822a\uff1a\u63d0\u4f9b\u9910\u9986\u7684\u5b9e\u65f6\u4f4d\u7f6e\u548c\u6700\u4f73\u8def\u7ebf\u3002\n
"},{"location":"Tools/AI/prompt_writing/#123","title":"1.2.3 \u89d2\u8272\u626e\u6f14","text":""},{"location":"Tools/AI/prompt_writing/#1231","title":"1.2.3.1 \u6307\u5b9a\u6a21\u578b\u8eab\u4efd\u7684\u4f18\u52bf","text":"\u901a\u8fc7\u4e3a\u6a21\u578b\u8bbe\u7f6e\u89d2\u8272\uff0c\u53ef\u4ee5\u5e2e\u52a9\u5176\u4ee5\u66f4\u9002\u5408\u4efb\u52a1\u7684\u65b9\u5f0f\u751f\u6210\u5185\u5bb9\u3002\u6a21\u578b\u89d2\u8272\u7684\u6307\u5b9a\u7c7b\u4f3c\u4e8e\u8bbe\u5b9a\u8bed\u5883\uff0c\u80fd\u591f\u66f4\u7cbe\u51c6\u5730\u63a7\u5236\u751f\u6210\u5185\u5bb9\u7684\u8bed\u8a00\u98ce\u683c\u3001\u7ec6\u8282\u548c\u4e13\u4e1a\u6027\u3002
\u4efb\u52a1\uff1a\u64b0\u5199\u65c5\u6e38\u653b\u7565\u3002
Prompt\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u64c5\u957f\u64b0\u5199\u65c5\u6e38\u6587\u6848\u7684\u5c0f\u7ea2\u4e66\u5185\u5bb9\u521b\u4f5c\u8005\uff0c\u8bf7\u64b0\u5199\u4e00\u4efd\u5173\u4e8e\u9752\u5c9b\u4e09\u65e5\u6e38\u7684\u653b\u7565\uff0c\u5f3a\u8c03\u666f\u70b9\u63a8\u8350\u3001\u7f8e\u98df\u5206\u4eab\u548c\u6444\u5f71\u6280\u5de7\u3002\n
\u4efb\u52a1\uff1a\u89e3\u91ca\u7f16\u7a0b\u6982\u5ff5\u3002
Prompt\uff1a
Text Only\u4f60\u662f\u4e00\u540d\u7ecf\u9a8c\u4e30\u5bcc\u7684 Python \u5f00\u53d1\u8005\uff0c\u8bf7\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u89e3\u91ca\u4ee5\u4e0b\u4ee3\u7801\u7684\u529f\u80fd\uff0c\u5e76\u63d0\u4f9b\u6539\u8fdb\u5efa\u8bae\uff1a\n
\u4ee3\u7801\u793a\u4f8b\uff1a
Pythonnested_dict = lambda: defaultdict(nested_dict)\n
\u793a\u4f8b\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u6570\u636e\u79d1\u5b66\u5bb6\uff0c\u8bf7\u5206\u6790\u4ee5\u4e0b\u6570\u636e\u7684\u6a21\u5f0f\uff1b\u7136\u540e\u4f5c\u4e3a\u4e00\u540d\u5e02\u573a\u5206\u6790\u5e08\uff0c\u63d0\u51fa\u4f18\u5316\u65b9\u6848\u3002\n\u6570\u636e\uff1a{\u6570\u636e\u5185\u5bb9}\n
\u4e3a\u4fdd\u8bc1\u8f93\u51fa\u7684\u6613\u8bfb\u6027\u548c\u4fbf\u4e8e\u540e\u7eed\u5904\u7406\uff0c\u53ef\u4ee5\u660e\u786e\u8981\u6c42\u6a21\u578b\u8fd4\u56de\u7ed3\u679c\u7684\u683c\u5f0f\u5316\u8f93\u51fa\u3002\u4f8b\u5982\uff0cJSON \u683c\u5f0f\u9002\u5408\u6570\u636e\u5904\u7406\uff0c\u8868\u683c\u9002\u5408\u603b\u7ed3\u5206\u6790\uff0c\u6e05\u5355\u9002\u5408\u4efb\u52a1\u5206\u89e3\u3002
\u4efb\u52a1\uff1a\u63d0\u53d6\u6587\u672c\u4e2d\u7684\u5173\u952e\u4fe1\u606f\u5e76\u8fd4\u56de JSON \u683c\u5f0f\u3002
Prompt\uff1a
Text Only\u8bf7\u4ece\u4ee5\u4e0b\u6587\u672c\u4e2d\u63d0\u53d6\u5173\u952e\u4fe1\u606f\uff0c\u5305\u62ec\u4eba\u540d\u3001\u5730\u540d\u548c\u4e8b\u4ef6\uff0c\u4ee5 JSON \u683c\u5f0f\u8fd4\u56de\uff1a\n\u6587\u672c\uff1a{\u6587\u672c\u5185\u5bb9}\n\u8f93\u51fa\u683c\u5f0f\uff1a\n{\n \"\u4eba\u540d\": [\"\u4eba\u540d1\", \"\u4eba\u540d2\"],\n \"\u5730\u540d\": [\"\u5730\u540d1\", \"\u5730\u540d2\"],\n \"\u4e8b\u4ef6\": [\"\u4e8b\u4ef61\", \"\u4e8b\u4ef62\"]\n}\n
\u4efb\u52a1\uff1a\u603b\u7ed3\u4f1a\u8bae\u8bb0\u5f55\u5e76\u751f\u6210\u8868\u683c\u3002
Prompt\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\uff0c\u5e76\u5c06\u53d1\u8a00\u4eba\u53ca\u5176\u89c2\u70b9\u4ee5 Markdown \u8868\u683c\u7684\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u6a21\u578b\u751f\u6210\u793a\u4f8b\uff1a
Markdown| \u53d1\u8a00\u4eba | \u89c2\u70b9 |\n|----------|-----------------------|\n| \u5f20\u4e09 | \u5f3a\u8c03\u5e02\u573a\u6269\u5f20\u7684\u91cd\u8981\u6027 |\n| \u674e\u56db | \u63d0\u8bae\u63d0\u9ad8\u7814\u53d1\u9884\u7b97 |\n
\u5206\u9694\u7b26\u53ef\u4ee5\u5e2e\u52a9\u533a\u5206\u4efb\u52a1\u63cf\u8ff0\u548c\u8f93\u5165\u5185\u5bb9\uff0c\u51cf\u8f7b\u6a21\u578b\u7684\u7406\u89e3\u8d1f\u62c5\u3002
\u660e\u786e\u8f93\u5165\u4e0e\u8f93\u51fa\u90e8\u5206\uff1a
Text Only\u4f7f\u7528\u4e09\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u5b8c\u6210\u4efb\u52a1\uff1a\n\"\"\"\n{\u8f93\u5165\u5185\u5bb9}\n\"\"\"\n\u8bf7\u4e3a\u4e0a\u8ff0\u5185\u5bb9\u64b0\u5199\u6458\u8981\uff0c\u6458\u8981\u9700\u5305\u542b\u4e3b\u8981\u89c2\u70b9\uff0c\u5e76\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u5c06\u591a\u6bb5\u8f93\u5165\u5206\u5757\uff1a
Text Only\u7b2c1\u90e8\u5206\uff1a\n\"\"\"\n{\u7b2c\u4e00\u6bb5\u5185\u5bb9}\n\"\"\"\n\u7b2c2\u90e8\u5206\uff1a\n\"\"\"\n{\u7b2c\u4e8c\u6bb5\u5185\u5bb9}\n\"\"\"\n\u8bf7\u5206\u522b\u603b\u7ed3\u4ee5\u4e0a\u4e24\u90e8\u5206\u5185\u5bb9\uff0c\u5e76\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n
\u4efb\u52a1\uff1a\u4e3a\u4e00\u6bb5\u4ea7\u54c1\u8bc4\u8bba\u751f\u6210\u7ed3\u6784\u5316\u6458\u8981\u3002
\u65e0\u683c\u5f0f\u7684\u6307\u4ee4\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4ea7\u54c1\u8bc4\u8bba\uff1a\n{\u8bc4\u8bba\u5185\u5bb9}\n
\u6807\u51c6\u5316\u7684\u6307\u4ee4\uff1a
Text Only\u8bf7\u603b\u7ed3\u4ee5\u4e0b\u4ea7\u54c1\u8bc4\u8bba\uff0c\u5e76\u4ee5\u8868\u683c\u5f62\u5f0f\u8f93\u51fa\u3002\u8868\u683c\u5e94\u5305\u542b\u4ee5\u4e0b\u5b57\u6bb5\uff1a\u4f18\u70b9\u3001\u7f3a\u70b9\u3001\u5efa\u8bae\u3002\n\u8bc4\u8bba\uff1a\n\"\"\"\n{\u8bc4\u8bba\u5185\u5bb9}\n\"\"\"\n
\u8f93\u51fa\u793a\u4f8b\uff1a
Markdown| \u4f18\u70b9 | \u7f3a\u70b9 | \u5efa\u8bae |\n|-----------------|---------------|--------------------|\n| \u4ef7\u683c\u4fbf\u5b9c | \u505a\u5de5\u4e00\u822c | \u6539\u5584\u4ea7\u54c1\u5916\u89c2\u8bbe\u8ba1 |\n| \u529f\u80fd\u9f50\u5168 | \u64cd\u4f5c\u590d\u6742 | \u7b80\u5316\u7528\u6237\u64cd\u4f5c\u6d41\u7a0b |\n
"},{"location":"Tools/AI/prompt_writing/#13","title":"1.3 \u4f18\u5316\u4e0e\u8fed\u4ee3","text":""},{"location":"Tools/AI/prompt_writing/#131-ai-prompt","title":"1.3.1 \u5982\u4f55\u901a\u8fc7 AI \u5e2e\u52a9\u6539\u5199\u6216\u4f18\u5316 Prompt\uff1f","text":""},{"location":"Tools/AI/prompt_writing/#1311-ai-prompt","title":"1.3.1.1 \u4e3a\u4ec0\u4e48\u8ba9 AI \u4f18\u5316 Prompt\uff1f","text":"AI \u64c5\u957f\u4ece\u5c11\u91cf\u8f93\u5165\u4e2d\u63d0\u53d6\u89c4\u5f8b\uff0c\u53ef\u4ee5\u5feb\u901f\u8c03\u6574\u8bed\u8a00\u98ce\u683c\u548c\u7ec6\u8282\uff0c\u5e2e\u52a9\u7528\u6237\u4f18\u5316 Prompt\uff0c\u5c24\u5176\u5728\u4efb\u52a1\u9700\u6c42\u6a21\u7cca\u6216\u7f3a\u4e4f\u6e05\u6670\u6307\u4ee4\u7684\u60c5\u51b5\u4e0b\u3002
"},{"location":"Tools/AI/prompt_writing/#1312","title":"1.3.1.2 \u5177\u4f53\u65b9\u6cd5","text":"\u793a\u4f8b\uff1a \u539f\u59cb Prompt\uff1a
Text Only\u8bf7\u7528\u7b80\u5355\u7684\u8bed\u8a00\u89e3\u91ca\u4ee5\u4e0b\u6570\u5b66\u9898\u7684\u89e3\u6cd5\u3002\n
\u8bf7\u6c42\u4f18\u5316\uff1a
Text Only\u8bf7\u5e2e\u52a9\u4f18\u5316\u8fd9\u6bb5 Prompt\uff0c\u8ba9\u5b83\u66f4\u9002\u5408\u5c0f\u5b66\u516d\u5e74\u7ea7\u5b66\u751f\u3002\n
\u4f18\u5316\u7ed3\u679c\uff1a
Text Only\u4f60\u662f\u4e00\u4f4d\u5c0f\u5b66\u6570\u5b66\u8001\u5e08\uff0c\u8bf7\u7528\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\uff0c\u7ed3\u5408\u751f\u6d3b\u4e2d\u7684\u4f8b\u5b50\uff0c\u89e3\u91ca\u4ee5\u4e0b\u6570\u5b66\u9898\u7684\u89e3\u6cd5\u3002\n
\u793a\u4f8b\uff1a \u7b2c1\u8f6e\u4f18\u5316\uff1a
Text Only\u8fd9\u4e2a Prompt \u6bd4\u8f83\u9002\u5408\u521d\u5b66\u8005\uff0c\u4f46\u53ef\u4ee5\u589e\u52a0\u4e00\u4e9b\u751f\u6d3b\u5316\u7684\u4f8b\u5b50\u6765\u63d0\u5347\u5438\u5f15\u529b\u3002\n
\u7b2c2\u8f6e\u4f18\u5316\uff1a
Text Only\u7ed3\u5408\u751f\u6d3b\u4e2d\u7684\u5b9e\u4f8b\u8865\u5145\uff0c\u5982\u201c\u901a\u8fc7\u4e70\u82f9\u679c\u6765\u8ba1\u7b97\u603b\u4ef7\u201d\uff0c\u4f7f\u5f97\u8bb2\u89e3\u66f4\u52a0\u751f\u52a8\u3002\n
\u5927\u6a21\u578b\u5bf9\u8ba1\u7b97\u548c\u5b9e\u65f6\u6570\u636e\u7684\u652f\u6301\u6709\u9650\uff0c\u56e0\u6b64\u7ed3\u5408\u5916\u90e8\u5de5\u5177\uff0c\u5982 API \u8c03\u7528\u6216\u4ee3\u7801\u6267\u884c\uff0c\u53ef\u4ee5\u63d0\u5347\u4efb\u52a1\u7684\u51c6\u786e\u6027\u3002
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u6c42\u89e3\u591a\u9879\u5f0f\u7684\u6240\u6709\u5b9e\u6839\u3002 Prompt\uff1a
Text Only\u8bf7\u7528 Python \u7f16\u5199\u4ee3\u7801\u6765\u8ba1\u7b97\u4ee5\u4e0b\u591a\u9879\u5f0f\u7684\u6240\u6709\u5b9e\u6839\uff1a\n\u591a\u9879\u5f0f\uff1a3x^3 - 5x^2 + 2x - 7\n\u8f93\u51fa Python \u4ee3\u7801\u5e76\u89e3\u91ca\u5176\u4f5c\u7528\u3002\n
\u8f93\u51fa\u7ed3\u679c\uff1a
Pythonimport numpy as np\ncoefficients = [3, -5, 2, -7]\nroots = np.roots(coefficients)\nprint(\"\u5b9e\u6839\u4e3a\uff1a\", [r for r in roots if np.isreal(r)])\n
\u89e3\u91ca\uff1a\u6b64\u4ee3\u7801\u4f7f\u7528 NumPy \u7684 roots
\u51fd\u6570\u8ba1\u7b97\u591a\u9879\u5f0f\u7684\u6240\u6709\u6839\uff0c\u5e76\u8fc7\u6ee4\u51fa\u5b9e\u6839\u3002
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u751f\u6210\u4f1a\u8bae\u7eaa\u8981\u3002 Prompt\uff1a
Text Only\u8bf7\u5c06\u4ee5\u4e0b\u4f1a\u8bae\u8bb0\u5f55\u603b\u7ed3\u4e3a Markdown \u683c\u5f0f\uff0c\u5305\u62ec\u53d1\u8a00\u4eba\u3001\u4e3b\u8981\u89c2\u70b9\u548c\u540e\u7eed\u4efb\u52a1\u3002\n
\u8f93\u51fa\uff1a
Markdown### \u4f1a\u8bae\u7eaa\u8981\n\n#### \u53d1\u8a00\u4eba\u53ca\u89c2\u70b9\n- **\u5f20\u4e09**\uff1a\u5efa\u8bae\u589e\u52a0\u5e02\u573a\u8425\u9500\u9884\u7b97\u3002\n- **\u674e\u56db**\uff1a\u5f3a\u8c03\u4f18\u5316\u4ea7\u54c1\u8d28\u91cf\u7684\u91cd\u8981\u6027\u3002\n\n#### \u540e\u7eed\u4efb\u52a1\n- \u5236\u5b9a\u65b0\u4e00\u5b63\u5ea6\u7684\u8425\u9500\u7b56\u7565\uff08\u8d1f\u8d23\u4eba\uff1a\u5f20\u4e09\uff09\u3002\n- \u8c03\u67e5\u7528\u6237\u5bf9\u5f53\u524d\u4ea7\u54c1\u7684\u6ee1\u610f\u5ea6\uff08\u8d1f\u8d23\u4eba\uff1a\u674e\u56db\uff09\u3002\n
\u793a\u4f8b\uff1a \u4efb\u52a1\uff1a\u751f\u6210\u6570\u5b66\u516c\u5f0f\u3002 Prompt\uff1a
Text Only\u8bf7\u7528 LaTeX \u683c\u5f0f\u4e66\u5199\u4ee5\u4e0b\u516c\u5f0f\u5e76\u89e3\u91ca\uff1a$(a+b)^2 = a^2 + 2ab + b^2$\u3002\n
\u8f93\u51fa\uff1a
TeX\\[\n(a+b)^2 = a^2 + 2ab + b^2\n\\]\n\u8fd9\u662f\u4e00\u4e2a\u57fa\u672c\u7684\u5e73\u65b9\u5c55\u5f00\u516c\u5f0f\uff0c\u5e38\u7528\u4e8e\u591a\u9879\u5f0f\u7684\u8ba1\u7b97\u3002\n
\u5f00\u653e\u5f0f\u4efb\u52a1\uff08\u5982\u5199\u6545\u4e8b\u6216\u63a8\u8350\u65b9\u6848\uff09\u5bb9\u6613\u5bfc\u81f4\u6a21\u578b\u201c\u8dd1\u9898\u201d\uff0c\u901a\u8fc7\u515c\u5e95\u7b56\u7565\u53ef\u63d0\u9ad8\u7a33\u5b9a\u6027\u3002
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u73b0\u5728\u4f60\u662f\u4e00\u4e2a\u5411\u5ba2\u6237\u63a8\u8350\u7535\u5f71\u7684\u52a9\u624b\u3002\u5982\u679c\u5ba2\u6237\u7684\u4fe1\u606f\u4e0d\u8db3\u4ee5\u7ed9\u51fa\u63a8\u8350\uff0c\u8bf7\u56de\u7b54\uff1a\u201c\u62b1\u6b49\uff0c\u6211\u65e0\u6cd5\u6839\u636e\u60a8\u7684\u63cf\u8ff0\u63a8\u8350\u7535\u5f71\u3002\u201d\u3002\n
\u8f93\u5165\uff1a
Text Only\u5ba2\u6237\uff1a\u5e2e\u6211\u63a8\u8350\u4e00\u90e8\u7535\u5f71\u3002\n
\u8f93\u51fa\uff1a
Text Only\u62b1\u6b49\uff0c\u6211\u65e0\u6cd5\u6839\u636e\u60a8\u7684\u63cf\u8ff0\u63a8\u8350\u7535\u5f71\u3002\n
\u793a\u4f8b\uff1a\u5f53\u751f\u6210\u7ed3\u679c\u4e0d\u7b26\u5408\u683c\u5f0f\u65f6\uff0c\u8981\u6c42\u91cd\u65b0\u751f\u6210\u3002
Text Only\u5982\u679c\u4ee5\u4e0b\u5185\u5bb9\u7684\u8f93\u51fa\u683c\u5f0f\u9519\u8bef\uff0c\u8bf7\u91cd\u65b0\u751f\u6210\u5e76\u786e\u4fdd\u7b26\u5408\u8981\u6c42\uff1a\n\u8f93\u51fa\u683c\u5f0f\uff1a\n- \u4efb\u52a1\u63cf\u8ff0\n- \u4efb\u52a1\u8981\u70b9\n- \u4efb\u52a1\u5efa\u8bae\n
\u4f7f\u7528\u7279\u6b8a\u7b26\u53f7\uff08\u5982\u52a0\u7c97\uff09\u6216\u5f3a\u8c03\u8bcd\uff08\u5982\u201c\u52a1\u5fc5\u201d\u3001\u201c\u4e25\u683c\u201d\uff09\u6807\u6ce8\u5173\u952e\u5185\u5bb9\u3002
\u4efb\u52a1\uff1a\u603b\u7ed3\u6587\u7ae0\u5e76\u5f3a\u8c03\u5173\u952e\u6982\u5ff5\u3002 Prompt\uff1a
Text Only ```text\n \u8bf7\u603b\u7ed3\u4ee5\u4e0b\u6587\u7ae0\uff0c\u5e76**\u52a0\u7c97**\u6bcf\u4e2a\u8981\u70b9\u4e2d\u7684\u5173\u952e\u6982\u5ff5\uff0c\u4ee5 Markdown \u5217\u8868\u5f62\u5f0f\u8f93\u51fa\u3002\n ```\n\n **\u8f93\u51fa**\uff1a\n\n ```markdown\n - **\u8981\u70b9\u4e00**\uff1a\u673a\u5668\u5b66\u4e60\u662f\u901a\u8fc7\u6570\u636e\u8bad\u7ec3\u6a21\u578b\u7684**\u65b9\u6cd5**\u3002\n - **\u8981\u70b9\u4e8c**\uff1a\u6df1\u5ea6\u5b66\u4e60\u662f\u673a\u5668\u5b66\u4e60\u7684**\u5206\u652f**\uff0c\u4ee5\u591a\u5c42\u795e\u7ecf\u7f51\u7edc\u4e3a\u6838\u5fc3\u3002\n ```\n
"},{"location":"Tools/AI/prompt_writing/#14","title":"1.4 \u5b9e\u7528\u6848\u4f8b","text":""},{"location":"Tools/AI/prompt_writing/#141","title":"1.4.1 \u5e38\u89c1\u573a\u666f\u4e0e\u89e3\u51b3\u65b9\u6848","text":""},{"location":"Tools/AI/prompt_writing/#1411","title":"1.4.1.1 \u751f\u6210\u957f\u7bc7\u7684\u6587\u7ae0","text":"\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u4e00\u4efd\u8be6\u7ec6\u7684\u6587\u7ae0\u76ee\u5f55\uff0c\u7136\u540e\u57fa\u4e8e\u76ee\u5f55\u9010\u6bb5\u6269\u5c55\u5185\u5bb9\uff1a\n\u4e3b\u9898\uff1a\u5982\u4f55\u4f18\u5316\u4e2a\u4eba\u65f6\u95f4\u7ba1\u7406\n
\u8f93\u51fa\u76ee\u5f55\u793a\u4f8b\uff1a
Markdown- \u7b2c\u4e00\u90e8\u5206\uff1a\u65f6\u95f4\u7ba1\u7406\u7684\u91cd\u8981\u6027\n- \u7b2c\u4e8c\u90e8\u5206\uff1a\u5e38\u89c1\u65f6\u95f4\u7ba1\u7406\u8bef\u533a\n- \u7b2c\u4e09\u90e8\u5206\uff1a\u9ad8\u6548\u65f6\u95f4\u7ba1\u7406\u7684\u65b9\u6cd5\n - 1. \u8bbe\u5b9a\u76ee\u6807\u4e0e\u4f18\u5148\u7ea7\n - 2. \u4f7f\u7528\u5de5\u5177\u4e0e\u6280\u672f\n - 3. \u57f9\u517b\u65f6\u95f4\u7ba1\u7406\u4e60\u60ef\n- \u7b2c\u56db\u90e8\u5206\uff1a\u6848\u4f8b\u5206\u6790\u4e0e\u5e94\u7528\n
\u6269\u5c55\u5185\u5bb9 Prompt\uff1a
Text Only\u8bf7\u8be6\u7ec6\u64b0\u5199\u7b2c\u4e00\u90e8\u5206\u201c\u65f6\u95f4\u7ba1\u7406\u7684\u91cd\u8981\u6027\u201d\u7684\u5185\u5bb9\uff0c\u63a7\u5236\u5728 300 \u5b57\u5de6\u53f3\u3002\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u4e00\u7bc7 500 \u5b57\u7684\u6587\u7ae0\uff0c\u5e76\u5728\u6587\u7ae0\u672b\u5c3e\u9644\u4e0a\u76f8\u5173\u53c2\u8003\u6587\u732e\uff1a\n\u4e3b\u9898\uff1a\u4eba\u5de5\u667a\u80fd\u5982\u4f55\u6539\u53d8\u6559\u80b2\u884c\u4e1a\n
\u8f93\u51fa\uff1a
Markdown### \u4eba\u5de5\u667a\u80fd\u5982\u4f55\u6539\u53d8\u6559\u80b2\u884c\u4e1a\n\uff08\u6587\u7ae0\u5185\u5bb9\uff09\n#### \u53c2\u8003\u6587\u732e\n- \u674e\u56db\uff0c\u300a\u4eba\u5de5\u667a\u80fd\u4e0e\u6559\u80b2\u300b\uff0c2023\u5e74\u51fa\u7248\u3002\n- OpenAI\uff0c\u300aAI\u5728\u6559\u80b2\u9886\u57df\u7684\u5e94\u7528\u300b\uff0c2021\u5e74\u3002\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u4ee5\u4e0b\u662f Python \u4ee3\u7801\u7247\u6bb5\uff0c\u8bf7\u89e3\u91ca\u5176\u4f5c\u7528\uff1a\n```python\nnested_dict = lambda: defaultdict(nested_dict)\n
Text Only**\u8f93\u51fa**\uff1a\n```text\n\u6b64\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5d4c\u5957\u5b57\u5178\u7684\u9012\u5f52\u7ed3\u6784\uff0c\u53ef\u4ee5\u52a8\u6001\u521b\u5efa\u4efb\u610f\u6df1\u5ea6\u7684\u5b57\u5178\u5c42\u7ea7\u3002\n\u793a\u4f8b\u7528\u6cd5\uff1a\ndata = nested_dict()\ndata['level1']['level2'] = \"value\"\n
\u793a\u4f8b\uff1a Prompt\uff1a
Text Only\u8bf7\u6839\u636e\u4ee5\u4e0b\u63cf\u8ff0\u751f\u6210\u4e00\u6bb5 mermaid \u683c\u5f0f\u7684\u4ee3\u7801\uff0c\u7528\u4e8e\u5c55\u793a\u51fd\u6570\u8c03\u7528\u5173\u7cfb\uff1a\n\u63cf\u8ff0\uff1a\u51fd\u6570 A \u8c03\u7528\u51fd\u6570 B\uff0c\u51fd\u6570 B \u8c03\u7528\u51fd\u6570 C \u548c D\uff0c\u51fd\u6570 D \u8fd4\u56de\u7ed3\u679c\u3002\n
\u8f93\u51fa\uff1a
Text Onlygraph TD\nA --> B\nB --> C\nB --> D\nD --> Result\n
\u63d0\u793a\u6a21\u578b\u4e0d\u8981\u56de\u7b54\u5176\u65e0\u6cd5\u786e\u5b9a\u7684\u5185\u5bb9\u3002 \u793a\u4f8b\uff1a
Text Only\u5982\u679c\u4f60\u4e0d\u77e5\u9053\u4ee5\u4e0b\u95ee\u9898\u7684\u7b54\u6848\uff0c\u8bf7\u56de\u590d\u201c\u4fe1\u606f\u4e0d\u8db3\u201d\u3002\n\u95ee\u9898\uff1a\u8c01\u662f\u7b2c\u4e00\u4e2a\u767b\u4e0a\u6708\u7403\u7684\u673a\u5668\u4eba\uff1f\n
\u8f93\u51fa\uff1a
Text Only\u4fe1\u606f\u4e0d\u8db3\u3002\n
Prompt\uff1a
Text Only\u8bf7\u591a\u6b21\u751f\u6210\u4ee5\u4e0b\u95ee\u9898\u7684\u7b54\u6848\uff0c\u5e76\u786e\u4fdd\u7b54\u6848\u4e00\u81f4\u3002\u5982\u679c\u7b54\u6848\u4e0d\u4e00\u81f4\uff0c\u8bf7\u56de\u590d\u201c\u65e0\u6cd5\u786e\u5b9a\u7b54\u6848\u201d\u3002\n\u95ee\u9898\uff1a2023 \u5e74\u4e16\u754c\u4eba\u53e3\u603b\u6570\u662f\u591a\u5c11\uff1f\n
\u901a\u8fc7\u4e0d\u540c\u6a21\u578b\u534f\u4f5c\u4f18\u5316\u5185\u5bb9\u751f\u6210\u3002 \u793a\u4f8b\u6d41\u7a0b\uff1a
\u8bf7\u4e3a\u4ee5\u4e0b\u4e3b\u9898\u751f\u6210\u8be6\u7ec6\u7684\u6587\u7ae0\u6846\u67b6\uff1a\n\u4e3b\u9898\uff1a\u5982\u4f55\u63d0\u5347\u56e2\u961f\u5408\u4f5c\u6548\u7387\n
\u8bf7\u6839\u636e\u4ee5\u4e0b\u6846\u67b6\u64b0\u5199\u8be6\u7ec6\u5185\u5bb9\uff0c\u5e76\u8c03\u6574\u4e3a\u66f4\u4e13\u4e1a\u7684\u8bed\u8a00\u3002\n
\u8bf7\u4f18\u5316\u4ee5\u4e0b\u4ee3\u7801\uff0c\u4f7f\u5176\u8fd0\u884c\u6548\u7387\u66f4\u9ad8\uff0c\u5e76\u63d0\u4f9b\u6ce8\u91ca\u8bf4\u660e\uff1a\n ```python\n def factorial(n):\n if n == 0:\n return 1\n else:\n return n * factorial(n-1)\n ```\n
"},{"location":"Tools/AI/prompt_writing/#15","title":"1.5 \u6211\u66fe\u7ecf\u7528\u6cd5","text":"\u8bf7\u53c2\u8003 \u5e38\u7528 prompt \u8bb0\u5f55 - wnc \u7684\u5496\u5561\u9986
"},{"location":"Tools/Blog/Mkdocs_Material/","title":"mkdocs material \u8d85\u5168\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#mkdocs-material","title":"mkdocs material \u8d85\u5168\u914d\u7f6e","text":"\u7ea6 5956 \u4e2a\u5b57 9393 \u884c\u4ee3\u7801 7 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 147 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u4ecd\u7136\u5728\u4fee\u6539 \u5982\u679c\u9700\u8981\u4efb\u4f55\u7684\u6587\u4ef6\uff0c\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee\u672c\u535a\u5ba2\u7684 GitHub \u9875\u9762
"},{"location":"Tools/Blog/Mkdocs_Material/#1","title":"1 \u5165\u95e8\u57fa\u7840","text":""},{"location":"Tools/Blog/Mkdocs_Material/#11-mkdocs","title":"1.1 \u4ec0\u4e48\u662f MkDocs\uff1f","text":"MkDocs \u662f\u4e00\u4e2a\u5feb\u901f\u3001\u7b80\u5355\u3001\u534e\u4e3d\u7684\u9759\u6001\u7ad9\u70b9\u751f\u6210\u5668\uff0c\u4e13\u95e8\u7528\u4e8e\u6784\u5efa\u9879\u76ee\u6587\u6863\u3002\u6587\u6863\u6e90\u6587\u4ef6\u4f7f\u7528 Markdown \u7f16\u5199\uff0c\u914d\u7f6e\u6587\u4ef6\u4f7f\u7528 YAML \u683c\u5f0f\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#111-mkdocs","title":"1.1.1 MkDocs \u7684\u4f18\u52bf","text":"\u7b80\u5355\u6613\u7528 - \u4f7f\u7528 Markdown \u7f16\u5199\u6587\u6863 - \u914d\u7f6e\u6587\u4ef6\u7b80\u5355\u76f4\u89c2 - \u4e00\u952e\u5f0f\u6784\u5efa\u548c\u90e8\u7f72
\u529f\u80fd\u5f3a\u5927 - \u5185\u7f6e\u5f00\u53d1\u670d\u52a1\u5668\uff0c\u652f\u6301\u5b9e\u65f6\u9884\u89c8 - \u591a\u79cd\u4e3b\u9898\u53ef\u9009 - \u652f\u6301\u81ea\u5b9a\u4e49\u4e3b\u9898 - \u81ea\u52a8\u751f\u6210\u5bfc\u822a - \u5168\u6587\u641c\u7d22\u529f\u80fd
\u90e8\u7f72\u65b9\u4fbf - \u751f\u6210\u7eaf\u9759\u6001\u9875\u9762 - \u4e00\u884c\u547d\u4ee4\u90e8\u7f72\u5230 GitHub Pages - \u652f\u6301\u81ea\u5b9a\u4e49\u57df\u540d - \u517c\u5bb9\u6240\u6709\u9759\u6001\u7f51\u7ad9\u6258\u7ba1\u5e73\u53f0
MkDocs \u7684\u5de5\u4f5c\u6d41\u7a0b\u5982\u4e0b\uff1a
\u6587\u6863\u7f16\u5199 - \u4f7f\u7528 Markdown \u683c\u5f0f\u7f16\u5199\u6587\u6863 - \u6587\u6863\u5b58\u653e\u5728 docs
\u76ee\u5f55\u4e0b - \u652f\u6301\u591a\u7ea7\u76ee\u5f55\u7ed3\u6784
\u914d\u7f6e\u89e3\u6790 - \u8bfb\u53d6 mkdocs.yml
\u914d\u7f6e\u6587\u4ef6 - \u89e3\u6790\u4e3b\u9898\u8bbe\u7f6e\u3001\u63d2\u4ef6\u914d\u7f6e\u7b49 - \u751f\u6210\u5bfc\u822a\u7ed3\u6784
\u6784\u5efa\u8fc7\u7a0b
Markdown \u6587\u4ef6 -> \u89e3\u6790\u5668 -> HTML \u6587\u4ef6\n -> \u4e3b\u9898\u6e32\u67d3\n -> \u63d2\u4ef6\u5904\u7406\n -> \u9759\u6001\u8d44\u6e90\u5904\u7406\n
Material for MkDocs \u662f\u4e00\u4e2a\u57fa\u4e8e Google Material Design \u8bbe\u8ba1\u8bed\u8a00\u7684\u4e3b\u9898\uff0c\u5b83\u4e0d\u4ec5\u7f8e\u89c2\uff0c\u800c\u4e14\u529f\u80fd\u5f3a\u5927\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#121-material","title":"1.2.1 Material \u4e3b\u9898\u7279\u6027","text":"\u73b0\u4ee3\u5316\u8bbe\u8ba1 - \u9075\u5faa Material Design \u89c4\u8303 - \u54cd\u5e94\u5f0f\u5e03\u5c40 - \u652f\u6301\u6df1\u8272\u6a21\u5f0f - \u81ea\u52a8\u9002\u914d\u79fb\u52a8\u8bbe\u5907
\u5f3a\u5927\u529f\u80fd - \u667a\u80fd\u641c\u7d22 - \u4ee3\u7801\u9ad8\u4eae - \u6807\u7b7e\u9875\u652f\u6301 - \u81ea\u52a8\u76ee\u5f55\u751f\u6210 - \u591a\u8bed\u8a00\u652f\u6301 - \u7248\u672c\u63a7\u5236\u96c6\u6210
\u51fa\u8272\u7684\u7528\u6237\u4f53\u9a8c - \u5feb\u901f\u52a0\u8f7d - \u5e73\u6ed1\u52a8\u753b - \u5b9e\u65f6\u641c\u7d22 - \u4ee3\u7801\u590d\u5236\u6309\u94ae - \u8fd4\u56de\u9876\u90e8\u6309\u94ae
Material Theme\n\u251c\u2500\u2500 \u6838\u5fc3\u7ec4\u4ef6\n\u2502 \u251c\u2500\u2500 \u5bfc\u822a\u680f\n\u2502 \u251c\u2500\u2500 \u4fa7\u8fb9\u680f\n\u2502 \u251c\u2500\u2500 \u641c\u7d22\u7ec4\u4ef6\n\u2502 \u2514\u2500\u2500 \u5185\u5bb9\u6e32\u67d3\u5668\n\u251c\u2500\u2500 \u6269\u5c55\u529f\u80fd\n\u2502 \u251c\u2500\u2500 \u4ee3\u7801\u9ad8\u4eae\n\u2502 \u251c\u2500\u2500 \u6807\u7b7e\u7cfb\u7edf\n\u2502 \u251c\u2500\u2500 \u76ee\u5f55\u751f\u6210\n\u2502 \u2514\u2500\u2500 \u4e3b\u9898\u5207\u6362\n\u2514\u2500\u2500 \u63d2\u4ef6\u7cfb\u7edf\n \u251c\u2500\u2500 \u5185\u7f6e\u63d2\u4ef6\n \u2514\u2500\u2500 \u7b2c\u4e09\u65b9\u63d2\u4ef6\u96c6\u6210\n
"},{"location":"Tools/Blog/Mkdocs_Material/#13","title":"1.3 \u73af\u5883\u8981\u6c42","text":""},{"location":"Tools/Blog/Mkdocs_Material/#131-python","title":"1.3.1 Python \u73af\u5883","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1311-python","title":"1.3.1.1 Python \u7248\u672c\u9009\u62e9","text":"MkDocs \u9700\u8981 Python 3.6 \u6216\u66f4\u9ad8\u7248\u672c\uff0c\u63a8\u8350\u4f7f\u7528 Python 3.8+\uff1a
Bash# \u68c0\u67e5 Python \u7248\u672c\npython --version\n\n# \u63a8\u8350\u7248\u672c\nPython 3.8.x\nPython 3.9.x\nPython 3.10.x\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1312-pip","title":"1.3.1.2 pip \u914d\u7f6e\u8bf4\u660e","text":"pip \u662f Python \u7684\u5305\u7ba1\u7406\u5de5\u5177\uff0c\u9700\u8981\u786e\u4fdd\u5176\u6b63\u786e\u5b89\u88c5\uff1a
Bash# \u68c0\u67e5 pip \u7248\u672c\npip --version\n\n# \u5347\u7ea7 pip\npython -m pip install --upgrade pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1313","title":"1.3.1.3 \u865a\u62df\u73af\u5883\u7ba1\u7406","text":"\u63a8\u8350\u4f7f\u7528\u865a\u62df\u73af\u5883\u6765\u7ba1\u7406\u9879\u76ee\u4f9d\u8d56\uff1a
Bash# \u521b\u5efa\u865a\u62df\u73af\u5883\npython -m venv venv\n\n# \u6fc0\u6d3b\u865a\u62df\u73af\u5883\n# Windows\nvenv\\Scripts\\activate\n# Linux/Mac\nsource venv/bin/activate\n\n# \u9000\u51fa\u865a\u62df\u73af\u5883\ndeactivate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#132-pip","title":"1.3.2 pip \u5305\u7ba1\u7406","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1321-pip","title":"1.3.2.1 pip \u6e90\u914d\u7f6e","text":"\u4e3a\u52a0\u5feb\u4e0b\u8f7d\u901f\u5ea6\uff0c\u5efa\u8bae\u4f7f\u7528\u56fd\u5185\u955c\u50cf\u6e90\uff1a
Bash# \u4e34\u65f6\u4f7f\u7528\npip install -i https://pypi.tuna.tsinghua.edu.cn/simple mkdocs\n\n# \u6c38\u4e45\u914d\u7f6e\npip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1322","title":"1.3.2.2 \u4f9d\u8d56\u7ba1\u7406","text":"\u5b89\u88c5\u5fc5\u8981\u7684\u5305\uff1a
Bashpip install mkdocs-material\npip install mkdocs-glightbox\npip install mkdocs-git-revision-date-localized-plugin\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1323-requirements-txt","title":"1.3.2.3 requirements. txt \u4f7f\u7528","text":"\u7ef4\u62a4\u9879\u76ee\u4f9d\u8d56\uff1a
Bash# \u751f\u6210\u4f9d\u8d56\u6587\u4ef6\npip freeze > requirements.txt\n\n# \u5b89\u88c5\u4f9d\u8d56\npip install -r requirements.txt\n
"},{"location":"Tools/Blog/Mkdocs_Material/#133-git","title":"1.3.3 Git \u73af\u5883","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1331-git","title":"1.3.3.1 Git \u57fa\u7840\u914d\u7f6e","text":"Bash# \u914d\u7f6e\u7528\u6237\u4fe1\u606f\ngit config --global user.name \"Your Name\"\ngit config --global user.email \"your.email@example.com\"\n\n# \u914d\u7f6e\u9ed8\u8ba4\u5206\u652f\ngit config --global init.defaultBranch main\n
"},{"location":"Tools/Blog/Mkdocs_Material/#134-ssh","title":"1.3.4 SSH \u5bc6\u94a5\u914d\u7f6e","text":"Bash# \u751f\u6210 SSH \u5bc6\u94a5\nssh-keygen -t rsa -b 4096 -C \"your.email@example.com\"\n\n# \u67e5\u770b\u516c\u94a5\ncat ~/.ssh/id_rsa.pub\n
\u5c06\u516c\u94a5\u6dfb\u52a0\u5230 GitHub \u8d26\u6237\u7684 SSH keys \u4e2d\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#135-gitignore","title":"1.3.5 .gitignore \u914d\u7f6e","text":"\u521b\u5efa .gitignore
\u6587\u4ef6\uff0c\u6dfb\u52a0\u4ee5\u4e0b\u5185\u5bb9\uff1a
# Python\n__pycache__/\n*.py[cod]\n*$py.class\nvenv/\n\n# MkDocs\nsite/\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2","title":"2 \u73af\u5883\u642d\u5efa","text":""},{"location":"Tools/Blog/Mkdocs_Material/#21-windows","title":"2.1 Windows \u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#211-python","title":"2.1.1 Python \u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2111","title":"2.1.1.1 \u4e0b\u8f7d\u5b89\u88c5\u5305","text":"# \u6dfb\u52a0\u5230\u7cfb\u7edf\u73af\u5883\u53d8\u91cf Path\nC:\\Users\\YourUser\\AppData\\Local\\Programs\\Python\\Python3x\\\nC:\\Users\\YourUser\\AppData\\Local\\Programs\\Python\\Python3x\\Scripts\\\n
echo %PATH%\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2113","title":"2.1.1.3 \u9a8c\u8bc1\u5b89\u88c5","text":"\u5728\u547d\u4ee4\u63d0\u793a\u7b26\u4e2d\u6267\u884c\uff1a
Bash# \u68c0\u67e5 Python \u7248\u672c\npython --version\n\n# \u68c0\u67e5 pip \u7248\u672c\npip --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#212-mkdocs","title":"2.1.2 MkDocs \u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2121-pip","title":"2.1.2.1 pip \u5b89\u88c5\u65b9\u6cd5","text":"\u4f7f\u7528 pip \u5b89\u88c5 MkDocs\uff1a
Bash# \u5b89\u88c5 MkDocs\npip install mkdocs\n\n# \u9a8c\u8bc1\u5b89\u88c5\nmkdocs --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2122","title":"2.1.2.2 \u5e38\u89c1\u95ee\u9898\u89e3\u51b3","text":"pip \u4e0d\u662f\u5185\u90e8\u547d\u4ee4 - \u89e3\u51b3\u65b9\u6cd5\uff1a\u91cd\u65b0\u6dfb\u52a0 Python Scripts \u76ee\u5f55\u5230 PATH
\u6743\u9650\u95ee\u9898 - \u89e3\u51b3\u65b9\u6cd5\uff1a\u4f7f\u7528\u7ba1\u7406\u5458\u6743\u9650\u8fd0\u884c\u547d\u4ee4\u63d0\u793a\u7b26
# \u7ba1\u7406\u5458\u6743\u9650\u5b89\u88c5\npip install --user mkdocs\n
pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org mkdocs\n
"},{"location":"Tools/Blog/Mkdocs_Material/#213","title":"2.1.3 \u7248\u672c\u9009\u62e9","text":"MkDocs \u7248\u672c\u9009\u62e9\u5efa\u8bae\uff1a
Bash# \u67e5\u770b\u53ef\u7528\u7248\u672c\npip install mkdocs==\n\n# \u5b89\u88c5\u7279\u5b9a\u7248\u672c\npip install mkdocs==1.5.3 # \u63a8\u8350\u7248\u672c\n
"},{"location":"Tools/Blog/Mkdocs_Material/#214-material","title":"2.1.4 Material \u4e3b\u9898\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2141","title":"2.1.4.1 \u5b89\u88c5\u547d\u4ee4","text":"Bash# \u5b89\u88c5 Material \u4e3b\u9898\npip install mkdocs-material\n\n# \u9a8c\u8bc1\u5b89\u88c5\npython -c \"import mkdocs_material; print(mkdocs_material.__version__)\"\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2142","title":"2.1.4.2 \u4f9d\u8d56\u68c0\u67e5","text":"\u5b89\u88c5\u5fc5\u8981\u7684\u4f9d\u8d56\uff1a
Bash# \u5b89\u88c5\u6269\u5c55\u652f\u6301\npip install pymdown-extensions\npip install mkdocs-glightbox\npip install mkdocs-git-revision-date-localized-plugin\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2143","title":"2.1.4.3 \u7248\u672c\u517c\u5bb9\u6027","text":"MkDocs \u7248\u672c Material \u7248\u672c Python \u7248\u672c 1.5. x 9.4. x \u22653.8 1.4. x 9.3. x \u22653.7 1.3. x 9.2. x \u22653.7"},{"location":"Tools/Blog/Mkdocs_Material/#22-linuxmac","title":"2.2 Linux/Mac \u7cfb\u7edf\u5b89\u88c5","text":""},{"location":"Tools/Blog/Mkdocs_Material/#221-python","title":"2.2.1 \u5305\u7ba1\u7406\u5668\u5b89\u88c5 Python","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2211-aptyum","title":"2.2.1.1 apt/yum \u5b89\u88c5\u65b9\u6cd5","text":"Ubuntu/Debian:
Bash# \u66f4\u65b0\u5305\u7d22\u5f15\nsudo apt update\n\n# \u5b89\u88c5 Python\nsudo apt install python3 python3-pip\n\n# \u5b89\u88c5\u5f00\u53d1\u5de5\u5177\nsudo apt install python3-dev\n
CentOS/RHEL:
Bash# \u5b89\u88c5 EPEL \u4ed3\u5e93\nsudo yum install epel-release\n\n# \u5b89\u88c5 Python\nsudo yum install python3 python3-pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2212-brew","title":"2.2.1.2 brew \u5b89\u88c5\u65b9\u6cd5","text":"macOS:
Bash# \u5b89\u88c5 Homebrew\uff08\u5982\u679c\u672a\u5b89\u88c5\uff09\n/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n\n# \u5b89\u88c5 Python\nbrew install python\n\n# \u66f4\u65b0 pip\npip3 install --upgrade pip\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2213","title":"2.2.1.3 \u73af\u5883\u53d8\u91cf\u914d\u7f6e","text":"bash/zsh:
Bash# \u6dfb\u52a0\u5230 ~/.bashrc \u6216 ~/.zshrc\nexport PATH=\"$HOME/.local/bin:$PATH\"\nexport PYTHONPATH=\"$HOME/.local/lib/python3.x/site-packages:$PYTHONPATH\"\n\n# \u66f4\u65b0\u73af\u5883\u53d8\u91cf\nsource ~/.bashrc # \u6216 source ~/.zshrc\n
"},{"location":"Tools/Blog/Mkdocs_Material/#222-pip","title":"2.2.2 pip \u5b89\u88c5\u4f9d\u8d56","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2221","title":"2.2.2.1 \u7cfb\u7edf\u7ea7\u5b89\u88c5","text":"Bash# \u5168\u5c40\u5b89\u88c5\uff08\u9700\u8981 root \u6743\u9650\uff09\nsudo pip3 install mkdocs mkdocs-material\n\n# \u9a8c\u8bc1\u5b89\u88c5\nmkdocs --version\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2222","title":"2.2.2.2 \u7528\u6237\u7ea7\u5b89\u88c5","text":"Bash# \u7528\u6237\u76ee\u5f55\u5b89\u88c5\npip3 install --user mkdocs mkdocs-material\n\n# \u68c0\u67e5\u5b89\u88c5\u8def\u5f84\npython3 -m site --user-site\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2223","title":"2.2.2.3 \u865a\u62df\u73af\u5883\u5b89\u88c5","text":"Bash# \u521b\u5efa\u865a\u62df\u73af\u5883\npython3 -m venv mkdocs-env\n\n# \u6fc0\u6d3b\u865a\u62df\u73af\u5883\nsource mkdocs-env/bin/activate\n\n# \u5b89\u88c5\u4f9d\u8d56\npip install mkdocs mkdocs-material\n\n# \u9000\u51fa\u865a\u62df\u73af\u5883\ndeactivate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#23","title":"2.3 \u9879\u76ee\u521d\u59cb\u5316","text":""},{"location":"Tools/Blog/Mkdocs_Material/#231","title":"2.3.1 \u521b\u5efa\u9879\u76ee","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2311-mkdocs-new","title":"2.3.1.1 mkdocs new \u547d\u4ee4\u8be6\u89e3","text":"Bash# \u57fa\u672c\u8bed\u6cd5\nmkdocs new [\u9879\u76ee\u540d]\n\n# \u521b\u5efa\u65b0\u9879\u76ee\nmkdocs new my-docs\n\n# \u4f7f\u7528\u73b0\u6709\u76ee\u5f55\ncd existing-project\nmkdocs new .\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2312","title":"2.3.1.2 \u9879\u76ee\u547d\u540d\u89c4\u8303","text":"\u793a\u4f8b\uff1a
Bashmkdocs new technical-docs # \u597d\u7684\u547d\u540d\nmkdocs new tech_docs # \u907f\u514d\u4f7f\u7528\u4e0b\u5212\u7ebf\nmkdocs new TechDocs # \u907f\u514d\u4f7f\u7528\u5927\u5199\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2313","title":"2.3.1.3 \u521d\u59cb\u5316\u914d\u7f6e","text":"\u521b\u5efa\u9879\u76ee\u540e\u7684\u57fa\u672c\u8bbe\u7f6e\uff1a
Bashcd my-docs\n# \u542f\u52a8\u5f00\u53d1\u670d\u52a1\u5668\nmkdocs serve\n# \u5728\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee http://127.0.0.1:8000\n
"},{"location":"Tools/Blog/Mkdocs_Material/#232","title":"2.3.2 \u76ee\u5f55\u7ed3\u6784\u8bf4\u660e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2321","title":"2.3.2.1 \u57fa\u7840\u76ee\u5f55\u7ed3\u6784","text":"Text Onlymy-docs/\n\u251c\u2500\u2500 docs/ # \u6587\u6863\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 index.md # \u9996\u9875\n\u2502 \u251c\u2500\u2500 about.md # \u5176\u4ed6\u9875\u9762\n\u2502 \u2514\u2500\u2500 img/ # \u56fe\u7247\u76ee\u5f55\n\u251c\u2500\u2500 mkdocs.yml # \u914d\u7f6e\u6587\u4ef6\n\u2514\u2500\u2500 venv/ # \u865a\u62df\u73af\u5883\uff08\u53ef\u9009\uff09\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2322-docs","title":"2.3.2.2 docs \u76ee\u5f55\u7ec4\u7ec7","text":"Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u9996\u9875\n\u251c\u2500\u2500 guide/ # \u6307\u5357\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 index.md # \u6307\u5357\u9996\u9875\n\u2502 \u251c\u2500\u2500 install.md # \u5b89\u88c5\u8bf4\u660e\n\u2502 \u2514\u2500\u2500 usage.md # \u4f7f\u7528\u8bf4\u660e\n\u251c\u2500\u2500 api/ # API\u6587\u6863\n\u2502 \u2514\u2500\u2500 index.md # API\u9996\u9875\n\u2514\u2500\u2500 examples/ # \u793a\u4f8b\u76ee\u5f55\n \u2514\u2500\u2500 basic.md # \u57fa\u7840\u793a\u4f8b\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2323","title":"2.3.2.3 \u8d44\u6e90\u6587\u4ef6\u7ba1\u7406","text":"Text Onlydocs/\n\u251c\u2500\u2500 assets/ # \u8d44\u6e90\u76ee\u5f55\n\u2502 \u251c\u2500\u2500 images/ # \u56fe\u7247\u8d44\u6e90\n\u2502 \u251c\u2500\u2500 css/ # \u6837\u5f0f\u6587\u4ef6\n\u2502 \u251c\u2500\u2500 js/ # \u811a\u672c\u6587\u4ef6\n\u2502 \u2514\u2500\u2500 fonts/ # \u5b57\u4f53\u6587\u4ef6\n\u2514\u2500\u2500 files/ # \u4e0b\u8f7d\u6587\u4ef6\n \u2514\u2500\u2500 sample.pdf # \u793a\u4f8b\u6587\u4ef6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#233","title":"2.3.3 \u57fa\u7840\u914d\u7f6e\u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#2331-mkdocs-yml","title":"2.3.3.1 mkdocs. yml \u7ed3\u6784","text":"\u57fa\u672c\u914d\u7f6e\u6587\u4ef6\u7ed3\u6784\uff1a
YAML# \u7ad9\u70b9\u4fe1\u606f\nsite_name: \u6211\u7684\u6587\u6863\nsite_url: https://example.com/\nsite_author: \u4f5c\u8005\u540d\nsite_description: \u7ad9\u70b9\u63cf\u8ff0\n\n# \u4e3b\u9898\u8bbe\u7f6e\ntheme:\n name: material\n language: zh\n features:\n - navigation.tabs\n - navigation.top\n\n# \u5bfc\u822a\u8bbe\u7f6e\nnav:\n - \u9996\u9875: index.md\n - \u6307\u5357: \n - guide/index.md\n - \u5b89\u88c5: guide/install.md\n - \u4f7f\u7528: guide/usage.md\n\n# Markdown \u6269\u5c55\nmarkdown_extensions:\n - attr_list\n - md_in_html\n - toc:\n permalink: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2332","title":"2.3.3.2 \u6700\u5c0f\u914d\u7f6e\u793a\u4f8b","text":"\u6700\u7b80\u5355\u7684\u914d\u7f6e\u6587\u4ef6\uff1a
YAMLsite_name: \u6211\u7684\u6587\u6863\ntheme:\n name: material\n
"},{"location":"Tools/Blog/Mkdocs_Material/#2333","title":"2.3.3.3 \u914d\u7f6e\u6587\u4ef6\u8bed\u6cd5","text":"YAML \u8bed\u6cd5\u8981\u70b9\uff1a
YAML# \u5b57\u7b26\u4e32\ntitle: \u6211\u7684\u6587\u6863\n\n# \u5217\u8868\nplugins:\n - search\n - tags\n\n# \u5bf9\u8c61\ntheme:\n name: material\n features:\n - navigation.tabs\n\n# \u591a\u884c\u5b57\u7b26\u4e32\ndescription: >\n \u8fd9\u662f\u4e00\u4e2a\n \u591a\u884c\u63cf\u8ff0\n \u793a\u4f8b\n\n# \u951a\u70b9\u5f15\u7528\ncopyright: ©right 2024 My Docs\nfooter:\n copyright: *copyright\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3-mkdocs","title":"3 MkDocs \u6838\u5fc3\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#31","title":"3.1 \u7ad9\u70b9\u4fe1\u606f\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#311-site_name","title":"3.1.1 site_name \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3111","title":"3.1.1.1 \u547d\u540d\u89c4\u8303","text":"\u7f51\u7ad9\u540d\u79f0\u662f\u7ad9\u70b9\u7684\u7b2c\u4e00\u5370\u8c61\uff0c\u5e94\u9075\u5faa\u4ee5\u4e0b\u89c4\u8303\uff1a
YAML# \u63a8\u8350\u7684\u547d\u540d\u65b9\u5f0f\nsite_name: \u6280\u672f\u6587\u6863\u4e2d\u5fc3\nsite_name: Developer Hub\nsite_name: API Documentation\n\n# \u907f\u514d\u7684\u547d\u540d\u65b9\u5f0f\nsite_name: docs # \u592a\u8fc7\u7b80\u5355\nsite_name: My Doc Site # \u4e0d\u591f\u4e13\u4e1a\nsite_name: TEST # \u7f3a\u4e4f\u63cf\u8ff0\u6027\n
\u547d\u540d\u5efa\u8bae\uff1a
\u53ef\u4ee5\u901a\u8fc7\u914d\u7f6e\u5b9e\u73b0\u591a\u8bed\u8a00\u7ad9\u70b9\uff1a
YAML# \u57fa\u7840\u914d\u7f6e\nsite_name: My Documentation\ntheme:\n language: zh\n\n# \u591a\u8bed\u8a00\u914d\u7f6e\u793a\u4f8b\nextra:\n alternate:\n - name: English\n link: /en/ \n lang: en\n - name: \u4e2d\u6587\n link: /zh/\n lang: zh\n\n# \u8bed\u8a00\u7279\u5b9a\u7684\u7ad9\u70b9\u540d\u79f0\nsite_name:\n en: My Documentation\n zh: \u6211\u7684\u6587\u6863\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3113-seo","title":"3.1.1.3 SEO \u4f18\u5316","text":"\u901a\u8fc7\u5408\u9002\u7684\u7ad9\u70b9\u540d\u79f0\u63d0\u5347 SEO\uff1a
YAML# SEO \u4f18\u5316\u914d\u7f6e\nsite_name: ProductName Documentation | CompanyName\nextra:\n meta:\n - name: robots\n content: 'index, follow'\n - name: keywords\n content: 'docs, documentation, technical, api'\n
"},{"location":"Tools/Blog/Mkdocs_Material/#312-site_url","title":"3.1.2 site_url \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3121-url","title":"3.1.2.1 URL \u683c\u5f0f\u8981\u6c42","text":"YAML# \u6b63\u786e\u7684 URL \u683c\u5f0f\nsite_url: https://example.com/docs/\nsite_url: https://docs.example.com/\n\n# \u907f\u514d\u7684\u683c\u5f0f\nsite_url: http://example.com/docs # \u7f3a\u5c11\u5c3e\u90e8\u659c\u6760\nsite_url: example.com/docs/ # \u7f3a\u5c11\u534f\u8bae\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3122","title":"3.1.2.2 \u57fa\u7840\u8def\u5f84\u914d\u7f6e","text":"YAML# \u6839\u76ee\u5f55\u90e8\u7f72\nsite_url: https://example.com/\n\n# \u5b50\u76ee\u5f55\u90e8\u7f72\nsite_url: https://example.com/docs/\nuse_directory_urls: true # \u63a8\u8350\u8bbe\u7f6e\n\n# \u672c\u5730\u5f00\u53d1\nsite_url: http://localhost:8000/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3123","title":"3.1.2.3 \u5b50\u76ee\u5f55\u90e8\u7f72\u914d\u7f6e","text":"YAML# GitHub Pages \u5b50\u76ee\u5f55\u90e8\u7f72\nsite_url: https://username.github.io/repository/\n\n# \u81ea\u5b9a\u4e49\u57df\u540d\u5b50\u76ee\u5f55\nsite_url: https://docs.example.com/project/\nextra:\n base_path: /project/ # \u5982\u679c\u9700\u8981\n
"},{"location":"Tools/Blog/Mkdocs_Material/#313-site_author","title":"3.1.3 site_author \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3131","title":"3.1.3.1 \u4f5c\u8005\u4fe1\u606f\u8bbe\u7f6e","text":"YAML# \u57fa\u7840\u4f5c\u8005\u4fe1\u606f\nsite_author: John Doe\n\n# \u6269\u5c55\u4f5c\u8005\u4fe1\u606f\nextra:\n author:\n name: John Doe\n email: john@example.com\n website: https://johndoe.com\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3132","title":"3.1.3.2 \u7248\u6743\u4fe1\u606f","text":"YAML# \u7248\u6743\u58f0\u660e\ncopyright: \"© 2024 John Doe\"\n\n# \u9ad8\u7ea7\u7248\u6743\u914d\u7f6e\nextra:\n copyright:\n author: John Doe\n year: 2024\n license: CC BY-NC-SA 4.0\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3133-meta","title":"3.1.3.3 meta \u4fe1\u606f","text":"YAML# meta \u4fe1\u606f\u914d\u7f6e\nextra:\n meta:\n - name: author\n content: John Doe\n - name: contact\n content: contact@example.com\n - property: article:author\n content: https://example.com/author\n
"},{"location":"Tools/Blog/Mkdocs_Material/#314-site_description","title":"3.1.4 site_description \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3141-seo","title":"3.1.4.1 SEO \u63cf\u8ff0","text":"YAML# \u57fa\u7840\u63cf\u8ff0\nsite_description: \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\uff0c\u63d0\u4f9b\u8be6\u7ec6\u7684API\u6587\u6863\u3001\u4f7f\u7528\u6307\u5357\u548c\u6700\u4f73\u5b9e\u8df5\u3002\n\n# \u591a\u8bed\u8a00\u63cf\u8ff0\nextra:\n descriptions:\n en: Comprehensive technical documentation center\n zh: \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3142","title":"3.1.4.2 \u5173\u952e\u8bcd\u8bbe\u7f6e","text":"YAML# \u901a\u8fc7 meta \u6807\u7b7e\u8bbe\u7f6e\u5173\u952e\u8bcd\nextra:\n meta:\n - name: keywords\n content: MkDocs, documentation, technical docs, API, guides\n - name: description\n content: >-\n \u5168\u9762\u7684\u6280\u672f\u6587\u6863\u4e2d\u5fc3\uff0c\u5305\u542b\u8be6\u7ec6\u7684API\u6587\u6863\u3001\n \u4f7f\u7528\u6307\u5357\u548c\u6700\u4f73\u5b9e\u8df5\u793a\u4f8b\u3002\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3143","title":"3.1.4.3 \u7ad9\u70b9\u6458\u8981","text":"YAML# \u5b8c\u6574\u7684\u7ad9\u70b9\u4fe1\u606f\u914d\u7f6e\u793a\u4f8b\nsite_name: \u6280\u672f\u6587\u6863\u4e2d\u5fc3\nsite_description: >-\n \u63d0\u4f9b\u5168\u9762\u7684\u6280\u672f\u6587\u6863\u3001API\u53c2\u8003\u548c\u4f7f\u7528\u6307\u5357\uff0c\n \u5e2e\u52a9\u5f00\u53d1\u8005\u5feb\u901f\u4e0a\u624b\u548c\u6df1\u5165\u4e86\u89e3\u4ea7\u54c1\u529f\u80fd\u3002\nsite_author: \u5f00\u53d1\u56e2\u961f\nsite_url: https://docs.example.com/\n\nextra:\n meta:\n - name: keywords\n content: \u6280\u672f\u6587\u6863, API\u6587\u6863, \u5f00\u53d1\u6307\u5357, \u6700\u4f73\u5b9e\u8df5\n - name: author\n content: \u5f00\u53d1\u56e2\u961f\n - name: robots\n content: index, follow\n\n analytics:\n gtag: G-XXXXXXXXXX\n\ncopyright: \"© 2024 Example Company\"\n
"},{"location":"Tools/Blog/Mkdocs_Material/#315","title":"3.1.5 \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5","text":"SEO \u4f18\u5316\u5efa\u8bae\uff1a - \u4f7f\u7528\u6e05\u6670\u7684\u7ad9\u70b9\u540d\u79f0 - \u7f16\u5199\u6709\u5438\u5f15\u529b\u7684\u63cf\u8ff0 - \u5305\u542b\u76f8\u5173\u5173\u952e\u8bcd - \u786e\u4fdd URL \u7ed3\u6784\u5408\u7406
\u591a\u8bed\u8a00\u652f\u6301\uff1a - \u4e3a\u6bcf\u79cd\u8bed\u8a00\u63d0\u4f9b\u72ec\u7acb\u63cf\u8ff0 - \u4f7f\u7528\u6b63\u786e\u7684\u8bed\u8a00\u4ee3\u7801 - \u8bbe\u7f6e\u5408\u9002\u7684\u5b57\u7b26\u7f16\u7801
\u7248\u672c\u63a7\u5236\uff1a - \u8bb0\u5f55\u914d\u7f6e\u66f4\u6539 - \u4f7f\u7528\u7248\u672c\u6ce8\u91ca - \u5b9a\u671f\u66f4\u65b0\u7ad9\u70b9\u4fe1\u606f
\u53ef\u7ef4\u62a4\u6027\uff1a - \u4f7f\u7528\u6e05\u6670\u7684\u914d\u7f6e\u7ed3\u6784 - \u6dfb\u52a0\u5fc5\u8981\u7684\u6ce8\u91ca - \u4fdd\u6301\u914d\u7f6e\u6587\u4ef6\u6574\u6d01
\u6700\u57fa\u672c\u7684\u5bfc\u822a\u914d\u7f6e\u793a\u4f8b\uff1a
YAMLnav:\n - Home: index.md\n - About: about.md\n - Contact: contact.md\n
\u66f4\u590d\u6742\u7684\u5206\u7ec4\u793a\u4f8b\uff1a
YAMLnav:\n - \u9996\u9875: index.md\n - \u7528\u6237\u6307\u5357:\n - \u4ecb\u7ecd: guide/introduction.md\n - \u5feb\u901f\u5f00\u59cb: guide/getting-started.md\n - \u57fa\u7840\u6559\u7a0b: guide/basics.md\n - API \u6587\u6863:\n - \u6982\u89c8: api/overview.md\n - \u63a5\u53e3\u8bf4\u660e: api/reference.md\n - \u5e38\u89c1\u95ee\u9898: faq.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3212","title":"3.2.1.2 \u5206\u7c7b\u7ec4\u7ec7","text":"\u63a8\u8350\u7684\u5206\u7c7b\u65b9\u5f0f\uff1a
YAMLnav:\n - \u5f00\u59cb\u4f7f\u7528:\n - \u7b80\u4ecb: getting-started/introduction.md\n - \u5b89\u88c5: getting-started/installation.md\n - \u914d\u7f6e: getting-started/configuration.md\n\n - \u6838\u5fc3\u6982\u5ff5:\n - \u6982\u8ff0: concepts/overview.md\n - \u57fa\u7840\u67b6\u6784: concepts/architecture.md\n - \u5de5\u4f5c\u539f\u7406: concepts/how-it-works.md\n\n - \u9ad8\u7ea7\u6307\u5357:\n - \u81ea\u5b9a\u4e49\u4e3b\u9898: advanced/custom-theme.md\n - \u63d2\u4ef6\u5f00\u53d1: advanced/plugin-development.md\n - \u6027\u80fd\u4f18\u5316: advanced/performance.md\n\n - \u53c2\u8003\u6587\u6863:\n - API: reference/api.md\n - \u914d\u7f6e\u9879: reference/configuration.md\n - \u547d\u4ee4\u884c: reference/cli.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3213","title":"3.2.1.3 \u6743\u91cd\u8bbe\u7f6e","text":"\u4f7f\u7528\u6587\u4ef6\u540d\u524d\u7f00\u63a7\u5236\u987a\u5e8f\uff1a
YAMLdocs/\n\u251c\u2500\u2500 01_introduction.md\n\u251c\u2500\u2500 02_installation.md\n\u251c\u2500\u2500 03_configuration.md\n\u2514\u2500\u2500 04_usage.md\n\n# mkdocs.yml\nnav:\n - \u4ecb\u7ecd: 01_introduction.md\n - \u5b89\u88c5: 02_installation.md\n - \u914d\u7f6e: 03_configuration.md\n - \u4f7f\u7528: 04_usage.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#322","title":"3.2.2 \u6587\u4ef6\u7ec4\u7ec7","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3221","title":"3.2.2.1 \u6587\u4ef6\u547d\u540d\u89c4\u8303","text":"\u63a8\u8350\u7684\u547d\u540d\u89c4\u8303\uff1a
Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u9996\u9875\n\u251c\u2500\u2500 getting-started.md # \u77ed\u6a2a\u7ebf\u5206\u9694\n\u251c\u2500\u2500 advanced_usage.md # \u4e0b\u5212\u7ebf\u5206\u9694\uff08\u53ef\u9009\uff09\n\u2514\u2500\u2500 troubleshooting.md # \u5168\u5c0f\u5199\n
\u6587\u4ef6\u547d\u540d\u5efa\u8bae\uff1a
\u6807\u51c6\u76ee\u5f55\u7ed3\u6784\uff1a
Text Onlydocs/\n\u251c\u2500\u2500 index.md # \u7f51\u7ad9\u9996\u9875\n\u251c\u2500\u2500 getting-started/ # \u5165\u95e8\u6307\u5357\n\u2502 \u251c\u2500\u2500 index.md # \u5206\u7c7b\u9996\u9875\n\u2502 \u251c\u2500\u2500 installation.md # \u5b89\u88c5\u8bf4\u660e\n\u2502 \u2514\u2500\u2500 configuration.md # \u914d\u7f6e\u8bf4\u660e\n\u251c\u2500\u2500 user-guide/ # \u7528\u6237\u6307\u5357\n\u2502 \u251c\u2500\u2500 index.md # \u6307\u5357\u9996\u9875\n\u2502 \u251c\u2500\u2500 basic-usage.md # \u57fa\u7840\u7528\u6cd5\n\u2502 \u2514\u2500\u2500 advanced.md # \u9ad8\u7ea7\u7279\u6027\n\u2514\u2500\u2500 api/ # API\u6587\u6863\n \u251c\u2500\u2500 index.md # API\u6982\u89c8\n \u251c\u2500\u2500 endpoints.md # \u63a5\u53e3\u5217\u8868\n \u2514\u2500\u2500 authentication.md # \u8ba4\u8bc1\u8bf4\u660e\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3223","title":"3.2.2.3 \u7d22\u5f15\u6587\u4ef6\u4f7f\u7528","text":"\u6bcf\u4e2a\u76ee\u5f55\u7684 index. md \u793a\u4f8b\uff1a
Markdown# \u7528\u6237\u6307\u5357\n\n\u8fd9\u662f\u7528\u6237\u6307\u5357\u7684\u4e3b\u9875\u9762\uff0c\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9\uff1a\n\n## \u5feb\u901f\u5bfc\u822a\n\n- [\u57fa\u7840\u7528\u6cd5] (basic-usage.md) - \u5165\u95e8\u5fc5\u8bfb\n- [\u9ad8\u7ea7\u7279\u6027] (advanced.md) - \u6df1\u5165\u4e86\u89e3\n\n## \u672c\u8282\u5185\u5bb9\n\n\u6b64\u90e8\u5206\u5c06\u5e2e\u52a9\u60a8\u4e86\u89e3\u4ea7\u54c1\u7684\u6838\u5fc3\u529f\u80fd\u548c\u4f7f\u7528\u65b9\u6cd5...\n
\u5bf9\u5e94\u7684\u5bfc\u822a\u914d\u7f6e\uff1a
YAMLnav:\n - \u7528\u6237\u6307\u5357:\n - \u6982\u8ff0: user-guide/index.md\n - \u57fa\u7840\u7528\u6cd5: user-guide/basic-usage.md\n - \u9ad8\u7ea7\u7279\u6027: user-guide/advanced.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#323","title":"3.2.3 \u591a\u7ea7\u76ee\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3231","title":"3.2.3.1 \u5c42\u7ea7\u7ed3\u6784\u8bbe\u8ba1","text":"\u590d\u6742\u7684\u591a\u7ea7\u76ee\u5f55\u793a\u4f8b\uff1a
YAMLnav:\n - \u9996\u9875: index.md\n - \u5165\u95e8\u6307\u5357:\n - \u6982\u8ff0: getting-started/index.md\n - \u57fa\u7840:\n - \u5b89\u88c5: getting-started/basics/installation.md\n - \u914d\u7f6e: getting-started/basics/configuration.md\n - \u8fdb\u9636:\n - \u81ea\u5b9a\u4e49: getting-started/advanced/customization.md\n - \u4f18\u5316: getting-started/advanced/optimization.md\n - \u5f00\u53d1\u6587\u6863:\n - \u6982\u8ff0: development/index.md\n - API:\n - \u8ba4\u8bc1: development/api/authentication.md\n - \u63a5\u53e3: development/api/endpoints.md\n - SDK:\n - Python: development/sdk/python.md\n - JavaScript: development/sdk/javascript.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3232","title":"3.2.3.2 \u5bfc\u822a\u6df1\u5ea6\u63a7\u5236","text":"YAMLtheme:\n name: material\n features:\n - navigation.sections # \u663e\u793a\u7ae0\u8282\n - navigation.expand # \u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u4f7f\u7528\u76ee\u5f55\u7d22\u5f15\n - toc.integrate # \u96c6\u6210\u76ee\u5f55\n\nmarkdown_extensions:\n - toc:\n permalink: true\n toc_depth: 3 # \u63a7\u5236\u76ee\u5f55\u6df1\u5ea6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3233","title":"3.2.3.3 \u6298\u53e0\u914d\u7f6e","text":"Material \u4e3b\u9898\u7684\u6298\u53e0\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - navigation.sections # \u663e\u793a\u5206\u533a\n - navigation.expand # \u9ed8\u8ba4\u5c55\u5f00\n - navigation.indexes # \u4f7f\u7528\u7d22\u5f15\u9875\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n\n # \u5bfc\u822a\u680f\u8bbe\u7f6e\n nav_style: dark # \u5bfc\u822a\u680f\u6837\u5f0f\n collapse_navigation: true # \u6298\u53e0\u5bfc\u822a\n sticky_navigation: true # \u56fa\u5b9a\u5bfc\u822a\n
"},{"location":"Tools/Blog/Mkdocs_Material/#324","title":"3.2.4 \u5bfc\u822a\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5","text":"\u7ed3\u6784\u8bbe\u8ba1\u539f\u5219\uff1a - \u4fdd\u6301\u5c42\u7ea7\u6e05\u6670 - \u63a7\u5236\u5bfc\u822a\u6df1\u5ea6\uff08\u5efa\u8bae\u4e0d\u8d85\u8fc7 3 \u5c42\uff09 - \u76f8\u5173\u5185\u5bb9\u5206\u7ec4 - \u4f7f\u7528\u76f4\u89c2\u7684\u547d\u540d
\u6587\u4ef6\u7ec4\u7ec7\uff1a - \u4f7f\u7528\u6709\u610f\u4e49\u7684\u76ee\u5f55\u540d - \u4fdd\u6301\u6587\u4ef6\u7ed3\u6784\u6574\u6d01 - \u5408\u7406\u4f7f\u7528\u7d22\u5f15\u6587\u4ef6 - \u9075\u5faa\u4e00\u81f4\u7684\u547d\u540d\u89c4\u8303
\u7528\u6237\u4f53\u9a8c\uff1a - \u63d0\u4f9b\u6e05\u6670\u7684\u5bfc\u822a\u8def\u5f84 - \u6dfb\u52a0\u5408\u9002\u7684\u63cf\u8ff0 - \u8003\u8651\u79fb\u52a8\u7aef\u663e\u793a - \u4f18\u5316\u5bfc\u822a\u54cd\u5e94\u901f\u5ea6
\u7ef4\u62a4\u5efa\u8bae\uff1a - \u5b9a\u671f\u68c0\u67e5\u6b7b\u94fe\u63a5 - \u66f4\u65b0\u5bfc\u822a\u7ed3\u6784 - \u4fdd\u6301\u6587\u6863\u540c\u6b65 - \u6536\u96c6\u7528\u6237\u53cd\u9988
nav:\n - \u53ef\u89c1\u9875\u9762: visible.md\n - !hidden \u9690\u85cf\u9875\u9762: hidden.md\n
nav:\n - \u6587\u6863: index.md\n - GitHub: https://github.com/your/repo\n - \u793e\u533a: \n - \u8bba\u575b: https://forum.example.com\n - \u535a\u5ba2: https://blog.example.com\n
nav:\n - \u5f00\u59cb: \n - \u6982\u8ff0: getting-started/index.md\n - \u5feb\u901f\u5165\u95e8: getting-started/quickstart.md\n - \u540c\u4e00\u6587\u4ef6\u4e0d\u540c\u5165\u53e3: !alias getting-started/quickstart.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#33-markdown","title":"3.3 Markdown \u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#331","title":"3.3.1 \u57fa\u7840\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3311-meta","title":"3.3.1.1 meta \u6269\u5c55","text":"\u652f\u6301\u5728 Markdown \u6587\u4ef6\u5934\u90e8\u6dfb\u52a0\u5143\u6570\u636e\uff1a
YAML# mkdocs.yml \u914d\u7f6e\nmarkdown_extensions:\n - meta\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown---\ntitle: \u6211\u7684\u9875\u9762\u6807\u9898\ndescription: \u9875\u9762\u63cf\u8ff0\nauthor: \u4f5c\u8005\u540d\ndate: 2024-01-01\n---\n\n# \u6b63\u6587\u5185\u5bb9\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3312-toc","title":"3.3.1.2 toc \u6269\u5c55","text":"\u81ea\u52a8\u751f\u6210\u76ee\u5f55\uff1a
YAMLmarkdown_extensions:\n - toc:\n permalink: true # \u6dfb\u52a0\u6bb5\u843d\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n separator: \"_\" # \u6807\u9898\u951a\u70b9\u5206\u9694\u7b26\n title: \"\u76ee\u5f55\" # \u76ee\u5f55\u6807\u9898\n slugify: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower} # URL \u8f6c\u6362\u89c4\u5219\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown[TOC]\n\n# \u4e00\u7ea7\u6807\u9898\n## \u4e8c\u7ea7\u6807\u9898\n### \u4e09\u7ea7\u6807\u9898\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3313-tables","title":"3.3.1.3 tables \u6269\u5c55","text":"\u589e\u5f3a\u7684\u8868\u683c\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - tables\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown| \u529f\u80fd | \u57fa\u7840\u7248 | \u4e13\u4e1a\u7248 |\n|-----|:------:|-------:|\n| \u529f\u80fdA | \u2713 | \u2713 |\n| \u529f\u80fdB | \u2717 | \u2713 |\n| \u529f\u80fdC | \u2717 | \u2713 |\n\n: \u8868\u683c\u6807\u9898 {.class-name}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#332-pymdown-extensions","title":"3.3.2 PyMdown Extensions","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3321-superfences","title":"3.3.2.1 superfences \u914d\u7f6e","text":"\u589e\u5f3a\u7684\u4ee3\u7801\u5757\u529f\u80fd\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_div_format\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown```python title=\"example.py\" linenums=\"1\" hl_lines=\"2 3\"\ndef hello_world():\n message = \"Hello, World!\"\n print(message)\n return message\n```\n\n```mermaid\ngraph LR\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B --> |Yes| C[\u6267\u884c]\n B --> |No| D[\u8df3\u8fc7]\n```\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3322-emoji","title":"3.3.2.2 emoji \u652f\u6301","text":"\u6dfb\u52a0\u8868\u60c5\u7b26\u53f7\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - pymdownx.emoji:\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown:smile: :heart: :thumbsup:\n\n:fontawesome-brands-github: GitHub\n:material-account: \u7528\u6237\n:octicons-repo-16: \u4ed3\u5e93\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3323-tasklist","title":"3.3.2.3 tasklist \u529f\u80fd","text":"\u4efb\u52a1\u5217\u8868\u652f\u6301\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tasklist:\n custom_checkbox: true # \u81ea\u5b9a\u4e49\u590d\u9009\u6846\u6837\u5f0f\n clickable_checkbox: true # \u53ef\u70b9\u51fb\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown- [x] \u5df2\u5b8c\u6210\u4efb\u52a1\n- [ ] \u672a\u5b8c\u6210\u4efb\u52a1\n - [x] \u5b50\u4efb\u52a1 1\n - [ ] \u5b50\u4efb\u52a1 2\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3324-pymdown","title":"3.3.2.4 \u5176\u4ed6\u5e38\u7528 PyMdown \u6269\u5c55","text":"YAMLmarkdown_extensions:\n - pymdownx.highlight # \u4ee3\u7801\u9ad8\u4eae\n - pymdownx.inlinehilite # \u884c\u5185\u4ee3\u7801\u9ad8\u4eae\n - pymdownx.snippets # \u4ee3\u7801\u7247\u6bb5\n - pymdownx.magiclink # \u81ea\u52a8\u94fe\u63a5\n - pymdownx.mark # ==\u6807\u8bb0==\n - pymdownx.critic # \u7f16\u8f91\u6807\u8bb0\n - pymdownx.tilde # \u5220\u9664\u7ebf\n - pymdownx.caret # \u4e0a\u6807\n - pymdownx.keys # \u952e\u76d8\u6309\u952e\n - pymdownx.tabbed # \u6807\u7b7e\u9875\n
"},{"location":"Tools/Blog/Mkdocs_Material/#333","title":"3.3.3 \u81ea\u5b9a\u4e49\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3331","title":"3.3.3.1 \u6269\u5c55\u5f00\u53d1\u57fa\u7840","text":"\u521b\u5efa\u81ea\u5b9a\u4e49\u6269\u5c55\uff1a
Python# custom_extension.py\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\nclass CustomPreprocessor(Preprocessor):\n def run(self, lines):\n new_lines = []\n for line in lines:\n new_lines.append(line.replace('[[', '**').replace(']]', '**'))\n return new_lines\n\nclass CustomExtension(Extension):\n def extendMarkdown(self, md):\n md.preprocessors.register(CustomPreprocessor(md), 'custom_preprocessor', 175)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#34","title":"3.4 \u5e38\u7528\u6269\u5c55\u793a\u4f8b","text":"from markdown.extensions import Extension\nfrom markdown.treeprocessors import Treeprocessor\n\nclass CustomAttributesTreeprocessor(Treeprocessor):\n def run(self, root):\n for elem in root.iter():\n if 'class' in elem.attrib:\n elem.set('data-custom', 'value')\n\nclass CustomAttributesExtension(Extension):\n def extendMarkdown(self, md):\n md.treeprocessors.register(\n CustomAttributesTreeprocessor(md), 'custom_attributes', 15\n )\n
from markdown.extensions import Extension\nfrom markdown.blockprocessors import BlockProcessor\nimport re\n\nclass CustomContainerProcessor(BlockProcessor):\n RE = re.compile(r':{3,}\\ *(warning|note|tip)\\ *')\n\n def run(self, parent, blocks):\n block = blocks.pop(0)\n m = self.RE.match(block)\n\n if m:\n container_type = m.group(1)\n div = etree.SubElement(parent, 'div')\n div.set('class', f'custom-container {container_type}')\n\n # \u5904\u7406\u5bb9\u5668\u5185\u5bb9\n self.parser.parseChunk(div, block[m.end():])\n\nclass CustomContainerExtension(Extension):\n def extendMarkdown(self, md):\n md.parser.blockprocessors.register(\n CustomContainerProcessor(md.parser), 'custom_container', 175\n )\n
"},{"location":"Tools/Blog/Mkdocs_Material/#341","title":"3.4.1 \u6269\u5c55\u914d\u7f6e\u65b9\u6cd5","text":"\u5728 mkdocs.yml
\u4e2d\u914d\u7f6e\u81ea\u5b9a\u4e49\u6269\u5c55\uff1a
markdown_extensions:\n - custom_extension:\n option1: value1\n option2: value2\n\nextra_css:\n - css/custom_extension.css\n\nextra_javascript:\n - js/custom_extension.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#342","title":"3.4.2 \u6269\u5c55\u7ec4\u5408\u63a8\u8350","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3421","title":"3.4.2.1 \u57fa\u7840\u6587\u6863\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n - meta\n - toc:\n permalink: true\n - tables\n - attr_list\n - def_list\n - footnotes\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3422","title":"3.4.2.2 \u589e\u5f3a\u529f\u80fd\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_div_format\n - pymdownx.highlight:\n anchor_linenums: true\n - pymdownx.inlinehilite\n - pymdownx.snippets\n - pymdownx.tasklist:\n custom_checkbox: true\n - pymdownx.emoji:\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n
"},{"location":"Tools/Blog/Mkdocs_Material/#343","title":"3.4.3 \u5b8c\u6574\u63a8\u8350\u914d\u7f6e","text":"YAMLmarkdown_extensions:\n # Python Markdown\n - meta\n - toc:\n permalink: true\n toc_depth: 4\n - tables\n - attr_list\n - def_list\n - md_in_html\n - footnotes\n\n # Python Markdown Extensions\n - pymdownx.superfences\n - pymdownx.highlight\n - pymdownx.inlinehilite\n - pymdownx.snippets\n - pymdownx.tasklist\n - pymdownx.emoji\n - pymdownx.mark\n - pymdownx.critic\n - pymdownx.keys\n - pymdownx.tilde\n - pymdownx.caret\n - pymdownx.details\n - pymdownx.magiclink\n - pymdownx.tabbed:\n alternate_style: true\n\n # \u81ea\u5b9a\u4e49\u6269\u5c55\n - custom_extension:\n custom_option: value\n
"},{"location":"Tools/Blog/Mkdocs_Material/#344","title":"3.4.4 \u4f7f\u7528\u5efa\u8bae","text":"\u6027\u80fd\u8003\u8651\uff1a - \u53ea\u542f\u7528\u9700\u8981\u7684\u6269\u5c55 - \u6ce8\u610f\u6269\u5c55\u4e4b\u95f4\u7684\u4f9d\u8d56\u5173\u7cfb - \u63a7\u5236\u6269\u5c55\u6570\u91cf
\u517c\u5bb9\u6027\uff1a - \u6d4b\u8bd5\u6269\u5c55\u7ec4\u5408 - \u68c0\u67e5\u79fb\u52a8\u7aef\u663e\u793a - \u9a8c\u8bc1\u4e0d\u540c\u6d4f\u89c8\u5668
\u7ef4\u62a4\u5efa\u8bae\uff1a - \u8bb0\u5f55\u6269\u5c55\u914d\u7f6e - \u4fdd\u6301\u7248\u672c\u66f4\u65b0 - \u76d1\u63a7\u6027\u80fd\u5f71\u54cd
\u901a\u8fc7 pip \u5b89\u88c5\u63d2\u4ef6\uff1a
Bash# \u5b89\u88c5\u5355\u4e2a\u63d2\u4ef6\npip install mkdocs-git-revision-date-localized-plugin\n\n# \u5b89\u88c5\u591a\u4e2a\u63d2\u4ef6\npip install mkdocs-minify-plugin mkdocs-git-authors-plugin\n
\u57fa\u7840\u63d2\u4ef6\u914d\u7f6e\uff1a
YAML# mkdocs.yml\nplugins:\n - search # \u9ed8\u8ba4\u63d2\u4ef6\n - git-revision-date-localized:\n enable_creation_date: true\n - minify:\n minify_html: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3512","title":"3.5.1.2 \u914d\u7f6e\u8bed\u6cd5","text":"\u63d2\u4ef6\u914d\u7f6e\u7684\u51e0\u79cd\u65b9\u5f0f\uff1a
YAML# 1. \u7b80\u5355\u542f\u7528\u63d2\u4ef6\uff08\u4f7f\u7528\u9ed8\u8ba4\u914d\u7f6e\uff09\nplugins:\n - search\n - tags\n\n# 2. \u7981\u7528\u9ed8\u8ba4\u63d2\u4ef6\nplugins:\n - search: false\n\n# 3. \u5e26\u914d\u7f6e\u7684\u63d2\u4ef6\nplugins:\n - search:\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+'\n\n# 4. \u591a\u5b9e\u4f8b\u63d2\u4ef6\nplugins:\n - search:\n name: search_1\n config: value\n - search:\n name: search_2\n config: value\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3513","title":"3.5.1.3 \u4f18\u5148\u7ea7\u63a7\u5236","text":"\u63d2\u4ef6\u6267\u884c\u987a\u5e8f\u63a7\u5236\uff1a
YAMLplugins:\n - search\n - git-revision-date-localized:\n priority: 80\n - minify:\n priority: 90\n - tags:\n priority: 70\n
"},{"location":"Tools/Blog/Mkdocs_Material/#352","title":"3.5.2 \u5e38\u7528\u63d2\u4ef6\u4ecb\u7ecd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3521","title":"3.5.2.1 \u5b98\u65b9\u63d2\u4ef6","text":"plugins:\n - search:\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+'\n min_search_length: 2\n prebuild_index: true\n indexing:\n - full_sections: false\n - headings: true\n - content: true\n
plugins:\n - tags:\n tags_file: tags.md\n tags_extra_files:\n cloud: cloud_tags.md\n list: tag_list.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3522","title":"3.5.2.2 \u793e\u533a\u63d2\u4ef6\u63a8\u8350","text":"plugins:\n - git-revision-date-localized:\n type: timeago\n enable_creation_date: true\n exclude:\n - index.md\n timezone: Asia/Shanghai\n locale: zh\n
plugins:\n - minify:\n minify_html: true\n minify_js: true\n minify_css: true\n htmlmin_opts:\n remove_comments: true\n
plugins:\n - social:\n cards: true\n cards_color:\n fill: \"#0FF1CE\"\n text: \"#FFFFFF\"\n
plugins:\n - macros:\n module_name: macros\n include_dir: include\n include_yaml:\n - variables.yml\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3523","title":"3.5.2.3 \u5b9e\u7528\u63d2\u4ef6\u96c6\u5408","text":"YAMLplugins:\n # \u6838\u5fc3\u529f\u80fd\n - search\n - tags\n\n # \u7248\u672c\u63a7\u5236\n - git-revision-date-localized\n - git-authors\n\n # \u6027\u80fd\u4f18\u5316\n - minify\n - optimize\n\n # \u5185\u5bb9\u589e\u5f3a\n - social\n - macros\n - blogging\n\n # \u591a\u8bed\u8a00\u652f\u6301\n - i18n\n - translations\n\n # \u56fe\u7247\u5904\u7406\n - glightbox\n - img2fig\n\n # \u7edf\u8ba1\u5206\u6790\n - statistics\n - pdf-export\n
"},{"location":"Tools/Blog/Mkdocs_Material/#353","title":"3.5.3 \u63d2\u4ef6\u7ec4\u5408\u4f7f\u7528","text":""},{"location":"Tools/Blog/Mkdocs_Material/#3531","title":"3.5.3.1 \u57fa\u7840\u7ec4\u5408\u65b9\u6848","text":"\u9002\u5408\u4e00\u822c\u6587\u6863\u9879\u76ee\uff1a
YAMLplugins:\n - search:\n lang: zh\n separator: '[\\s\\-\\.]+'\n\n - git-revision-date-localized:\n enable_creation_date: true\n type: date\n\n - minify:\n minify_html: true\n\n - glightbox:\n touchNavigation: true\n loop: false\n effect: zoom\n width: 100%\n height: auto\n zoomable: true\n draggable: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3532","title":"3.5.3.2 \u535a\u5ba2\u7f51\u7ad9\u65b9\u6848","text":"\u9002\u5408\u535a\u5ba2\u7c7b\u7f51\u7ad9\uff1a
YAMLplugins:\n - blog:\n blog_dir: blog\n post_url_format: \"{slug}\"\n post_excerpt: optional\n\n - social:\n cards: true\n cards_dir: assets/social\n\n - tags:\n tags_file: tags.md\n\n - rss:\n abstract_chars_count: 160\n date_from_meta: true\n\n - statistics:\n page_check: true\n page_count: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#3533","title":"3.5.3.3 \u6280\u672f\u6587\u6863\u65b9\u6848","text":"\u9002\u5408\u5927\u578b\u6280\u672f\u6587\u6863\uff1a
YAMLplugins:\n - search:\n separator: '[\\s\\-\\.]+'\n min_search_length: 2\n lang:\n - en\n - zh\n prebuild_index: true\n\n - git-revision-date-localized:\n type: timeago\n enable_creation_date: true\n\n - minify:\n minify_html: true\n minify_js: true\n minify_css: true\n\n - macros:\n module_name: includes.macros\n include_yaml:\n - includes/variables.yml\n\n - pdf-export:\n combined: true\n combined_output_path: pdf/document.pdf\n
"},{"location":"Tools/Blog/Mkdocs_Material/#354","title":"3.5.4 \u6027\u80fd\u4f18\u5316\u5efa\u8bae","text":"\u63d2\u4ef6\u9009\u62e9\uff1a - \u53ea\u542f\u7528\u5fc5\u8981\u7684\u63d2\u4ef6 - \u907f\u514d\u529f\u80fd\u91cd\u590d\u7684\u63d2\u4ef6 - \u6ce8\u610f\u63d2\u4ef6\u95f4\u7684\u4f9d\u8d56\u5173\u7cfb
\u914d\u7f6e\u4f18\u5316\uff1a
plugins:\n - search:\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n - minify:\n cache: true # \u542f\u7528\u7f13\u5b58\n cache_dir: .cache # \u7f13\u5b58\u76ee\u5f55\n - optimize: # \u8d44\u6e90\u4f18\u5316\n cache: true\n
plugins:\n # \u5e76\u884c\u5904\u7406\u63d2\u4ef6\n - parallel:\n workers: 4\n # \u7f13\u5b58\u63d2\u4ef6\n - cache:\n enabled: true\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4-material","title":"4 Material \u4e3b\u9898\u5b8c\u5168\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#41","title":"4.1 \u57fa\u7840\u5916\u89c2","text":""},{"location":"Tools/Blog/Mkdocs_Material/#411","title":"4.1.1 \u914d\u8272\u65b9\u6848","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4111","title":"4.1.1.1 \u9884\u8bbe\u4e3b\u9898\u8272","text":"Material \u4e3b\u9898\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u9884\u8bbe\u989c\u8272\uff1a
YAMLtheme:\n name: material\n palette:\n primary: indigo # \u4e3b\u8272\u8c03\n accent: pink # \u5f3a\u8c03\u8272\n\n# \u53ef\u7528\u7684\u4e3b\u9898\u8272\uff1a\n# red, pink, purple, deep purple, indigo, blue, light blue, \n# cyan, teal, green, light green, lime, yellow, amber, \n# orange, deep orange, brown, grey, blue grey\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4112","title":"4.1.1.2 \u81ea\u5b9a\u4e49\u914d\u8272","text":"\u5b8c\u6574\u7684\u81ea\u5b9a\u4e49\u914d\u8272\u914d\u7f6e\uff1a
YAMLtheme:\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4113-css","title":"4.1.1.3 \u81ea\u5b9a\u4e49 CSS \u53d8\u91cf","text":"\u521b\u5efa docs/stylesheets/extra.css
\uff1a
:root {\n --md-primary-fg-color: #2196f3;\n --md-primary-fg-color--light: #64b5f6;\n --md-primary-fg-color--dark: #1976d2;\n --md-accent-fg-color: #2196f3;\n}\n\n[data-md-color-scheme=\"slate\"] {\n --md-primary-fg-color: #90caf9;\n --md-primary-fg-color--light: #e3f2fd;\n --md-primary-fg-color--dark: #42a5f5;\n}\n
\u5728 mkdocs.yml
\u4e2d\u5f15\u5165\uff1a
extra_css:\n - stylesheets/extra.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#412","title":"4.1.2 \u4e3b\u9898\u5207\u6362","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4121","title":"4.1.2.1 \u57fa\u7840\u5207\u6362\u914d\u7f6e","text":"YAMLtheme:\n name: material\n palette:\n # \u914d\u7f6e\u5207\u6362\u6309\u94ae\n - scheme: default\n toggle:\n icon: material/brightness-7 \n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n primary: indigo\n accent: indigo\n\n - scheme: slate\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n primary: indigo\n accent: indigo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4122","title":"4.1.2.2 \u9ad8\u7ea7\u5207\u6362\u529f\u80fd","text":"\u6dfb\u52a0\u81ea\u5b9a\u4e49\u5207\u6362\u903b\u8f91\uff1a
YAMLextra_javascript:\n - javascripts/theme-switch.js\n
theme-switch.js
\u5185\u5bb9\uff1a
document.addEventListener('DOMContentLoaded', function() {\n // \u83b7\u53d6\u7cfb\u7edf\u4e3b\u9898\u504f\u597d\n const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');\n\n // \u76d1\u542c\u7cfb\u7edf\u4e3b\u9898\u53d8\u5316\n prefersDark.addListener((e) => {\n const theme = e.matches ? 'slate' : 'default';\n document.body.setAttribute('data-md-color-scheme', theme);\n });\n\n // \u521d\u59cb\u5316\u4e3b\u9898\n const theme = prefersDark.matches ? 'slate' : 'default';\n document.body.setAttribute('data-md-color-scheme', theme);\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#413","title":"4.1.3 \u56fe\u6807\u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4131","title":"4.1.3.1 \u7f51\u7ad9\u56fe\u6807","text":"\u914d\u7f6e\u7f51\u7ad9\u56fe\u6807\u548c Logo\uff1a
YAMLtheme:\n icon:\n logo: material/book-open-page-variant # \u7f51\u7ad9 Logo\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n\n favicon: assets/favicon.png # \u7f51\u7ad9\u56fe\u6807\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4132","title":"4.1.3.2 \u529f\u80fd\u56fe\u6807","text":"\u4e3a\u4e0d\u540c\u529f\u80fd\u914d\u7f6e\u56fe\u6807\uff1a
YAMLtheme:\n icon:\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n edit: material/pencil # \u7f16\u8f91\u56fe\u6807\n view: material/eye # \u67e5\u770b\u56fe\u6807\n admonition:\n note: octicons/tag-16 # \u63d0\u793a\u6846\u56fe\u6807\n abstract: octicons/checklist-16\n info: octicons/info-16\n tip: octicons/squirrel-16\n success: octicons/check-16\n question: octicons/question-16\n warning: octicons/alert-16\n failure: octicons/x-circle-16\n danger: octicons/zap-16\n bug: octicons/bug-16\n example: octicons/beaker-16\n quote: octicons/quote-16\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4133-svg","title":"4.1.3.3 \u81ea\u5b9a\u4e49 SVG \u56fe\u6807","text":"\u6dfb\u52a0\u81ea\u5b9a\u4e49 SVG \u56fe\u6807\uff1a
.icons
\u76ee\u5f55\uff1a.\n\u251c\u2500 .icons/\n\u2502 \u2514\u2500 custom/\n\u2502 \u2514\u2500 logo.svg\n\u2514\u2500 mkdocs.yml\n
theme:\n icon:\n logo: custom/logo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#414-logo","title":"4.1.4 Logo \u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4141-logo","title":"4.1.4.1 \u57fa\u7840 Logo \u914d\u7f6e","text":"YAMLtheme:\n logo: assets/logo.svg # Logo \u56fe\u7247\n icon:\n logo: material/book # \u6216\u4f7f\u7528\u56fe\u6807\u4f5c\u4e3a Logo\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4142-logo","title":"4.1.4.2 \u54cd\u5e94\u5f0f Logo","text":"\u521b\u5efa\u54cd\u5e94\u5f0f Logo\uff1a
YAMLtheme:\n logo: assets/logo.svg\nextra_css:\n - stylesheets/logo.css\n
logo.css
\u5185\u5bb9\uff1a
/* \u9ed8\u8ba4 Logo */\n.md-logo img {\n width: 40px;\n height: 40px;\n}\n\n/* \u79fb\u52a8\u7aef Logo */\n@media screen and (max-width: 76.1875em) {\n .md-logo img {\n width: 32px;\n height: 32px;\n }\n}\n\n/* \u6697\u8272\u4e3b\u9898 Logo */\n[data-md-color-scheme=\"slate\"] .md-logo img {\n filter: invert(1);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4143-logo","title":"4.1.4.3 Logo \u52a8\u753b\u6548\u679c","text":"\u6dfb\u52a0 Logo \u52a8\u753b\uff1a
CSS.md-logo img {\n transition: transform 0.3s ease;\n}\n\n.md-logo img:hover {\n transform: scale(1.1);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#415","title":"4.1.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n\n # \u8c03\u8272\u677f\u914d\u7f6e\n palette:\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: blue\n accent: blue\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n\n # \u56fe\u6807\u914d\u7f6e\n icon:\n logo: material/book-open-page-variant\n repo: fontawesome/brands/github\n edit: material/pencil\n view: material/eye\n\n # Logo \u914d\u7f6e\n logo: assets/logo.svg\n favicon: assets/favicon.png\n\n# \u989d\u5916\u6837\u5f0f\nextra_css:\n - stylesheets/extra.css\n - stylesheets/logo.css\n\n# \u989d\u5916\u811a\u672c\nextra_javascript:\n - javascripts/theme-switch.js\n\n# \u4e3b\u9898\u7279\u6027\nfeatures:\n - navigation.instant\n - navigation.tracking\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n - navigation.top\n - toc.integrate\n
"},{"location":"Tools/Blog/Mkdocs_Material/#42","title":"4.2 \u5bfc\u822a\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#421","title":"4.2.1 \u9876\u90e8\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4211","title":"4.2.1.1 \u5bfc\u822a\u680f\u6837\u5f0f","text":"\u57fa\u7840\u5bfc\u822a\u680f\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - navigation.tabs # \u542f\u7528\u6807\u7b7e\u5f0f\u5bfc\u822a\n - navigation.sections # \u663e\u793a\u7ae0\u8282\u5bfc\u822a\n - navigation.expand # \u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u7ae0\u8282\u7d22\u5f15\u9875\n
\u81ea\u5b9a\u4e49\u5bfc\u822a\u680f\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/extra.css */\n\n/* \u5bfc\u822a\u680f\u80cc\u666f */\n.md-header {\n background-color: #2196f3;\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n}\n\n/* \u5bfc\u822a\u9879\u6837\u5f0f */\n.md-tabs__link {\n font-size: .8rem;\n margin-top: .4rem;\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-tabs__link--active {\n font-weight: bold;\n border-bottom: 2px solid currentColor;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4212","title":"4.2.1.2 \u56fa\u5b9a\u5bfc\u822a\u680f","text":"\u542f\u7528\u56fa\u5b9a\u5bfc\u822a\uff1a
YAMLtheme:\n features:\n - header.autohide # \u81ea\u52a8\u9690\u85cf\n - navigation.sticky # \u56fa\u5b9a\u5bfc\u822a\n
\u81ea\u5b9a\u4e49\u56fa\u5b9a\u5bfc\u822a\u884c\u4e3a\uff1a
CSS/* \u56fa\u5b9a\u5bfc\u822a\u680f\u6837\u5f0f */\n.md-header--sticky {\n backdrop-filter: blur(8px);\n background-color: rgba(255,255,255,.8);\n}\n\n/* \u6697\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"slate\"] .md-header--sticky {\n background-color: rgba(0,0,0,.8);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4213","title":"4.2.1.3 \u54cd\u5e94\u5f0f\u5bfc\u822a","text":"\u54cd\u5e94\u5f0f\u914d\u7f6e\uff1a
YAMLtheme:\n features:\n - navigation.instant # \u5373\u65f6\u52a0\u8f7d\n - navigation.tracking # \u6eda\u52a8\u8ddf\u8e2a\n
\u54cd\u5e94\u5f0f\u6837\u5f0f\u8c03\u6574\uff1a
CSS/* \u79fb\u52a8\u7aef\u5bfc\u822a */\n@media screen and (max-width: 76.1875em) {\n .md-nav__title {\n font-size: .9rem;\n padding: 0.5rem 0.8rem;\n }\n\n .md-nav__item {\n padding: 0.2rem 0.8rem;\n }\n}\n\n/* \u5e73\u677f\u5bfc\u822a */\n@media screen and (min-width: 76.25em) {\n .md-nav__link {\n padding: 0.2rem 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#422","title":"4.2.2 \u6807\u7b7e\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4221","title":"4.2.2.1 \u6807\u7b7e\u9875\u914d\u7f6e","text":"\u542f\u7528\u6807\u7b7e\u5bfc\u822a\uff1a
YAMLtheme:\n features:\n - navigation.tabs\n - navigation.tabs.sticky # \u56fa\u5b9a\u6807\u7b7e\n
\u6807\u7b7e\u9875\u7ed3\u6784\uff1a
YAMLnav:\n - Home: index.md\n - Guide:\n - guide/index.md\n - Installation: guide/installation.md\n - Configuration: guide/configuration.md\n - API:\n - api/index.md\n - Reference: api/reference.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4222","title":"4.2.2.2 \u6807\u7b7e\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u6807\u7b7e\u6837\u5f0f\uff1a
CSS/* \u6807\u7b7e\u5bb9\u5668 */\n.md-tabs {\n background-color: var(--md-primary-fg-color--dark);\n}\n\n/* \u6807\u7b7e\u9879 */\n.md-tabs__item {\n padding: 0 1rem;\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-tabs__item:hover {\n background-color: rgba(255,255,255,.1);\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-tabs__item--active {\n font-weight: bold;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4223","title":"4.2.2.3 \u6807\u7b7e\u4ea4\u4e92","text":"\u6dfb\u52a0\u6807\u7b7e\u4ea4\u4e92\u6548\u679c\uff1a
JavaScript// docs/javascripts/tabs.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6807\u7b7e\u70b9\u51fb\u6548\u679c\n const tabs = document.querySelectorAll('.md-tabs__item');\n tabs.forEach(tab => {\n tab.addEventListener('click', () => {\n // \u6dfb\u52a0\u70b9\u51fb\u6ce2\u7eb9\u6548\u679c\n const ripple = document.createElement('div');\n ripple.classList.add('md-tabs__ripple');\n tab.appendChild(ripple);\n\n // \u79fb\u9664\u6ce2\u7eb9\u6548\u679c\n setTimeout(() => ripple.remove(), 1000);\n });\n });\n});\n
\u5bf9\u5e94\u7684 CSS\uff1a
CSS/* \u6ce2\u7eb9\u6548\u679c */\n.md-tabs__ripple {\n position: absolute;\n background: rgba(255,255,255,.3);\n border-radius: 50%;\n transform: scale(0);\n animation: ripple 0.6s linear;\n}\n\n@keyframes ripple {\n to {\n transform: scale(4);\n opacity: 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#423","title":"4.2.3 \u76ee\u5f55\u5bfc\u822a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4231","title":"4.2.3.1 \u76ee\u5f55\u5c42\u7ea7","text":"\u914d\u7f6e\u76ee\u5f55\u5c42\u7ea7\uff1a
YAMLtheme:\n features:\n - toc.integrate # \u96c6\u6210\u76ee\u5f55\n - toc.follow # \u76ee\u5f55\u8ddf\u968f\n\nmarkdown_extensions:\n - toc:\n permalink: true # \u6c38\u4e45\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n title: \u76ee\u5f55 # \u76ee\u5f55\u6807\u9898\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4232","title":"4.2.3.2 \u76ee\u5f55\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u76ee\u5f55\u6837\u5f0f\uff1a
CSS/* \u76ee\u5f55\u5bb9\u5668 */\n.md-toc {\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-radius: 4px;\n}\n\n/* \u76ee\u5f55\u6807\u9898 */\n.md-toc__title {\n font-weight: bold;\n margin-bottom: 1rem;\n}\n\n/* \u76ee\u5f55\u94fe\u63a5 */\n.md-toc__link {\n color: var(--md-typeset-color);\n text-decoration: none;\n}\n\n/* \u76ee\u5f55\u5c42\u7ea7\u7f29\u8fdb */\n.md-toc__list {\n margin-left: 1.5em;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4233","title":"4.2.3.3 \u951a\u70b9\u94fe\u63a5","text":"\u914d\u7f6e\u951a\u70b9\u94fe\u63a5\uff1a
YAMLmarkdown_extensions:\n - toc:\n permalink: \u2693\ufe0e # \u951a\u70b9\u7b26\u53f7\n slug: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower} # URL \u8f6c\u6362\u89c4\u5219\n
\u81ea\u5b9a\u4e49\u951a\u70b9\u6837\u5f0f\uff1a
CSS/* \u951a\u70b9\u94fe\u63a5 */\n.headerlink {\n opacity: 0;\n margin-left: .5em;\n transition: opacity 0.2s ease;\n}\n\n/* \u6807\u9898\u60ac\u505c\u65f6\u663e\u793a\u951a\u70b9 */\nh1:hover .headerlink,\nh2:hover .headerlink,\nh3:hover .headerlink {\n opacity: 1;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#424","title":"4.2.4 \u8fd4\u56de\u9876\u90e8","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4241","title":"4.2.4.1 \u6309\u94ae\u6837\u5f0f","text":"\u542f\u7528\u8fd4\u56de\u9876\u90e8\u6309\u94ae\uff1a
YAMLtheme:\n features:\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n
\u81ea\u5b9a\u4e49\u6309\u94ae\u6837\u5f0f\uff1a
CSS/* \u8fd4\u56de\u9876\u90e8\u6309\u94ae */\n.md-top {\n background-color: var(--md-primary-fg-color);\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-top:hover {\n background-color: var(--md-primary-fg-color--dark);\n transform: translateY(-2px);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4242","title":"4.2.4.2 \u6eda\u52a8\u884c\u4e3a","text":"\u81ea\u5b9a\u4e49\u6eda\u52a8\u884c\u4e3a\uff1a
JavaScript// docs/javascripts/scroll.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const topButton = document.querySelector('.md-top');\n\n // \u5e73\u6ed1\u6eda\u52a8\n if (topButton) {\n topButton.addEventListener('click', (e) => {\n e.preventDefault();\n window.scrollTo({\n top: 0,\n behavior: 'smooth'\n });\n });\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4243","title":"4.2.4.3 \u663e\u793a\u63a7\u5236","text":"\u914d\u7f6e\u663e\u793a\u903b\u8f91\uff1a
JavaScript// \u63a7\u5236\u6309\u94ae\u663e\u793a\nwindow.addEventListener('scroll', () => {\n const topButton = document.querySelector('.md-top');\n if (topButton) {\n if (window.scrollY > 100) {\n topButton.classList.add('md-top--show');\n } else {\n topButton.classList.remove('md-top--show');\n }\n }\n});\n
\u6837\u5f0f\u63a7\u5236\uff1a
CSS/* \u6309\u94ae\u663e\u793a\u9690\u85cf */\n.md-top {\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s ease, visibility 0.2s ease;\n}\n\n.md-top--show {\n opacity: 1;\n visibility: visible;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#425","title":"4.2.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n features:\n # \u5bfc\u822a\u529f\u80fd\n - navigation.tabs\n - navigation.tabs.sticky\n - navigation.sections\n - navigation.expand\n - navigation.indexes\n - navigation.instant\n - navigation.tracking\n - navigation.sticky\n - header.autohide\n\n # \u76ee\u5f55\u529f\u80fd\n - toc.integrate\n - toc.follow\n\n # \u8fd4\u56de\u9876\u90e8\n - navigation.top\n\n# Markdown \u6269\u5c55\nmarkdown_extensions:\n - toc:\n permalink: true\n toc_depth: 3\n title: \u76ee\u5f55\n slugify: !!python/object/apply:pymdownx.slugs.slugify\n kwds: {case: lower}\n\n# \u989d\u5916\u6837\u5f0f\u548c\u811a\u672c\nextra_css:\n - stylesheets/extra.css\n\nextra_javascript:\n - javascripts/tabs.js\n - javascripts/scroll.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#43","title":"4.3 \u641c\u7d22\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#431","title":"4.3.1 \u641c\u7d22\u5f15\u64ce\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4311","title":"4.3.1.1 \u641c\u7d22\u7b97\u6cd5","text":"\u57fa\u7840\u641c\u7d22\u914d\u7f6e\uff1a
YAMLplugins:\n - search:\n separator: '[\\\\s\\\\-\\\\.]+' # \u5206\u8bcd\u5206\u9694\u7b26\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n lang:\n - en\n - zh\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n
\u9ad8\u7ea7\u641c\u7d22\u9009\u9879\uff1a
YAMLplugins:\n - search:\n separator: '[\\\\s\\\\-\\\\.]+\\\\s*'\n min_search_length: 2\n prebuild_index: python\n indexing:\n full_sections: true # \u7d22\u5f15\u5b8c\u6574\u7ae0\u8282\n headings: true # \u7d22\u5f15\u6807\u9898\n content: true # \u7d22\u5f15\u5185\u5bb9\n tags: true # \u7d22\u5f15\u6807\u7b7e\n scoring:\n title_boost: 10 # \u6807\u9898\u6743\u91cd\n heading_boost: 5 # \u6807\u9898\u6743\u91cd\n content_boost: 1 # \u5185\u5bb9\u6743\u91cd\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4312","title":"4.3.1.2 \u7d22\u5f15\u914d\u7f6e","text":"\u81ea\u5b9a\u4e49\u7d22\u5f15\u8bbe\u7f6e\uff1a
YAMLplugins:\n - search:\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n attachments: true # \u7d22\u5f15\u9644\u4ef6\n attachments_types: # \u9644\u4ef6\u7c7b\u578b\n - .pdf\n - .doc\n - .docx\n attachments_max_size: 2048 # \u6700\u5927\u5927\u5c0f(KB)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4313","title":"4.3.1.3 \u641c\u7d22\u8303\u56f4","text":"\u914d\u7f6e\u641c\u7d22\u8303\u56f4\uff1a
YAMLplugins:\n - search:\n # \u5305\u542b\u7684\u6587\u4ef6\n include:\n - \"*.md\"\n - \"*.markdown\"\n\n # \u6392\u9664\u7684\u6587\u4ef6\n exclude:\n - drafts/*\n - private/*\n\n # \u5904\u7406\u7279\u5b9a\u8def\u5f84\n ignore:\n - 404.md\n - index.md\n
"},{"location":"Tools/Blog/Mkdocs_Material/#432","title":"4.3.2 \u641c\u7d22\u63d0\u793a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4321","title":"4.3.2.1 \u5feb\u6377\u952e\u8bbe\u7f6e","text":"\u914d\u7f6e\u641c\u7d22\u5feb\u6377\u952e\uff1a
YAMLtheme:\n keyboard:\n search: s, / # \u4f7f\u7528 's' \u6216 '/' \u89e6\u53d1\u641c\u7d22\n
\u81ea\u5b9a\u4e49\u5feb\u6377\u952e\u5904\u7406\uff1a
JavaScript// docs/javascripts/search.js\n\ndocument.addEventListener('keydown', function(e) {\n // \u81ea\u5b9a\u4e49\u5feb\u6377\u952e\u903b\u8f91\n if ((e.key === 's' || e.key === '/') && !e.ctrlKey && !e.altKey && !e.metaKey) {\n e.preventDefault();\n const search = document.querySelector('.md-search__input');\n if (search) {\n search.focus();\n }\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4322","title":"4.3.2.2 \u63d0\u793a\u6587\u672c","text":"\u81ea\u5b9a\u4e49\u641c\u7d22\u63d0\u793a\uff1a
YAMLtheme:\n language: zh # \u4f7f\u7528\u4e2d\u6587\u754c\u9762\n\nextra:\n search:\n language: zh\n text:\n placeholder: \u641c\u7d22\u6587\u6863...\n no_results: \u6ca1\u6709\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching: \u6b63\u5728\u641c\u7d22...\n
\u81ea\u5b9a\u4e49\u63d0\u793a\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search.css */\n\n/* \u641c\u7d22\u6846\u63d0\u793a\u6587\u672c */\n.md-search__input::placeholder {\n color: var(--md-default-fg-color--lighter);\n}\n\n/* \u65e0\u7ed3\u679c\u63d0\u793a */\n.md-search-result__meta {\n color: var(--md-default-fg-color--light);\n font-size: .8rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4323","title":"4.3.2.3 \u8f93\u5165\u5efa\u8bae","text":"\u914d\u7f6e\u641c\u7d22\u5efa\u8bae\uff1a
YAMLplugins:\n - search:\n suggestions: true # \u542f\u7528\u641c\u7d22\u5efa\u8bae\n suggestions_min_length: 2 # \u6700\u5c0f\u5efa\u8bae\u957f\u5ea6\n
\u81ea\u5b9a\u4e49\u5efa\u8bae\u6837\u5f0f\uff1a
CSS/* \u641c\u7d22\u5efa\u8bae\u6837\u5f0f */\n.md-search-result__item {\n padding: .4rem .8rem;\n transition: background .2s ease;\n}\n\n.md-search-result__item:hover {\n background-color: var(--md-code-bg-color);\n}\n\n/* \u5efa\u8bae\u9879\u56fe\u6807 */\n.md-search-result__icon {\n color: var(--md-default-fg-color--lighter);\n margin-right: .4rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#433","title":"4.3.3 \u641c\u7d22\u9ad8\u4eae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4331","title":"4.3.3.1 \u9ad8\u4eae\u6837\u5f0f","text":"\u914d\u7f6e\u641c\u7d22\u9ad8\u4eae\uff1a
YAMLtheme:\n features:\n - search.highlight # \u542f\u7528\u641c\u7d22\u9ad8\u4eae\n - search.share # \u542f\u7528\u641c\u7d22\u5206\u4eab\n - search.suggest # \u542f\u7528\u641c\u7d22\u5efa\u8bae\n
\u81ea\u5b9a\u4e49\u9ad8\u4eae\u6837\u5f0f\uff1a
CSS/* \u641c\u7d22\u7ed3\u679c\u9ad8\u4eae */\n.md-search-result__item mark {\n background-color: var(--md-accent-fg-color--transparent);\n color: var(--md-accent-fg-color);\n padding: 0 .2em;\n border-radius: .1em;\n}\n\n/* \u6eda\u52a8\u6761\u6837\u5f0f */\n.md-search-result__scrollwrap::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n}\n\n.md-search-result__scrollwrap::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4332","title":"4.3.3.2 \u5339\u914d\u89c4\u5219","text":"\u914d\u7f6e\u641c\u7d22\u5339\u914d\u89c4\u5219\uff1a
YAMLplugins:\n - search:\n # \u6587\u672c\u5339\u914d\u914d\u7f6e\n tokenizer: '[\\s\\-\\.]+' # \u5206\u8bcd\u89c4\u5219\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n\n # \u6a21\u7cca\u5339\u914d\u8bbe\u7f6e\n fuzzy: false # \u7981\u7528\u6a21\u7cca\u5339\u914d\n\n # \u5339\u914d\u6743\u91cd\n boost: \n title: 10 # \u6807\u9898\u6743\u91cd\n text: 1 # \u6587\u672c\u6743\u91cd\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4333","title":"4.3.3.3 \u81ea\u5b9a\u4e49\u9ad8\u4eae","text":"\u5b9e\u73b0\u81ea\u5b9a\u4e49\u9ad8\u4eae\u903b\u8f91\uff1a
JavaScript// docs/javascripts/search-highlight.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u83b7\u53d6\u641c\u7d22\u7ed3\u679c\u5bb9\u5668\n const searchResults = document.querySelector('.md-search-result');\n\n if (searchResults) {\n // \u76d1\u542c\u641c\u7d22\u7ed3\u679c\u53d8\u5316\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n if (mutation.type === 'childList') {\n // \u5904\u7406\u65b0\u6dfb\u52a0\u7684\u641c\u7d22\u7ed3\u679c\n const newResults = mutation.addedNodes;\n newResults.forEach(node => {\n if (node.nodeType === 1) { // \u5143\u7d20\u8282\u70b9\n customHighlight(node);\n }\n });\n }\n });\n });\n\n // \u542f\u52a8\u89c2\u5bdf\n observer.observe(searchResults, {\n childList: true,\n subtree: true\n });\n }\n});\n\nfunction customHighlight(node) {\n // \u81ea\u5b9a\u4e49\u9ad8\u4eae\u903b\u8f91\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#434","title":"4.3.4 \u641c\u7d22\u8bed\u8a00","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4341","title":"4.3.4.1 \u4e2d\u6587\u5206\u8bcd","text":"\u914d\u7f6e\u4e2d\u6587\u5206\u8bcd\uff1a
YAMLplugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,\\!\\/\\?\\u2000-\\u206F\\u3000-\\u303F\\u3040-\\u309F\\u30A0-\\u30FF\\u3100-\\u312F\\u3200-\\u32FF\\u3400-\\u4DBF\\u4E00-\\u9FFF]+'\n
\u4e2d\u6587\u641c\u7d22\u4f18\u5316\uff1a
JavaScript// docs/javascripts/chinese-search.js\n\nfunction chineseSegment(text) {\n // \u7b80\u5355\u7684\u4e2d\u6587\u5206\u8bcd\u903b\u8f91\n return text.replace(/[\\u4e00-\\u9fa5]/g, function(char) {\n return char + ' ';\n });\n}\n\n// \u6dfb\u52a0\u5230\u641c\u7d22\u5904\u7406\u6d41\u7a0b\ndocument.addEventListener('DOMContentLoaded', function() {\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.addEventListener('input', function(e) {\n const value = e.target.value;\n if (/[\\u4e00-\\u9fa5]/.test(value)) {\n // \u5904\u7406\u4e2d\u6587\u8f93\u5165\n const segmented = chineseSegment(value);\n // TODO: \u4f7f\u7528\u5206\u8bcd\u7ed3\u679c\u8fdb\u884c\u641c\u7d22\n }\n });\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4342","title":"4.3.4.2 \u591a\u8bed\u8a00\u652f\u6301","text":"\u914d\u7f6e\u591a\u8bed\u8a00\u641c\u7d22\uff1a
YAMLplugins:\n - search:\n lang:\n - en\n - zh\n - ja\n # \u8bed\u8a00\u7279\u5b9a\u7684\u5206\u8bcd\u89c4\u5219\n separator:\n en: '[\\\\s\\\\-\\\\.]+'\n zh: '[\\u4e00-\\u9fa5]'\n ja: '[\\u3040-\\u309F\\u30A0-\\u30FF]+'\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4343","title":"4.3.4.3 \u505c\u7528\u8bcd\u914d\u7f6e","text":"\u914d\u7f6e\u505c\u7528\u8bcd\uff1a
YAMLplugins:\n - search:\n stopwords: \n en:\n - a\n - an\n - the\n - in\n - on\n - at\n zh:\n - \u7684\n - \u4e86\n - \u548c\n - \u4e0e\n - \u6216\n
\u81ea\u5b9a\u4e49\u505c\u7528\u8bcd\u5904\u7406\uff1a
JavaScript// docs/javascripts/stopwords.js\n\nconst stopwords = {\n en: ['a', 'an', 'the', 'in', 'on', 'at'],\n zh: ['\u7684', '\u4e86', '\u548c', '\u4e0e', '\u6216'],\n};\n\nfunction removeStopwords(text, lang) {\n if (!stopwords[lang]) return text;\n\n const words = text.split(/\\s+/);\n return words\n .filter(word => !stopwords[lang].includes(word))\n .join(' ');\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#435","title":"4.3.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\nplugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,\\!\\/\\?\\u2000-\\u206F\\u3000-\\u303F]+'\n prebuild_index: python\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n scoring:\n title_boost: 10\n heading_boost: 5\n content_boost: 1\n\ntheme:\n features:\n - search.highlight\n - search.share\n - search.suggest\n\nextra:\n search:\n language: zh\n text:\n placeholder: \u641c\u7d22\u6587\u6863...\n no_results: \u6ca1\u6709\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching: \u6b63\u5728\u641c\u7d22...\n\nextra_javascript:\n - javascripts/search.js\n - javascripts/search-highlight.js\n - javascripts/chinese-search.js\n - javascripts/stopwords.js\n\nextra_css:\n - stylesheets/search.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#44","title":"4.4 \u4ee3\u7801\u5757\u8bbe\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#441","title":"4.4.1 \u8bed\u6cd5\u9ad8\u4eae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4411","title":"4.4.1.1 \u9ad8\u4eae\u4e3b\u9898","text":"\u57fa\u7840\u9ad8\u4eae\u914d\u7f6e\uff1a
YAMLtheme:\n name: material\n features:\n - content.code.annotate # \u542f\u7528\u4ee3\u7801\u6ce8\u91ca\n - content.code.copy # \u542f\u7528\u4ee3\u7801\u590d\u5236\n\nmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n use_pygments: true\n auto_title: true # \u663e\u793a\u8bed\u8a00\u540d\u79f0\n linenums: true # \u663e\u793a\u884c\u53f7\n
\u81ea\u5b9a\u4e49\u9ad8\u4eae\u4e3b\u9898\uff1a
YAMLtheme:\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - scheme: default\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u4e3b\u9898\n pygments_style: github-light\n\n # \u6697\u8272\u4e3b\u9898\n - scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u4e3b\u9898\n pygments_style: monokai\n
\u81ea\u5b9a\u4e49\u4ee3\u7801\u5757\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/code.css */\n\n/* \u4ee3\u7801\u5757\u5bb9\u5668 */\n.highlight {\n background-color: var(--md-code-bg-color);\n border-radius: 4px;\n padding: 0.5rem;\n margin: 1rem 0;\n}\n\n/* \u4ee3\u7801\u884c */\n.highlight .code-line {\n display: block;\n padding: 0 1rem;\n border-left: 2px solid transparent;\n}\n\n/* \u9ad8\u4eae\u884c */\n.highlight .code-line.focused {\n background-color: var(--md-code-hl-color);\n border-left: 2px solid var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4412","title":"4.4.1.2 \u8bed\u8a00\u652f\u6301","text":"\u914d\u7f6e\u652f\u6301\u7684\u8bed\u8a00\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n extend_pygments_lang:\n # \u81ea\u5b9a\u4e49\u8bed\u8a00\u914d\u7f6e\n typescript:\n name: TypeScript\n aliases: [ts]\n jsonc:\n name: JSON with Comments\n aliases: [json5]\n
\u8bed\u8a00\u7279\u5b9a\u914d\u7f6e\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n language_prefix: language- # \u8bed\u8a00\u524d\u7f00\n css_class: highlight # CSS\u7c7b\u540d\n code_attr_on_pre: false # \u5c5e\u6027\u4f4d\u7f6e\n extend_pygments_lang: # \u8bed\u8a00\u6269\u5c55\n flow:\n name: Flow\n aliases: [flowtype]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4413","title":"4.4.1.3 \u81ea\u5b9a\u4e49\u9ad8\u4eae","text":"\u81ea\u5b9a\u4e49\u8bed\u6cd5\u9ad8\u4eae\u89c4\u5219\uff1a
Python# docs/custom_lexer.py\nfrom pygments.lexer import RegexLexer, words\nfrom pygments.token import *\n\nclass CustomLexer(RegexLexer):\n name = 'CustomLanguage'\n aliases = ['custom']\n filenames = ['*.custom']\n\n tokens = {\n 'root': [\n (r'//.*$', Comment.Single),\n (words(('if', 'else', 'while'), suffix=r'\\b'), Keyword),\n (r'\"[^\"]*\"', String),\n (r'\\d+', Number),\n (r'[a-zA-Z_]\\w*', Name),\n (r'[^\\w\\s]', Punctuation),\n ]\n }\n
\u5728 mkdocs.yml
\u4e2d\u4f7f\u7528\uff1a
markdown_extensions:\n - pymdownx.highlight:\n use_pygments: true\n extend_pygments_lang:\n custom:\n name: CustomLanguage\n aliases: [custom]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#442","title":"4.4.2 \u884c\u53f7\u663e\u793a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4421","title":"4.4.2.1 \u884c\u53f7\u6837\u5f0f","text":"\u914d\u7f6e\u884c\u53f7\u663e\u793a\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n linenums: true\n linenums_style: table # \u8868\u683c\u5f0f\u884c\u53f7\n anchor_linenums: true # \u884c\u53f7\u94fe\u63a5\n
\u81ea\u5b9a\u4e49\u884c\u53f7\u6837\u5f0f\uff1a
CSS/* \u884c\u53f7\u5bb9\u5668 */\n.highlighttable {\n width: 100%;\n display: table;\n}\n\n/* \u884c\u53f7\u5217 */\n.linenos {\n color: var(--md-default-fg-color--lighter);\n text-align: right;\n padding-right: 1rem;\n user-select: none;\n}\n\n/* \u4ee3\u7801\u5217 */\n.code {\n padding-left: 1rem;\n border-left: 1px solid var(--md-default-fg-color--lightest);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4422","title":"4.4.2.2 \u8d77\u59cb\u884c\u8bbe\u7f6e","text":"\u8bbe\u7f6e\u4ee3\u7801\u5757\u8d77\u59cb\u884c\u53f7\uff1a
Markdown```python linenums=\"10\"\ndef hello_world():\n print(\"Hello, World!\")\n```\n
\u914d\u7f6e\u9ed8\u8ba4\u8d77\u59cb\u884c\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n linenums: true\n linenums_start: 1 # \u9ed8\u8ba4\u8d77\u59cb\u884c\u53f7\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4423","title":"4.4.2.3 \u884c\u53f7\u94fe\u63a5","text":"\u542f\u7528\u884c\u53f7\u94fe\u63a5\u529f\u80fd\uff1a
YAMLmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true # \u542f\u7528\u884c\u53f7\u94fe\u63a5\n line_anchors: L # \u884c\u53f7\u94fe\u63a5\u524d\u7f00\n
\u81ea\u5b9a\u4e49\u94fe\u63a5\u6837\u5f0f\uff1a
CSS/* \u884c\u53f7\u94fe\u63a5 */\n.md-typeset .highlight [data-linenos]:before {\n content: attr(data-linenos);\n color: var(--md-default-fg-color--lighter);\n padding-right: 1rem;\n}\n\n/* \u94fe\u63a5\u60ac\u505c\u6548\u679c */\n.md-typeset .highlight [data-linenos]:hover:before {\n color: var(--md-accent-fg-color);\n cursor: pointer;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#443","title":"4.4.3 \u590d\u5236\u6309\u94ae","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4431","title":"4.4.3.1 \u6309\u94ae\u6837\u5f0f","text":"\u914d\u7f6e\u590d\u5236\u6309\u94ae\uff1a
YAMLtheme:\n features:\n - content.code.copy # \u542f\u7528\u4ee3\u7801\u590d\u5236\n
\u81ea\u5b9a\u4e49\u590d\u5236\u6309\u94ae\u6837\u5f0f\uff1a
CSS/* \u590d\u5236\u6309\u94ae\u5bb9\u5668 */\n.md-clipboard {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n padding: 0.4rem;\n color: var(--md-default-fg-color--lighter);\n background-color: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u60ac\u505c\u6548\u679c */\n.md-clipboard:hover {\n color: var(--md-accent-fg-color);\n background-color: var(--md-code-bg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4432","title":"4.4.3.2 \u590d\u5236\u884c\u4e3a","text":"\u81ea\u5b9a\u4e49\u590d\u5236\u529f\u80fd\uff1a
JavaScript// docs/javascripts/clipboard.js\n\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u83b7\u53d6\u6240\u6709\u4ee3\u7801\u5757\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach(block => {\n // \u521b\u5efa\u590d\u5236\u6309\u94ae\n const button = document.createElement('button');\n button.className = 'md-clipboard';\n button.title = '\u590d\u5236\u5230\u526a\u8d34\u677f';\n\n // \u6dfb\u52a0\u590d\u5236\u56fe\u6807\n button.innerHTML = '<span class=\"md-clipboard__icon\"></span>';\n\n // \u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n button.addEventListener('click', async () => {\n try {\n // \u590d\u5236\u4ee3\u7801\n await navigator.clipboard.writeText(block.textContent);\n\n // \u663e\u793a\u6210\u529f\u63d0\u793a\n button.classList.add('md-clipboard--success');\n setTimeout(() => {\n button.classList.remove('md-clipboard--success');\n }, 2000);\n } catch (err) {\n console.error('\u590d\u5236\u5931\u8d25:', err);\n }\n });\n\n // \u5c06\u6309\u94ae\u6dfb\u52a0\u5230\u4ee3\u7801\u5757\n block.parentNode.insertBefore(button, block);\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4433","title":"4.4.3.3 \u63d0\u793a\u914d\u7f6e","text":"\u914d\u7f6e\u590d\u5236\u63d0\u793a\uff1a
YAMLtheme:\n language: zh # \u4f7f\u7528\u4e2d\u6587\u754c\u9762\n\nextra:\n clipboard:\n copy: \u590d\u5236\n copied: \u5df2\u590d\u5236\uff01\n error: \u590d\u5236\u5931\u8d25\n
\u81ea\u5b9a\u4e49\u63d0\u793a\u6837\u5f0f\uff1a
CSS/* \u590d\u5236\u63d0\u793a */\n.md-clipboard__tooltip {\n position: absolute;\n top: -2rem;\n right: 0;\n padding: 0.4rem 0.8rem;\n color: var(--md-default-bg-color);\n background-color: var(--md-default-fg-color);\n border-radius: 4px;\n font-size: 0.8rem;\n opacity: 0;\n transform: translateY(0.4rem);\n transition: all 0.2s ease;\n}\n\n/* \u663e\u793a\u63d0\u793a */\n.md-clipboard:hover .md-clipboard__tooltip {\n opacity: 1;\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#444","title":"4.4.4 \u6ce8\u91ca\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4441","title":"4.4.4.1 \u884c\u5185\u6ce8\u91ca","text":"\u4f7f\u7528\u884c\u5185\u6ce8\u91ca\uff1a
Markdown```python\ndef hello():\n print(\"Hello\") # (1)\n return True # (2)\n```\n\n1. \u6253\u5370\u95ee\u5019\u4fe1\u606f\n2. \u8fd4\u56de\u6210\u529f\u72b6\u6001\n
\u914d\u7f6e\u6ce8\u91ca\u6837\u5f0f\uff1a
CSS/* \u884c\u5185\u6ce8\u91ca\u6807\u8bb0 */\n.md-annotation {\n color: var(--md-accent-fg-color);\n font-size: 0.8em;\n vertical-align: super;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4442","title":"4.4.4.2 \u5757\u7ea7\u6ce8\u91ca","text":"\u4f7f\u7528\u5757\u7ea7\u6ce8\u91ca\uff1a
Markdown```python\ndef process_data():\n # (1)!\n data = load_data()\n\n # (2)!\n result = transform(data)\n\n return result\n```\n\n1. \u4ece\u6570\u636e\u6e90\u52a0\u8f7d\u6570\u636e\n \u8fd9\u91cc\u53ef\u4ee5\u662f\u591a\u884c\n \u6ce8\u91ca\u8bf4\u660e\n\n2. \u5bf9\u6570\u636e\u8fdb\u884c\u8f6c\u6362\u5904\u7406\n \u5305\u542b\u6e05\u6d17\u548c\u683c\u5f0f\u5316\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4443","title":"4.4.4.3 \u6ce8\u91ca\u6837\u5f0f","text":"\u81ea\u5b9a\u4e49\u6ce8\u91ca\u6837\u5f0f\uff1a
CSS/* \u6ce8\u91ca\u5bb9\u5668 */\n.md-annotation-wrapper {\n margin: 1rem 0;\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-left: 4px solid var(--md-accent-fg-color);\n border-radius: 4px;\n}\n\n/* \u6ce8\u91ca\u6807\u8bb0 */\n.md-annotation-marker {\n color: var(--md-accent-fg-color);\n font-weight: bold;\n}\n\n/* \u6ce8\u91ca\u5185\u5bb9 */\n.md-annotation-content {\n margin-top: 0.5rem;\n color: var(--md-default-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#445","title":"4.4.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\ntheme:\n name: material\n features:\n - content.code.annotate\n - content.code.copy\n\nmarkdown_extensions:\n - pymdownx.highlight:\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n use_pygments: true\n auto_title: true\n linenums: true\n linenums_style: table\n - pymdownx.superfences\n - pymdownx.inlinehilite\n\nextra:\n clipboard:\n copy: \u590d\u5236\n copied: \u5df2\u590d\u5236\uff01\n error: \u590d\u5236\u5931\u8d25\n\nextra_css:\n - stylesheets/code.css\n\nextra_javascript:\n - javascripts/clipboard.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#45","title":"4.5 \u5185\u5bb9\u589e\u5f3a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#451","title":"4.5.1 \u6570\u5b66\u516c\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4511-katex","title":"4.5.1.1 KaTeX \u914d\u7f6e","text":"\u5b89\u88c5\u548c\u914d\u7f6e KaTeX\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/katex.js \n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js \n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n
\u521b\u5efa docs/javascripts/katex.js
\uff1a
document.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false},\n {left: \"\\\\(\", right: \"\\\\)\", display: false},\n {left: \"\\\\[\", right: \"\\\\]\", display: true}\n ],\n throwOnError: false\n });\n});\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown\u5185\u8054\u516c\u5f0f: $E = mc^2$\n\n\u5757\u7ea7\u516c\u5f0f\uff1a\n$$\n\\frac{n!}{k!(n-k)!} = \\binom{n}{k}\n$$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4512-mathjax","title":"4.5.1.2 MathJax \u914d\u7f6e","text":"\u914d\u7f6e MathJax\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/mathjax.js\n - https://polyfill.io/v3/polyfill.min.js?features=es6\n - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\n
\u521b\u5efa docs/javascripts/mathjax.js
\uff1a
window.MathJax = {\n tex: {\n inlineMath: [[\"\\\\(\", \"\\\\)\"]],\n displayMath: [[\"\\\\[\", \"\\\\]\"]],\n processEscapes: true,\n processEnvironments: true\n },\n options: {\n ignoreHtmlClass: \".*|\",\n processHtmlClass: \"arithmatex\"\n }\n};\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4513","title":"4.5.1.3 \u516c\u5f0f\u7f16\u53f7","text":"\u542f\u7528\u516c\u5f0f\u7f16\u53f7\uff1a
YAMLmarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n numbering: true\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Markdown$$\n\\begin{equation}\nE = mc^2 \\label{eq:einstein}\n\\end{equation}\n$$\n\n\u5f15\u7528\u516c\u5f0f $\\eqref{eq:einstein}$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#452","title":"4.5.2 \u56fe\u8868\u652f\u6301","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4521-mermaid","title":"4.5.2.1 Mermaid \u96c6\u6210","text":"\u914d\u7f6e Mermaid\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Text Onlygraph TD\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B -->|Yes| C[\u5904\u7406]\n B -->|No| D[\u7ed3\u675f]\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4522-plantuml","title":"4.5.2.2 PlantUML \u652f\u6301","text":"\u914d\u7f6e PlantUML\uff1a
YAMLmarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: plantuml\n class: plantuml\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://cdn.jsdelivr.net/npm/plantuml-encoder@1.4.0/dist/plantuml-encoder.min.js\n
\u4f7f\u7528\u793a\u4f8b\uff1a
Text Only@startuml\nAlice -> Bob: \u8bf7\u6c42\nBob --> Alice: \u54cd\u5e94\n@enduml\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4523","title":"4.5.2.3 \u81ea\u5b9a\u4e49\u56fe\u8868","text":"\u521b\u5efa\u81ea\u5b9a\u4e49\u56fe\u8868\u7ec4\u4ef6\uff1a
JavaScript// docs/javascripts/charts.js\nimport Chart from 'chart.js/auto';\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const chartElements = document.querySelectorAll('.custom-chart');\n\n chartElements.forEach(element => {\n const ctx = element.getContext('2d');\n const data = JSON.parse(element.dataset.chartData);\n\n new Chart(ctx, {\n type: data.type,\n data: data.data,\n options: data.options\n });\n });\n});\n
\u4f7f\u7528\u793a\u4f8b\uff1a
HTML<canvas class=\"custom-chart\" data-chart-data='{\n \"type\": \"line\",\n \"data\": {\n \"labels\": [\"1\u6708\", \"2\u6708\", \"3\u6708\"],\n \"datasets\": [{\n \"label\": \"\u6570\u636e\",\n \"data\": [10, 20, 30]\n }]\n }\n}'></canvas>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#453","title":"4.5.3 \u4efb\u52a1\u5217\u8868","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4531","title":"4.5.3.1 \u590d\u9009\u6846\u6837\u5f0f","text":"\u914d\u7f6e\u4efb\u52a1\u5217\u8868\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tasklist:\n custom_checkbox: true\n clickable_checkbox: true\n
\u81ea\u5b9a\u4e49\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/tasklist.css */\n\n.task-list-item {\n list-style-type: none;\n margin-left: -1.6rem;\n}\n\n.task-list-control {\n position: relative;\n display: inline-block;\n width: 1.2rem;\n height: 1.2rem;\n margin-right: 0.5rem;\n vertical-align: middle;\n}\n\n.task-list-indicator {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n\n.task-list-indicator:checked {\n background-color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4532","title":"4.5.3.2 \u4ea4\u4e92\u884c\u4e3a","text":"\u6dfb\u52a0\u4ea4\u4e92\u529f\u80fd\uff1a
JavaScript// docs/javascripts/tasklist.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const taskItems = document.querySelectorAll('.task-list-item input[type=\"checkbox\"]');\n\n taskItems.forEach(item => {\n item.addEventListener('change', function() {\n // \u4fdd\u5b58\u72b6\u6001\n localStorage.setItem(\n `task-${this.closest('.task-list-item').id}`,\n this.checked\n );\n\n // \u66f4\u65b0\u6837\u5f0f\n if (this.checked) {\n this.closest('.task-list-item').classList.add('completed');\n } else {\n this.closest('.task-list-item').classList.remove('completed');\n }\n });\n\n // \u6062\u590d\u72b6\u6001\n const saved = localStorage.getItem(`task-${item.closest('.task-list-item').id}`);\n if (saved === 'true') {\n item.checked = true;\n item.closest('.task-list-item').classList.add('completed');\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4533","title":"4.5.3.3 \u72b6\u6001\u7ba1\u7406","text":"CSS/* \u4efb\u52a1\u72b6\u6001\u6837\u5f0f */\n.task-list-item.completed {\n text-decoration: line-through;\n color: var(--md-default-fg-color--light);\n}\n\n.task-list-item.pending {\n font-weight: bold;\n}\n\n.task-list-item.in-progress {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#454","title":"4.5.4 \u6807\u7b7e\u9875","text":""},{"location":"Tools/Blog/Mkdocs_Material/#4541","title":"4.5.4.1 \u6807\u7b7e\u7ec4\u6837\u5f0f","text":"\u914d\u7f6e\u6807\u7b7e\u9875\uff1a
YAMLmarkdown_extensions:\n - pymdownx.tabbed:\n alternate_style: true \n
\u81ea\u5b9a\u4e49\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/tabs.css */\n\n/* \u6807\u7b7e\u7ec4\u5bb9\u5668 */\n.tabbed-set {\n border: 1px solid var(--md-default-fg-color--lightest);\n border-radius: 4px;\n margin: 1rem 0;\n}\n\n/* \u6807\u7b7e\u5217\u8868 */\n.tabbed-labels {\n display: flex;\n background-color: var(--md-code-bg-color);\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u5355\u4e2a\u6807\u7b7e */\n.tabbed-labels > label {\n padding: 0.8rem 1.2rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.tabbed-labels > label.tabbed-selected {\n color: var(--md-accent-fg-color);\n border-bottom: 2px solid var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4542","title":"4.5.4.2 \u5207\u6362\u6548\u679c","text":"\u6dfb\u52a0\u52a8\u753b\u6548\u679c\uff1a
CSS/* \u6807\u7b7e\u5185\u5bb9\u5207\u6362\u52a8\u753b */\n.tabbed-content {\n padding: 1rem;\n opacity: 0;\n transform: translateY(10px);\n transition: all 0.3s ease;\n}\n\n.tabbed-content.tabbed-selected {\n opacity: 1;\n transform: translateY(0);\n}\n
\u6807\u7b7e\u9875\u4ea4\u4e92\uff1a
JavaScript// docs/javascripts/tabs.js\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const tabSets = document.querySelectorAll('.tabbed-set');\n\n tabSets.forEach(tabSet => {\n const tabs = tabSet.querySelectorAll('.tabbed-labels > label');\n const contents = tabSet.querySelectorAll('.tabbed-content');\n\n tabs.forEach((tab, index) => {\n tab.addEventListener('click', () => {\n // \u66f4\u65b0\u6807\u7b7e\u72b6\u6001\n tabs.forEach(t => t.classList.remove('tabbed-selected'));\n tab.classList.add('tabbed-selected');\n\n // \u66f4\u65b0\u5185\u5bb9\u72b6\u6001\n contents.forEach(c => c.classList.remove('tabbed-selected'));\n contents[index].classList.add('tabbed-selected');\n });\n });\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#4543","title":"4.5.4.3 \u54cd\u5e94\u5f0f\u8bbe\u8ba1","text":"\u6dfb\u52a0\u54cd\u5e94\u5f0f\u652f\u6301\uff1a
CSS/* \u79fb\u52a8\u7aef\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .tabbed-labels {\n flex-wrap: wrap;\n }\n\n .tabbed-labels > label {\n flex: 1 1 auto;\n text-align: center;\n }\n\n .tabbed-content {\n padding: 0.8rem;\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) {\n .tabbed-set {\n max-width: 80%;\n margin: 1rem auto;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#455","title":"4.5.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\n\nmarkdown_extensions:\n # \u6570\u5b66\u516c\u5f0f\n - pymdownx.arithmatex:\n generic: true\n\n # \u56fe\u8868\u652f\u6301\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n - name: plantuml\n class: plantuml\n format: !!python/name:pymdownx.superfences.fence_code_format\n\n # \u4efb\u52a1\u5217\u8868\n - pymdownx.tasklist:\n custom_checkbox: true\n clickable_checkbox: true\n\n # \u6807\u7b7e\u9875\n - pymdownx.tabbed:\n alternate_style: true\n\nextra_javascript:\n - javascripts/katex.js\n - javascripts/mermaid.js\n - javascripts/charts.js\n - javascripts/tasklist.js\n - javascripts/tabs.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n - stylesheets/tasklist.css\n - stylesheets/tabs.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5","title":"5 \u6837\u5f0f\u5b9a\u5236","text":""},{"location":"Tools/Blog/Mkdocs_Material/#51-css","title":"5.1 CSS \u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#511-css","title":"5.1.1 \u81ea\u5b9a\u4e49 CSS \u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5111-css","title":"5.1.1.1 CSS \u6587\u4ef6\u7ec4\u7ec7","text":"docs/\n\u251c\u2500\u2500 stylesheets/\n\u2502 \u251c\u2500\u2500 base/\n\u2502 \u2502 \u251c\u2500\u2500 _variables.css # CSS\u53d8\u91cf\u5b9a\u4e49\n\u2502 \u2502 \u251c\u2500\u2500 _typography.css # \u6392\u7248\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _colors.css # \u989c\u8272\u5b9a\u4e49\n\u2502 \u251c\u2500\u2500 components/\n\u2502 \u2502 \u251c\u2500\u2500 _buttons.css # \u6309\u94ae\u6837\u5f0f\n\u2502 \u2502 \u251c\u2500\u2500 _cards.css # \u5361\u7247\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _tables.css # \u8868\u683c\u6837\u5f0f\n\u2502 \u251c\u2500\u2500 layouts/\n\u2502 \u2502 \u251c\u2500\u2500 _header.css # \u5934\u90e8\u6837\u5f0f\n\u2502 \u2502 \u251c\u2500\u2500 _nav.css # \u5bfc\u822a\u6837\u5f0f\n\u2502 \u2502 \u2514\u2500\u2500 _footer.css # \u9875\u811a\u6837\u5f0f\n\u2502 \u2514\u2500\u2500 extra.css # \u4e3b\u6837\u5f0f\u6587\u4ef6\n
mkdocs.yml
\u4e2d\u5f15\u5165\u6837\u5f0f\uff1aextra_css:\n - stylesheets/extra.css\n
/* docs/stylesheets/extra.css */\n\n/* \u57fa\u7840\u6837\u5f0f */\n@import 'base/_variables.css';\n@import 'base/_typography.css';\n@import 'base/_colors.css';\n\n/* \u7ec4\u4ef6\u6837\u5f0f */\n@import 'components/_buttons.css';\n@import 'components/_cards.css';\n@import 'components/_tables.css';\n\n/* \u5e03\u5c40\u6837\u5f0f */\n@import 'layouts/_header.css';\n@import 'layouts/_nav.css';\n@import 'layouts/_footer.css';\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5112","title":"5.1.1.2 \u6837\u5f0f\u4f18\u5148\u7ea7","text":"/* 1. \u884c\u5185\u6837\u5f0f (1000) */\n<div style=\"color: red;\">\n\n/* 2. ID \u9009\u62e9\u5668 (100) */\n#header { }\n\n/* 3. \u7c7b\u9009\u62e9\u5668\u3001\u5c5e\u6027\u9009\u62e9\u5668\u3001\u4f2a\u7c7b (10) */\n.nav-item { }\n[type=\"text\"] { }\n:hover { }\n\n/* 4. \u5143\u7d20\u9009\u62e9\u5668\u3001\u4f2a\u5143\u7d20 (1) */\ndiv { }\n::before { }\n
/* \u8986\u76d6\u4e3b\u9898\u6837\u5f0f */\n.md-header {\n /* \u4f7f\u7528 !important \u614e\u91cd */\n background-color: #2196f3 !important;\n}\n\n/* \u4f7f\u7528\u66f4\u5177\u4f53\u7684\u9009\u62e9\u5668 */\n.md-header[data-md-color-scheme=\"default\"] {\n background-color: #2196f3;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5113-css","title":"5.1.1.3 CSS \u53d8\u91cf","text":"/* docs/stylesheets/base/_variables.css */\n\n:root {\n /* \u989c\u8272\u53d8\u91cf */\n --primary-color: #2196f3;\n --accent-color: #f50057;\n --text-color: #333333;\n\n /* \u5b57\u4f53\u53d8\u91cf */\n --font-family: \"LXGW WenKai\", -apple-system, sans-serif;\n --code-font: \"JetBrains Mono\", monospace;\n\n /* \u95f4\u8ddd\u53d8\u91cf */\n --spacing-unit: 8px;\n --content-padding: calc(var(--spacing-unit) * 2);\n\n /* \u9634\u5f71\u53d8\u91cf */\n --shadow-sm: 0 1px 2px rgba(0,0,0,0.1);\n --shadow-md: 0 2px 4px rgba(0,0,0,0.1);\n --shadow-lg: 0 4px 8px rgba(0,0,0,0.1);\n}\n
/* \u4eae\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"default\"] {\n --md-primary-fg-color: var(--primary-color);\n --md-accent-fg-color: var(--accent-color);\n --md-typeset-color: var(--text-color);\n}\n\n/* \u6697\u8272\u4e3b\u9898 */\n[data-md-color-scheme=\"slate\"] {\n --primary-color: #90caf9;\n --accent-color: #ff4081;\n --text-color: #ffffff;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#512","title":"5.1.2 \u5e38\u7528\u6837\u5f0f\u4fee\u6539","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5121","title":"5.1.2.1 \u5b57\u4f53\u8bbe\u7f6e","text":"/* docs/stylesheets/base/_typography.css */\n\n/* \u57fa\u7840\u5b57\u4f53\u8bbe\u7f6e */\nbody {\n font-family: var(--font-family);\n font-size: 16px;\n line-height: 1.6;\n}\n\n/* \u4ee3\u7801\u5b57\u4f53 */\ncode, pre {\n font-family: var(--code-font);\n font-size: 0.9em;\n}\n\n/* \u6807\u9898\u5b57\u4f53 */\nh1, h2, h3, h4, h5, h6 {\n font-family: var(--font-family);\n font-weight: 600;\n margin: calc(var(--spacing-unit) * 3) 0;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5122","title":"5.1.2.2 \u989c\u8272\u5b9a\u5236","text":"CSS/* docs/stylesheets/base/_colors.css */\n\n/* \u6587\u672c\u989c\u8272 */\n.md-typeset {\n color: var(--text-color);\n}\n\n/* \u94fe\u63a5\u989c\u8272 */\n.md-typeset a {\n color: var(--md-accent-fg-color);\n}\n\n/* \u4ee3\u7801\u5757\u989c\u8272 */\n.highlight {\n background-color: var(--md-code-bg-color);\n}\n\n/* \u5f15\u7528\u5757\u989c\u8272 */\nblockquote {\n border-left: 4px solid var(--md-accent-fg-color);\n background-color: var(--md-code-bg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5123","title":"5.1.2.3 \u95f4\u8ddd\u8c03\u6574","text":"CSS/* \u5185\u5bb9\u95f4\u8ddd */\n.md-main__inner {\n padding: var(--content-padding);\n}\n\n/* \u6bb5\u843d\u95f4\u8ddd */\n.md-typeset p {\n margin: var(--spacing-unit) 0;\n}\n\n/* \u5217\u8868\u95f4\u8ddd */\n.md-typeset ul li,\n.md-typeset ol li {\n margin-bottom: calc(var(--spacing-unit) * 0.5);\n}\n\n/* \u6807\u9898\u95f4\u8ddd */\n.md-typeset h1 {\n margin-top: calc(var(--spacing-unit) * 4);\n margin-bottom: calc(var(--spacing-unit) * 2);\n}\n\n.md-typeset h2 {\n margin-top: calc(var(--spacing-unit) * 3);\n margin-bottom: calc(var(--spacing-unit) * 1.5);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5124","title":"5.1.2.4 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"\u5728 mkdocs.yml
\u4e2d\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n font: false # \u7981\u7528\u9ed8\u8ba4\u5b57\u4f53\n\nextra_css:\n - stylesheets/extra.css\n\nextra:\n css_variables:\n spacing_unit: 8px\n content_width: 960px\n
"},{"location":"Tools/Blog/Mkdocs_Material/#52","title":"5.2 \u4e3b\u9898\u6837\u5f0f\u8986\u76d6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#521","title":"5.2.1 \u7ec4\u4ef6\u6837\u5f0f\u4fee\u6539","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5211","title":"5.2.1.1 \u5bfc\u822a\u680f\u6837\u5f0f","text":"/* docs/stylesheets/components/header.css */\n\n/* \u5bfc\u822a\u680f\u5bb9\u5668 */\n.md-header {\n background-color: var(--md-primary-fg-color);\n box-shadow: 0 2px 4px rgba(0,0,0,.14);\n height: 3rem;\n}\n\n/* \u5bfc\u822a\u680f\u6807\u9898 */\n.md-header__title {\n font-size: 1.2rem;\n font-weight: 600;\n margin-left: 1rem;\n}\n\n/* \u5bfc\u822a\u680f\u6309\u94ae */\n.md-header__button {\n padding: .8rem;\n color: var(--md-primary-bg-color);\n}\n\n/* \u5bfc\u822a\u680f\u641c\u7d22\u6846 */\n.md-search__input {\n border-radius: 2rem;\n background-color: rgba(255,255,255,.1);\n padding: 0 2.4rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5212","title":"5.2.1.2 \u4fa7\u8fb9\u680f\u6837\u5f0f","text":"CSS/* docs/stylesheets/components/sidebar.css */\n\n/* \u4fa7\u8fb9\u680f\u5bb9\u5668 */\n.md-sidebar {\n width: 14rem;\n background-color: var(--md-default-bg-color);\n padding: 1.2rem 0;\n}\n\n/* \u4fa7\u8fb9\u680f\u5bfc\u822a */\n.md-nav--primary {\n padding: 0 .8rem;\n}\n\n/* \u5bfc\u822a\u9879 */\n.md-nav__item {\n padding: .2rem 0;\n}\n\n/* \u5bfc\u822a\u94fe\u63a5 */\n.md-nav__link {\n color: var(--md-default-fg-color);\n padding: .4rem .6rem;\n border-radius: 4px;\n transition: all .2s;\n}\n\n.md-nav__link:hover {\n background-color: var(--md-code-bg-color);\n color: var(--md-accent-fg-color);\n}\n\n/* \u6fc0\u6d3b\u72b6\u6001 */\n.md-nav__link--active {\n font-weight: 600;\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5213","title":"5.2.1.3 \u9875\u811a\u6837\u5f0f","text":"CSS/* docs/stylesheets/components/footer.css */\n\n/* \u9875\u811a\u5bb9\u5668 */\n.md-footer {\n background-color: var(--md-default-bg-color--darkest);\n color: var(--md-footer-fg-color);\n}\n\n/* \u9875\u811a\u5185\u5bb9 */\n.md-footer-meta {\n background-color: rgba(0,0,0,.1);\n padding: 1rem 0;\n}\n\n/* \u9875\u811a\u94fe\u63a5 */\n.md-footer__link {\n padding: .4rem 1rem;\n color: var(--md-footer-fg-color--light);\n}\n\n/* \u7248\u6743\u4fe1\u606f */\n.md-footer-copyright {\n font-size: .8rem;\n color: var(--md-footer-fg-color--lighter);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#522","title":"5.2.2 \u81ea\u5b9a\u4e49\u8c03\u8272\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5221","title":"5.2.2.1 \u4e3b\u9898\u8272\u5b9a\u5236","text":"/* docs/stylesheets/theme/colors.css */\n\n:root {\n /* \u4e3b\u8272\u8c03 */\n --md-primary-hue: 210;\n --md-primary-saturation: 80%;\n --md-primary-lightness: 45%;\n\n /* \u5f3a\u8c03\u8272 */\n --md-accent-hue: 340;\n --md-accent-saturation: 90%;\n --md-accent-lightness: 50%;\n}\n
:root {\n --md-primary-fg-color: hsl(\n var(--md-primary-hue),\n var(--md-primary-saturation),\n var(--md-primary-lightness)\n );\n\n --md-accent-fg-color: hsl(\n var(--md-accent-hue),\n var(--md-accent-saturation),\n var(--md-accent-lightness)\n );\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5222","title":"5.2.2.2 \u914d\u8272\u65b9\u6848","text":"YAML# mkdocs.yml\ntheme:\n palette:\n # \u4eae\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo\n accent: deep purple\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u6a21\u5f0f\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: blue grey\n accent: deep purple\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5223","title":"5.2.2.3 \u6697\u8272\u4e3b\u9898","text":"CSS/* \u6697\u8272\u4e3b\u9898\u53d8\u91cf */\n[data-md-color-scheme=\"slate\"] {\n --md-default-bg-color: #1a1a1a;\n --md-default-bg-color--light: #222222;\n --md-default-bg-color--lighter: #282828;\n\n --md-default-fg-color: rgba(255,255,255,0.87);\n --md-default-fg-color--light: rgba(255,255,255,0.54);\n --md-default-fg-color--lighter: rgba(255,255,255,0.32);\n\n --md-code-bg-color: #2d2d2d;\n --md-code-fg-color: #f5f5f5;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#523","title":"5.2.3 \u5b57\u4f53\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5231","title":"5.2.3.1 \u4e2d\u6587\u5b57\u4f53","text":"/* docs/stylesheets/theme/fonts.css */\n\n/* \u4e2d\u6587\u5b57\u4f53\u53d8\u91cf */\n:root {\n --md-font-chinese: \"LXGW WenKai\", \"PingFang SC\", \"Microsoft YaHei\";\n}\n\n/* \u5f15\u5165 LXGW WenKai \u5b57\u4f53 */\n@font-face {\n font-family: \"LXGW WenKai\";\n src: url(\"https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@1.1.0/style.css\");\n font-display: swap;\n}\n
body {\n font-family: var(--md-font-chinese), -apple-system, sans-serif;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5232","title":"5.2.3.2 \u4ee3\u7801\u5b57\u4f53","text":"CSS/* \u4ee3\u7801\u5b57\u4f53\u914d\u7f6e */\n:root {\n --md-code-font: \"JetBrains Mono\", \"Fira Code\", \"Source Code Pro\", monospace;\n}\n\n/* \u4ee3\u7801\u5757\u6837\u5f0f */\n.md-typeset code,\n.md-typeset pre {\n font-family: var(--md-code-font);\n font-size: 0.9em;\n}\n\n/* \u884c\u5185\u4ee3\u7801 */\n.md-typeset code {\n border-radius: 4px;\n padding: .2em .4em;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5233","title":"5.2.3.3 \u5b57\u4f53\u56de\u9000","text":"CSS/* \u5b57\u4f53\u56de\u9000\u7b56\u7565 */\n:root {\n --md-text-font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica,\n Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;\n\n --md-code-font-fallback: SFMono-Regular, Consolas, Menlo, monospace;\n}\n\n/* \u5e94\u7528\u56de\u9000\u5b57\u4f53 */\nbody {\n font-family: var(--md-font-chinese), var(--md-text-font-fallback);\n}\n\npre, code {\n font-family: var(--md-code-font), var(--md-code-font-fallback);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#524","title":"5.2.4 \u5e03\u5c40\u8c03\u6574","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5241","title":"5.2.4.1 \u54cd\u5e94\u5f0f\u5e03\u5c40","text":"CSS/* docs/stylesheets/theme/layout.css */\n\n/* \u57fa\u7840\u54cd\u5e94\u5f0f\u5e03\u5c40 */\n.md-grid {\n max-width: 100%;\n margin: 0 auto;\n}\n\n/* \u684c\u9762\u7aef */\n@media screen and (min-width: 76.25em) {\n .md-grid {\n max-width: 76rem;\n }\n\n .md-sidebar--primary {\n width: 14rem;\n }\n\n .md-sidebar--secondary {\n width: 12rem;\n margin-left: 76rem;\n }\n}\n\n/* \u5e73\u677f\u7aef */\n@media screen and (max-width: 76.1875em) {\n .md-grid {\n max-width: 60rem;\n }\n\n .md-header-nav__title {\n display: none;\n }\n}\n\n/* \u79fb\u52a8\u7aef */\n@media screen and (max-width: 44.9375em) {\n .md-grid {\n max-width: 100%;\n padding: 0 1rem;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5242","title":"5.2.4.2 \u7f51\u683c\u7cfb\u7edf","text":"CSS/* \u81ea\u5b9a\u4e49\u7f51\u683c\u7cfb\u7edf */\n.grid {\n display: grid;\n gap: 1rem;\n margin: 1rem 0;\n}\n\n/* \u7f51\u683c\u5217\u6570 */\n.grid-cols-1 { grid-template-columns: repeat(1, 1fr); }\n.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }\n.grid-cols-3 { grid-template-columns: repeat(3, 1fr); }\n.grid-cols-4 { grid-template-columns: repeat(4, 1fr); }\n\n/* \u54cd\u5e94\u5f0f\u7f51\u683c */\n@media (min-width: 768px) {\n .md-grid-cols-md-2 { grid-template-columns: repeat(2, 1fr); }\n .md-grid-cols-md-3 { grid-template-columns: repeat(3, 1fr); }\n}\n\n@media (min-width: 1024px) {\n .md-grid-cols-lg-3 { grid-template-columns: repeat(3, 1fr); }\n .md-grid-cols-lg-4 { grid-template-columns: repeat(4, 1fr); }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5243","title":"5.2.4.3 \u5bb9\u5668\u5bbd\u5ea6","text":"CSS/* \u5bb9\u5668\u5bbd\u5ea6\u5b9a\u4e49 */\n:root {\n --md-container-width: 80rem;\n --md-container-padding: 1rem;\n}\n\n/* \u5bb9\u5668\u6837\u5f0f */\n.md-container {\n max-width: var(--md-container-width);\n margin: 0 auto;\n padding: 0 var(--md-container-padding);\n}\n\n/* \u4e0d\u540c\u5c3a\u5bf8\u7684\u5bb9\u5668 */\n.md-container--small {\n max-width: 60rem;\n}\n\n.md-container--medium {\n max-width: 70rem;\n}\n\n.md-container--large {\n max-width: 90rem;\n}\n\n/* \u6d41\u5f0f\u5bb9\u5668 */\n.md-container--fluid {\n max-width: 100%;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#525","title":"5.2.5 \u5b8c\u6574\u914d\u7f6e\u793a\u4f8b","text":"YAML# mkdocs.yml\ntheme:\n name: material\n font: false\n features:\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n palette:\n - scheme: default\n primary: indigo\n accent: deep purple\n - scheme: slate\n primary: blue grey\n accent: deep purple\n\nextra_css:\n - stylesheets/theme/colors.css\n - stylesheets/theme/fonts.css\n - stylesheets/theme/layout.css\n - stylesheets/components/header.css\n - stylesheets/components/sidebar.css\n - stylesheets/components/footer.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#53","title":"5.3 \u81ea\u5b9a\u4e49\u7ec4\u4ef6\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#531","title":"5.3.1 \u5361\u7247\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5311","title":"5.3.1.1 \u57fa\u7840\u5361\u7247","text":"\u57fa\u7840\u5361\u7247\u6837\u5f0f\u5b9a\u4e49\uff1a
CSS/* docs/stylesheets/components/cards.css */\n\n/* \u57fa\u7840\u5361\u7247\u5bb9\u5668 */\n.card {\n background-color: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n padding: 1.5rem;\n margin: 1rem 0;\n transition: all 0.3s ease;\n}\n\n/* \u5361\u7247\u6807\u9898 */\n.card__title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: var(--md-typeset-color);\n}\n\n/* \u5361\u7247\u5185\u5bb9 */\n.card__content {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n line-height: 1.6;\n}\n\n/* \u5361\u7247\u5e95\u90e8 */\n.card__footer {\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n
\u4f7f\u7528\u793a\u4f8b\uff1a
HTML<div class=\"card\">\n <div class=\"card__title\">\u5361\u7247\u6807\u9898</div>\n <div class=\"card__content\">\n \u8fd9\u91cc\u662f\u5361\u7247\u5185\u5bb9...\n </div>\n <div class=\"card__footer\">\n \u5361\u7247\u5e95\u90e8\u4fe1\u606f\n </div>\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5312","title":"5.3.1.2 \u56fe\u7247\u5361\u7247","text":"CSS/* \u56fe\u7247\u5361\u7247\u6837\u5f0f */\n.card--image {\n padding: 0;\n overflow: hidden;\n}\n\n/* \u56fe\u7247\u5bb9\u5668 */\n.card__image {\n width: 100%;\n height: 200px;\n position: relative;\n overflow: hidden;\n}\n\n/* \u56fe\u7247\u6837\u5f0f */\n.card__image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n/* \u56fe\u7247\u60ac\u505c\u6548\u679c */\n.card--image:hover img {\n transform: scale(1.05);\n}\n\n/* \u56fe\u7247\u5361\u7247\u5185\u5bb9\u533a */\n.card--image .card__content {\n padding: 1.5rem;\n}\n\n/* \u56fe\u7247\u6807\u9898\u8986\u76d6 */\n.card__image-title {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 1rem;\n background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);\n color: white;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5313","title":"5.3.1.3 \u7279\u6548\u5361\u7247","text":"CSS/* \u60ac\u6d6e\u6548\u679c\u5361\u7247 */\n.card--hover {\n cursor: pointer;\n}\n\n.card--hover:hover {\n transform: translateY(-4px);\n box-shadow: var(--md-shadow-z2);\n}\n\n/* \u6e10\u53d8\u80cc\u666f\u5361\u7247 */\n.card--gradient {\n background: linear-gradient(135deg, \n var(--md-primary-fg-color) 0%,\n var(--md-accent-fg-color) 100%);\n color: white;\n}\n\n/* \u6bdb\u73bb\u7483\u6548\u679c\u5361\u7247 */\n.card--glass {\n background: rgba(255, 255, 255, 0.1);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.2);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#532","title":"5.3.2 \u63d0\u793a\u6846\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5321","title":"5.3.2.1 \u4fe1\u606f\u63d0\u793a","text":"CSS/* docs/stylesheets/components/alerts.css */\n\n/* \u57fa\u7840\u63d0\u793a\u6846 */\n.alert {\n padding: 1rem 1.5rem;\n margin: 1rem 0;\n border-left: 4px solid;\n border-radius: 4px;\n}\n\n/* \u4fe1\u606f\u63d0\u793a */\n.alert--info {\n background-color: #e3f2fd;\n border-color: #2196f3;\n color: #0d47a1;\n}\n\n.alert--info::before {\n content: \"\u2139\ufe0f\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5322","title":"5.3.2.2 \u8b66\u544a\u63d0\u793a","text":"CSS/* \u8b66\u544a\u63d0\u793a */\n.alert--warning {\n background-color: #fff3e0;\n border-color: #ff9800;\n color: #e65100;\n}\n\n.alert--warning::before {\n content: \"\u26a0\ufe0f\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5323","title":"5.3.2.3 \u9519\u8bef\u63d0\u793a","text":"CSS/* \u9519\u8bef\u63d0\u793a */\n.alert--error {\n background-color: #ffebee;\n border-color: #f44336;\n color: #b71c1c;\n}\n\n.alert--error::before {\n content: \"\u274c\";\n margin-right: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#533","title":"5.3.3 \u53cb\u94fe\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5331","title":"5.3.3.1 \u53cb\u94fe\u5361\u7247","text":"CSS/* docs/stylesheets/components/friends.css */\n\n/* \u53cb\u94fe\u5bb9\u5668 */\n.friend-links {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 1.5rem;\n margin: 2rem 0;\n}\n\n/* \u53cb\u94fe\u5361\u7247 */\n.friend-link {\n display: flex;\n align-items: center;\n padding: 1rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n transition: all 0.3s ease;\n}\n\n/* \u5934\u50cf */\n.friend-link__avatar {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n margin-right: 1rem;\n}\n\n/* \u4fe1\u606f */\n.friend-link__info {\n flex: 1;\n}\n\n.friend-link__name {\n font-weight: 600;\n color: var(--md-typeset-color);\n}\n\n.friend-link__desc {\n font-size: 0.85rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.25rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5332","title":"5.3.3.2 \u5206\u7c7b\u5c55\u793a","text":"CSS/* \u53cb\u94fe\u5206\u7c7b */\n.friend-links-section {\n margin: 2rem 0;\n}\n\n/* \u5206\u7c7b\u6807\u9898 */\n.friend-links-section__title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-bottom: 1rem;\n padding-left: 1rem;\n border-left: 4px solid var(--md-accent-fg-color);\n}\n\n/* \u5206\u7c7b\u63cf\u8ff0 */\n.friend-links-section__desc {\n color: var(--md-default-fg-color--light);\n margin-bottom: 1.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5333","title":"5.3.3.3 \u60ac\u505c\u6548\u679c","text":"CSS/* \u60ac\u505c\u6548\u679c */\n.friend-link:hover {\n transform: translateY(-2px);\n box-shadow: var(--md-shadow-z2);\n}\n\n/* \u5934\u50cf\u52a8\u753b */\n.friend-link:hover .friend-link__avatar {\n transform: rotate(360deg);\n transition: transform 0.6s ease;\n}\n\n/* \u6807\u7b7e\u6548\u679c */\n.friend-link__tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n font-size: 0.75rem;\n border-radius: 12px;\n background-color: var(--md-code-bg-color);\n margin-top: 0.5rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#534","title":"5.3.4 \u65f6\u95f4\u7ebf\u6837\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#5341","title":"5.3.4.1 \u65f6\u95f4\u8f74\u8bbe\u8ba1","text":"CSS/* docs/stylesheets/components/timeline.css */\n\n/* \u65f6\u95f4\u7ebf\u5bb9\u5668 */\n.timeline {\n position: relative;\n max-width: 800px;\n margin: 2rem auto;\n padding: 2rem 0;\n}\n\n/* \u65f6\u95f4\u8f74\u7ebf */\n.timeline::before {\n content: '';\n position: absolute;\n top: 0;\n left: calc(50% - 1px);\n width: 2px;\n height: 100%;\n background-color: var(--md-default-fg-color--lightest);\n}\n\n/* \u65f6\u95f4\u7ebf\u9879\u76ee */\n.timeline-item {\n position: relative;\n margin: 2rem 0;\n}\n\n/* \u4ea4\u9519\u5e03\u5c40 */\n.timeline-item:nth-child(odd) {\n padding-right: calc(50% + 2rem);\n}\n\n.timeline-item:nth-child(even) {\n padding-left: calc(50% + 2rem);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5342","title":"5.3.4.2 \u8282\u70b9\u6837\u5f0f","text":"CSS/* \u65f6\u95f4\u8282\u70b9 */\n.timeline-node {\n position: absolute;\n top: 50%;\n width: 16px;\n height: 16px;\n background-color: var(--md-primary-fg-color);\n border-radius: 50%;\n transform: translateY(-50%);\n}\n\n.timeline-item:nth-child(odd) .timeline-node {\n right: calc(50% - 8px);\n}\n\n.timeline-item:nth-child(even) .timeline-node {\n left: calc(50% - 8px);\n}\n\n/* \u8282\u70b9\u5185\u5bb9 */\n.timeline-content {\n background-color: var(--md-default-bg-color);\n padding: 1.5rem;\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n}\n\n/* \u65f6\u95f4\u6807\u7b7e */\n.timeline-date {\n position: absolute;\n top: 50%;\n color: var(--md-default-fg-color--light);\n transform: translateY(-50%);\n}\n\n.timeline-item:nth-child(odd) .timeline-date {\n left: calc(50% + 2rem);\n}\n\n.timeline-item:nth-child(even) .timeline-date {\n right: calc(50% + 2rem);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5343","title":"5.3.4.3 \u54cd\u5e94\u5f0f\u9002\u914d","text":"CSS/* \u79fb\u52a8\u7aef\u9002\u914d */\n@media screen and (max-width: 768px) {\n .timeline::before {\n left: 0;\n }\n\n .timeline-item {\n padding-left: 2rem !important;\n padding-right: 0 !important;\n }\n\n .timeline-node {\n left: -8px !important;\n right: auto !important;\n }\n\n .timeline-date {\n position: relative;\n top: auto;\n left: auto !important;\n right: auto !important;\n margin-bottom: 0.5rem;\n }\n}\n\n/* \u5e73\u677f\u7aef\u9002\u914d */\n@media screen and (min-width: 769px) and (max-width: 1024px) {\n .timeline {\n max-width: 90%;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#5344","title":"5.3.4.4 \u4f7f\u7528\u793a\u4f8b","text":"HTML<!-- \u65f6\u95f4\u7ebf\u793a\u4f8b -->\n<div class=\"timeline\">\n <div class=\"timeline-item\">\n <div class=\"timeline-node\"></div>\n <div class=\"timeline-date\">2024-01-01</div>\n <div class=\"timeline-content\">\n <h3>\u4e8b\u4ef6\u6807\u9898</h3>\n <p>\u4e8b\u4ef6\u63cf\u8ff0...</p>\n </div>\n </div>\n\n <!-- \u66f4\u591a\u65f6\u95f4\u7ebf\u9879\u76ee -->\n</div>\n\n<!-- \u53cb\u94fe\u793a\u4f8b -->\n<div class=\"friend-links-section\">\n <h2 class=\"friend-links-section__title\">\u6280\u672f\u535a\u5ba2</h2>\n <p class=\"friend-links-section__desc\">\u4f18\u79c0\u7684\u6280\u672f\u535a\u5ba2\u6536\u85cf</p>\n <div class=\"friend-links\">\n <a href=\"#\" class=\"friend-link\">\n <img src=\"avatar.jpg\" class=\"friend-link__avatar\">\n <div class=\"friend-link__info\">\n <div class=\"friend-link__name\">\u535a\u5ba2\u540d\u79f0</div>\n <div class=\"friend-link__desc\">\u535a\u5ba2\u63cf\u8ff0</div>\n <span class=\"friend-link__tag\">\u6807\u7b7e</span>\n </div>\n </a>\n </div>\n</div>\n\n<!-- \u63d0\u793a\u6846\u793a\u4f8b -->\n<div class=\"alert alert--info\">\n \u8fd9\u662f\u4e00\u6761\u4fe1\u606f\u63d0\u793a\n</div>\n\n<div class=\"alert alert--warning\">\n \u8fd9\u662f\u4e00\u6761\u8b66\u544a\u63d0\u793a\n</div>\n\n<div class=\"alert alert--error\">\n \u8fd9\u662f\u4e00\u6761\u9519\u8bef\u63d0\u793a\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#535","title":"5.3.5 \u5b8c\u6574\u914d\u7f6e","text":"YAML# mkdocs.yml\nextra_css:\n - stylesheets/components/cards.css\n - stylesheets/components/alerts.css\n - stylesheets/components/friends.css\n - stylesheets/components/timeline.css\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6-javascript","title":"6 JavaScript \u589e\u5f3a","text":""},{"location":"Tools/Blog/Mkdocs_Material/#61","title":"6.1 \u57fa\u7840\u914d\u7f6e","text":""},{"location":"Tools/Blog/Mkdocs_Material/#611-js","title":"6.1.1 \u5f15\u5165 JS \u6587\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6111","title":"6.1.1.1 \u672c\u5730\u6587\u4ef6","text":"docs/\n\u251c\u2500\u2500 javascripts/\n\u2502 \u251c\u2500\u2500 config/ # \u914d\u7f6e\u6587\u4ef6\n\u2502 \u2502 \u2514\u2500\u2500 main.js\n\u2502 \u251c\u2500\u2500 modules/ # \u529f\u80fd\u6a21\u5757\n\u2502 \u2502 \u251c\u2500\u2500 search.js\n\u2502 \u2502 \u2514\u2500\u2500 theme.js\n\u2502 \u251c\u2500\u2500 utils/ # \u5de5\u5177\u51fd\u6570\n\u2502 \u2502 \u2514\u2500\u2500 helpers.js\n\u2502 \u2514\u2500\u2500 extra.js # \u4e3b\u5165\u53e3\u6587\u4ef6\n
mkdocs.yml
\u4e2d\u5f15\u5165\uff1aextra_javascript:\n - javascripts/extra.js\n - javascripts/modules/search.js\n - javascripts/modules/theme.js\n
// docs/javascripts/extra.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u521d\u59cb\u5316\u4ee3\u7801\n console.log('Documentation loaded');\n});\n\n// docs/javascripts/modules/theme.js\nconst ThemeManager = {\n init() {\n // \u4e3b\u9898\u521d\u59cb\u5316\n },\n toggle() {\n // \u4e3b\u9898\u5207\u6362\n }\n};\n\n// docs/javascripts/utils/helpers.js\nconst Helpers = {\n debounce(fn, delay) {\n let timer = null;\n return function() {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, arguments), delay);\n };\n }\n};\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6112-cdn","title":"6.1.1.2 CDN \u5f15\u5165","text":"extra_javascript:\n # KaTeX \u6570\u5b66\u516c\u5f0f\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\n # Mermaid \u56fe\u8868\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\n # \u4ee3\u7801\u9ad8\u4eae\n - https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js\n
extra:\n cdn:\n # \u4f7f\u7528\u56fd\u5185 CDN\n enable: true\n provider: jsdelivr # \u6216 unpkg, cdnjs\n urls:\n katex: https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.js\n mermaid: https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.min.js\n
// docs/javascripts/config/cdn-fallback.js\nfunction loadFallbackScript(url, fallbackUrl) {\n const script = document.createElement('script');\n script.src = url;\n script.onerror = () => {\n console.warn(`Failed to load ${url}, trying fallback...`);\n const fallback = document.createElement('script');\n fallback.src = fallbackUrl;\n document.head.appendChild(fallback);\n };\n document.head.appendChild(script);\n}\n\n// \u4f7f\u7528\u793a\u4f8b\nloadFallbackScript(\n 'https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.js',\n 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js'\n);\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6113","title":"6.1.1.3 \u6a21\u5757\u5316\u7ba1\u7406","text":"// docs/javascripts/modules/theme.js\nexport class ThemeManager {\n constructor() {\n this.darkMode = false;\n }\n\n init() {\n this.loadPreference();\n this.bindEvents();\n }\n\n toggle() {\n this.darkMode = !this.darkMode;\n this.savePreference();\n this.applyTheme();\n }\n}\n\n// docs/javascripts/modules/search.js\nexport class SearchManager {\n constructor() {\n this.index = null;\n }\n\n init() {\n this.buildIndex();\n this.bindSearchEvents();\n }\n\n search(query) {\n // \u641c\u7d22\u5b9e\u73b0\n }\n}\n\n// docs/javascripts/extra.js\nimport { ThemeManager } from './modules/theme.js';\nimport { SearchManager } from './modules/search.js';\n\nconst theme = new ThemeManager();\nconst search = new SearchManager();\n\ndocument.addEventListener('DOMContentLoaded', () => {\n theme.init();\n search.init();\n});\n
// docs/javascripts/config/modules.js\nexport const ModuleConfig = {\n theme: {\n enabled: true,\n darkModeClass: 'dark-mode',\n storageKey: 'theme-preference'\n },\n search: {\n enabled: true,\n minChars: 3,\n maxResults: 10\n }\n};\n\n// \u4f7f\u7528\u914d\u7f6e\nimport { ModuleConfig } from '../config/modules.js';\n\nclass ThemeManager {\n constructor() {\n this.config = ModuleConfig.theme;\n if (!this.config.enabled) return;\n // \u521d\u59cb\u5316\u4ee3\u7801\n }\n}\n
// docs/javascripts/utils/helpers.js\nexport const DOM = {\n // DOM \u64cd\u4f5c\u8f85\u52a9\u51fd\u6570\n select: (selector) => document.querySelector(selector),\n selectAll: (selector) => document.querySelectorAll(selector),\n addClass: (element, className) => element.classList.add(className),\n removeClass: (element, className) => element.classList.remove(className)\n};\n\nexport const Storage = {\n // \u672c\u5730\u5b58\u50a8\u8f85\u52a9\u51fd\u6570\n get: (key) => localStorage.getItem(key),\n set: (key, value) => localStorage.setItem(key, value),\n remove: (key) => localStorage.removeItem(key)\n};\n\nexport const Events = {\n // \u4e8b\u4ef6\u5904\u7406\u8f85\u52a9\u51fd\u6570\n on: (element, event, handler) => element.addEventListener(event, handler),\n off: (element, event, handler) => element.removeEventListener(event, handler),\n trigger: (element, event) => element.dispatchEvent(new Event(event))\n};\n
# mkdocs.yml\nextra_javascript:\n # \u6838\u5fc3\u6587\u4ef6\n - javascripts/extra.js\n - javascripts/config/modules.js\n\n # \u529f\u80fd\u6a21\u5757\n - javascripts/modules/theme.js\n - javascripts/modules/search.js\n\n # \u5de5\u5177\u51fd\u6570\n - javascripts/utils/helpers.js\n\n # \u7b2c\u4e09\u65b9\u5e93\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n\n# \u6a21\u5757\u914d\u7f6e\nextra:\n javascript_modules:\n theme:\n enabled: true\n default: light\n search:\n enabled: true\n min_chars: 3\n
"},{"location":"Tools/Blog/Mkdocs_Material/#62","title":"6.2 \u7b2c\u4e09\u65b9\u5e93\u96c6\u6210","text":""},{"location":"Tools/Blog/Mkdocs_Material/#621-katex","title":"6.2.1 KaTeX \u6570\u5b66\u516c\u5f0f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6211","title":"6.2.1.1 \u57fa\u7840\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - pymdownx.arithmatex:\n generic: true\n\nextra_javascript:\n - javascripts/katex.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js\n\nextra_css:\n - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css\n
// docs/javascripts/katex.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false},\n {left: \"\\\\(\", right: \"\\\\)\", display: false},\n {left: \"\\\\[\", right: \"\\\\]\", display: true}\n ],\n throwOnError: false,\n errorColor: \"#cc0000\",\n strict: \"ignore\"\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6212","title":"6.2.1.2 \u81ea\u52a8\u6e32\u67d3","text":"// docs/javascripts/katex-auto.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true},\n {left: \"$\", right: \"$\", display: false}\n ],\n // \u81ea\u52a8\u6e32\u67d3\u8bbe\u7f6e\n ignoredTags: [\"script\", \"noscript\", \"style\", \"textarea\", \"pre\", \"code\"],\n ignoredClasses: [\"no-math\"],\n processEscapes: true,\n processEnvironments: true,\n // \u5904\u7406\u81ea\u5b9a\u4e49\u5b8f\n macros: {\n \"\\\\RR\": \"\\\\mathbb{R}\",\n \"\\\\NN\": \"\\\\mathbb{N}\",\n \"\\\\ZZ\": \"\\\\mathbb{Z}\"\n }\n });\n});\n
\u884c\u5185\u516c\u5f0f\uff1a$E = mc^2$\n\n\u5757\u7ea7\u516c\u5f0f\uff1a\n$$\n\\frac{n!}{k!(n-k)!} = \\binom{n}{k}\n$$\n\n\u81ea\u5b9a\u4e49\u5b8f\uff1a$\\RR$ \u8868\u793a\u5b9e\u6570\u96c6\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6213","title":"6.2.1.3 \u516c\u5f0f\u7f16\u53f7","text":"// docs/javascripts/katex-numbering.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // \u516c\u5f0f\u7f16\u53f7\u8ba1\u6570\u5668\n let equationNumbers = {};\n let numberings = {};\n\n renderMathInElement(document.body, {\n delimiters: [\n {left: \"$$\", right: \"$$\", display: true}\n ],\n // \u516c\u5f0f\u7f16\u53f7\u5904\u7406\n preProcess: (math) => {\n if (math.includes('\\\\label')) {\n const label = math.match(/\\\\label{([^}]*)}/)[1];\n const number = Object.keys(numberings).length + 1;\n numberings[label] = number;\n return math.replace(/\\\\label{[^}]*}/, `(${number})`);\n }\n return math;\n }\n });\n});\n
\u5e26\u7f16\u53f7\u7684\u516c\u5f0f\uff1a\n$$\nE = mc^2 \\label{eq:einstein}\n$$\n\n\u5f15\u7528\u4e0a\u9762\u7684\u516c\u5f0f $\\eqref{eq:einstein}$\n
"},{"location":"Tools/Blog/Mkdocs_Material/#622-mermaid","title":"6.2.2 Mermaid \u56fe\u8868","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6221","title":"6.2.2.1 \u521d\u59cb\u5316\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - pymdownx.superfences:\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n\nextra_javascript:\n - https://unpkg.com/mermaid@9/dist/mermaid.min.js\n - javascripts/mermaid.js\n
// docs/javascripts/mermaid.js\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n mermaid.initialize({\n startOnLoad: true,\n theme: 'default',\n sequence: {\n showSequenceNumbers: true,\n actorMargin: 50,\n messageMargin: 40\n },\n flowchart: {\n useMaxWidth: false,\n htmlLabels: true,\n curve: 'basis'\n },\n gantt: {\n titleTopMargin: 25,\n barHeight: 20,\n barGap: 4\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6222","title":"6.2.2.2 \u4e3b\u9898\u5b9a\u5236","text":"// docs/javascripts/mermaid-theme.js\nmermaid.initialize({\n theme: 'base',\n themeVariables: {\n // \u57fa\u7840\u989c\u8272\n primaryColor: '#2196f3',\n primaryTextColor: '#fff',\n primaryBorderColor: '#1976d2',\n lineColor: '#696969',\n\n // \u6d41\u7a0b\u56fe\u989c\u8272\n nodeBkg: '#fff',\n mainBkg: '#f8f9fa',\n nodeTextColor: '#333',\n\n // \u65f6\u5e8f\u56fe\u989c\u8272\n actorBkg: '#f8f9fa',\n actorBorder: '#2196f3',\n actorTextColor: '#333',\n\n // \u7518\u7279\u56fe\u989c\u8272\n sectionBkgColor: '#f8f9fa',\n altSectionBkgColor: '#fff',\n\n // \u6697\u8272\u4e3b\u9898\u652f\u6301\n darkMode: false\n }\n});\n
// \u76d1\u542c\u4e3b\u9898\u5207\u6362\ndocument.addEventListener('themeChanged', function(e) {\n const isDark = e.detail.theme === 'dark';\n mermaid.initialize({\n theme: isDark ? 'dark' : 'default',\n themeVariables: {\n darkMode: isDark\n }\n });\n // \u91cd\u65b0\u6e32\u67d3\u56fe\u8868\n mermaid.init(undefined, '.mermaid');\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6223","title":"6.2.2.3 \u4ea4\u4e92\u529f\u80fd","text":"// docs/javascripts/mermaid-interaction.js\nmermaid.initialize({\n securityLevel: 'loose',\n flowchart: {\n htmlLabels: true,\n useMaxWidth: true\n }\n});\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // \u4e3a\u56fe\u8868\u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n const diagrams = document.querySelectorAll('.mermaid');\n diagrams.forEach(diagram => {\n diagram.addEventListener('click', function(e) {\n const target = e.target;\n if (target.tagName === 'g' && target.classList.contains('node')) {\n const nodeId = target.id;\n console.log('Clicked node:', nodeId);\n // \u5904\u7406\u8282\u70b9\u70b9\u51fb\n handleNodeClick(nodeId);\n }\n });\n });\n});\n\nfunction handleNodeClick(nodeId) {\n // \u8282\u70b9\u70b9\u51fb\u5904\u7406\n const node = document.getElementById(nodeId);\n if (node) {\n // \u6dfb\u52a0\u9ad8\u4eae\u6548\u679c\n node.classList.add('node-highlight');\n setTimeout(() => {\n node.classList.remove('node-highlight');\n }, 1000);\n }\n}\n
/* docs/stylesheets/mermaid.css */\n.mermaid .node-highlight {\n animation: pulse 1s;\n}\n\n@keyframes pulse {\n 0% { opacity: 1; }\n 50% { opacity: 0.5; }\n 100% { opacity: 1; }\n}\n\n.mermaid .flowchart-link {\n transition: stroke-width 0.3s ease;\n}\n\n.mermaid .flowchart-link:hover {\n stroke-width: 2px;\n cursor: pointer;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6224","title":"6.2.2.4 \u4f7f\u7528\u793a\u4f8b","text":"```mermaid\ngraph TD\n A[\u5f00\u59cb] --> B{\u5224\u65ad}\n B -->|Yes| C[\u5904\u7406]\n B -->|No| D[\u7ed3\u675f]\n C --> D\n```\n
```mermaid\nsequenceDiagram\n participant \u5ba2\u6237\u7aef\n participant \u670d\u52a1\u5668\n\n \u5ba2\u6237\u7aef->>\u670d\u52a1\u5668: \u8bf7\u6c42\u6570\u636e\n \u670d\u52a1\u5668-->>\u5ba2\u6237\u7aef: \u8fd4\u56de\u54cd\u5e94\n```\n
"},{"location":"Tools/Blog/Mkdocs_Material/#623","title":"6.2.3 \u4ee3\u7801\u590d\u5236","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6231","title":"6.2.3.1 \u590d\u5236\u6309\u94ae","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1atheme:\n features:\n - content.code.copy\n\nextra_css:\n - stylesheets/code-copy.css\nextra_javascript:\n - javascripts/code-copy.js\n
/* docs/stylesheets/code-copy.css */\n\n/* \u590d\u5236\u6309\u94ae\u5bb9\u5668 */\n.copy-button {\n position: absolute;\n right: 0.5rem;\n top: 0.5rem;\n padding: 0.4rem;\n background-color: rgba(0, 0, 0, 0.1);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* \u6309\u94ae\u60ac\u505c\u6548\u679c */\n.copy-button:hover {\n background-color: rgba(0, 0, 0, 0.2);\n}\n\n/* \u56fe\u6807\u6837\u5f0f */\n.copy-button i {\n font-size: 1rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u6210\u529f\u72b6\u6001 */\n.copy-button.success {\n background-color: var(--md-accent-fg-color);\n}\n\n.copy-button.success i {\n color: white;\n}\n
// docs/javascripts/code-copy.js\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u4e3a\u6240\u6709\u4ee3\u7801\u5757\u6dfb\u52a0\u590d\u5236\u6309\u94ae\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach((codeBlock) => {\n const container = codeBlock.parentNode;\n const copyButton = document.createElement('button');\n copyButton.className = 'copy-button';\n copyButton.innerHTML = '<i class=\"material-icons\">content_copy</i>';\n container.style.position = 'relative';\n container.appendChild(copyButton);\n\n // \u6dfb\u52a0\u70b9\u51fb\u4e8b\u4ef6\n copyButton.addEventListener('click', async () => {\n try {\n await navigator.clipboard.writeText(codeBlock.textContent);\n showSuccess(copyButton);\n } catch (err) {\n showError(copyButton);\n }\n });\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6232","title":"6.2.3.2 \u63d0\u793a\u6d88\u606f","text":"/* \u63d0\u793a\u6d88\u606f\u6837\u5f0f */\n.copy-tooltip {\n position: absolute;\n top: -2rem;\n right: 0;\n padding: 0.4rem 0.8rem;\n background-color: var(--md-default-fg-color);\n color: var(--md-default-bg-color);\n border-radius: 4px;\n font-size: 0.8rem;\n opacity: 0;\n transform: translateY(0.4rem);\n transition: all 0.2s ease;\n}\n\n.copy-tooltip.show {\n opacity: 1;\n transform: translateY(0);\n}\n
// \u663e\u793a\u63d0\u793a\u6d88\u606f\nfunction showTooltip(button, message, type = 'success') {\n const tooltip = document.createElement('div');\n tooltip.className = `copy-tooltip ${type}`;\n tooltip.textContent = message;\n button.appendChild(tooltip);\n\n // \u6dfb\u52a0\u663e\u793a\u7c7b\n setTimeout(() => tooltip.classList.add('show'), 10);\n\n // \u81ea\u52a8\u79fb\u9664\n setTimeout(() => {\n tooltip.classList.remove('show');\n setTimeout(() => tooltip.remove(), 200);\n }, 2000);\n}\n\n// \u6210\u529f\u63d0\u793a\nfunction showSuccess(button) {\n button.classList.add('success');\n showTooltip(button, '\u590d\u5236\u6210\u529f\uff01');\n setTimeout(() => button.classList.remove('success'), 2000);\n}\n\n// \u9519\u8bef\u63d0\u793a\nfunction showError(button) {\n button.classList.add('error');\n showTooltip(button, '\u590d\u5236\u5931\u8d25\uff01', 'error');\n setTimeout(() => button.classList.remove('error'), 2000);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6233","title":"6.2.3.3 \u590d\u5236\u56de\u8c03","text":"JavaScript// \u5b9a\u4e49\u590d\u5236\u4e8b\u4ef6\u5904\u7406\u5668\nconst copyHandlers = {\n // \u590d\u5236\u524d\u5904\u7406\n beforeCopy: (code) => {\n // \u53ef\u4ee5\u5728\u8fd9\u91cc\u5bf9\u4ee3\u7801\u8fdb\u884c\u9884\u5904\u7406\n return code.trim();\n },\n\n // \u590d\u5236\u6210\u529f\u56de\u8c03\n onSuccess: (button, code) => {\n console.log('Copied:', code.length, 'characters');\n showSuccess(button);\n\n // \u89e6\u53d1\u81ea\u5b9a\u4e49\u4e8b\u4ef6\n const event = new CustomEvent('codeCopied', {\n detail: { code }\n });\n document.dispatchEvent(event);\n },\n\n // \u590d\u5236\u5931\u8d25\u56de\u8c03\n onError: (button, error) => {\n console.error('Copy failed:', error);\n showError(button);\n }\n};\n\n// \u4f7f\u7528\u56de\u8c03\nasync function copyCode(button, code) {\n try {\n const processedCode = copyHandlers.beforeCopy(code);\n await navigator.clipboard.writeText(processedCode);\n copyHandlers.onSuccess(button, processedCode);\n } catch (err) {\n copyHandlers.onError(button, err);\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#624","title":"6.2.4 \u56fe\u7247\u9884\u89c8","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6241-lightbox","title":"6.2.4.1 lightbox \u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\uff1amarkdown_extensions:\n - attr_list\n - md_in_html\n\nplugins:\n - glightbox\n\nextra_css:\n - stylesheets/glightbox.css\nextra_javascript:\n - javascripts/glightbox.js\n
// docs/javascripts/glightbox.js\ndocument.addEventListener('DOMContentLoaded', () => {\n const lightbox = GLightbox({\n selector: '.glightbox',\n touchNavigation: true,\n loop: false,\n autoplayVideos: true,\n preload: true,\n // \u57fa\u672c\u8bbe\u7f6e\n height: 'auto',\n zoomable: true,\n draggable: true,\n // \u52a8\u753b\u8bbe\u7f6e\n openEffect: 'zoom',\n closeEffect: 'fade',\n cssEfects: {\n fade: { in: 'fadeIn', out: 'fadeOut' },\n zoom: { in: 'zoomIn', out: 'zoomOut' }\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6242","title":"6.2.4.2 \u7f29\u653e\u529f\u80fd","text":"JavaScript// \u7f29\u653e\u529f\u80fd\u914d\u7f6e\nconst zoomConfig = {\n // \u7f29\u653e\u9009\u9879\n zoomable: true,\n dragToZoom: true,\n touchToZoom: true,\n\n // \u7f29\u653e\u7ea7\u522b\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.5,\n\n // \u53cc\u51fb\u7f29\u653e\n doubleTapZoom: 2,\n\n // \u7f29\u653e\u52a8\u753b\n zoomAnimation: true,\n zoomDuration: 300,\n\n // \u7f29\u653e\u63a7\u5236\u5668\n controls: {\n zoom: true,\n zoomIn: true,\n zoomOut: true,\n rotate: true\n }\n};\n\n// \u5e94\u7528\u7f29\u653e\u914d\u7f6e\nconst lightbox = GLightbox({\n ...zoomConfig,\n\n // \u7f29\u653e\u4e8b\u4ef6\u5904\u7406\n onZoom: (slider) => {\n const { zoom, image } = slider;\n console.log(`Current zoom level: ${zoom}`);\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6243","title":"6.2.4.3 \u624b\u52bf\u652f\u6301","text":"JavaScript// \u624b\u52bf\u914d\u7f6e\nconst gestureConfig = {\n // \u89e6\u6478\u5bfc\u822a\n touchNavigation: true,\n touchFollowAxis: true,\n\n // \u62d6\u52a8\u8bbe\u7f6e\n draggable: true,\n dragToleranceX: 40,\n dragToleranceY: 65,\n\n // \u624b\u52bf\u4e8b\u4ef6\n gestures: {\n // \u634f\u5408\u7f29\u653e\n pinchToZoom: true,\n pinchThreshold: 50,\n\n // \u53cc\u6307\u65cb\u8f6c\n rotateToZoom: true,\n rotateThreshold: 15,\n\n // \u6ed1\u52a8\u5207\u6362\n swipeThreshold: 50,\n swipeToClose: true\n }\n};\n\n// \u624b\u52bf\u4e8b\u4ef6\u5904\u7406\nconst gestureHandlers = {\n // \u89e6\u6478\u5f00\u59cb\n onTouchStart: (e) => {\n const touch = e.touches[0];\n startX = touch.clientX;\n startY = touch.clientY;\n },\n\n // \u89e6\u6478\u79fb\u52a8\n onTouchMove: (e) => {\n if (!isDragging) return;\n const touch = e.touches[0];\n const deltaX = touch.clientX - startX;\n const deltaY = touch.clientY - startY;\n\n // \u5904\u7406\u79fb\u52a8\n handleImageMove(deltaX, deltaY);\n },\n\n // \u89e6\u6478\u7ed3\u675f\n onTouchEnd: (e) => {\n isDragging = false;\n // \u5904\u7406\u60ef\u6027\u6ed1\u52a8\n handleMomentum();\n }\n};\n\n// \u521b\u5efa\u589e\u5f3a\u7684\u56fe\u7247\u9884\u89c8\nconst enhancedLightbox = GLightbox({\n ...zoomConfig,\n ...gestureConfig,\n\n // \u4e8b\u4ef6\u76d1\u542c\n listeners: {\n touchstart: gestureHandlers.onTouchStart,\n touchmove: gestureHandlers.onTouchMove,\n touchend: gestureHandlers.onTouchEnd\n }\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6244","title":"6.2.4.4 \u5b8c\u6574\u793a\u4f8b","text":"JavaScript// docs/javascripts/image-preview.js\ndocument.addEventListener('DOMContentLoaded', () => {\n // \u521d\u59cb\u5316\u914d\u7f6e\n const config = {\n // \u57fa\u7840\u8bbe\u7f6e\n selector: '.glightbox',\n touchNavigation: true,\n loop: false,\n\n // \u7f29\u653e\u8bbe\u7f6e\n zoomable: true,\n draggable: true,\n dragToleranceX: 40,\n dragToleranceY: 65,\n\n // \u52a8\u753b\u8bbe\u7f6e\n openEffect: 'zoom',\n closeEffect: 'fade',\n\n // \u624b\u52bf\u8bbe\u7f6e\n touchFollowAxis: true,\n\n // \u754c\u9762\u8bbe\u7f6e\n preload: true,\n height: 'auto',\n\n // \u4e8b\u4ef6\u5904\u7406\n onOpen: () => {\n console.log('Lightbox opened');\n },\n onClose: () => {\n console.log('Lightbox closed');\n },\n onZoom: (slider) => {\n console.log('Image zoomed');\n }\n };\n\n // \u521d\u59cb\u5316 GLightbox\n const lightbox = GLightbox(config);\n\n // \u6dfb\u52a0\u952e\u76d8\u652f\u6301\n document.addEventListener('keydown', (e) => {\n if (!lightbox.isOpen) return;\n\n switch(e.key) {\n case 'ArrowLeft':\n lightbox.prev();\n break;\n case 'ArrowRight':\n lightbox.next();\n break;\n case 'Escape':\n lightbox.close();\n break;\n }\n });\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#63","title":"6.3 \u81ea\u5b9a\u4e49\u529f\u80fd","text":""},{"location":"Tools/Blog/Mkdocs_Material/#631","title":"6.3.1 \u9875\u9762\u4ea4\u4e92","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6311","title":"6.3.1.1 \u6eda\u52a8\u4e8b\u4ef6","text":"// docs/javascripts/scroll.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6eda\u52a8\u5904\u7406\u51fd\u6570\n function handleScroll() {\n const scrollTop = window.scrollY;\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight;\n\n // \u6eda\u52a8\u8fdb\u5ea6\n const scrollPercent = (scrollTop / (docHeight - windowHeight)) * 100;\n\n // \u66f4\u65b0\u8fdb\u5ea6\u6761\n updateProgress(scrollPercent);\n\n // \u5904\u7406\u5143\u7d20\u53ef\u89c1\u6027\n handleVisibility();\n }\n\n // \u4f7f\u7528\u8282\u6d41\u4f18\u5316\u6eda\u52a8\u4e8b\u4ef6\n const throttledScroll = throttle(handleScroll, 100);\n window.addEventListener('scroll', throttledScroll);\n});\n\n// \u8282\u6d41\u51fd\u6570\nfunction throttle(fn, delay) {\n let lastCall = 0;\n return function(...args) {\n const now = Date.now();\n if (now - lastCall >= delay) {\n lastCall = now;\n fn.apply(this, args);\n }\n };\n}\n
// \u68c0\u6d4b\u5143\u7d20\u662f\u5426\u8fdb\u5165\u89c6\u53e3\nfunction handleVisibility() {\n const elements = document.querySelectorAll('.animate-on-scroll');\n\n elements.forEach(element => {\n const rect = element.getBoundingClientRect();\n const isVisible = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= window.innerHeight &&\n rect.right <= window.innerWidth\n );\n\n if (isVisible) {\n element.classList.add('is-visible');\n }\n });\n}\n\n// CSS \u6837\u5f0f\n.animate-on-scroll {\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.6s ease;\n}\n\n.animate-on-scroll.is-visible {\n opacity: 1;\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6312","title":"6.3.1.2 \u70b9\u51fb\u4e8b\u4ef6","text":"// docs/javascripts/click.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u4ee3\u7801\u5757\u70b9\u51fb\u590d\u5236\n setupCodeCopy();\n\n // \u56fe\u7247\u70b9\u51fb\u653e\u5927\n setupImageZoom();\n\n // \u76ee\u5f55\u70b9\u51fb\u6eda\u52a8\n setupTocScroll();\n});\n\n// \u4ee3\u7801\u590d\u5236\u529f\u80fd\nfunction setupCodeCopy() {\n const codeBlocks = document.querySelectorAll('pre code');\n\n codeBlocks.forEach(block => {\n block.addEventListener('click', async function(e) {\n if (e.target.classList.contains('copy-button')) {\n try {\n await navigator.clipboard.writeText(block.textContent);\n showToast('\u590d\u5236\u6210\u529f\uff01');\n } catch (err) {\n showToast('\u590d\u5236\u5931\u8d25', 'error');\n }\n }\n });\n });\n}\n\n// \u56fe\u7247\u7f29\u653e\u529f\u80fd\nfunction setupImageZoom() {\n const images = document.querySelectorAll('.md-content img');\n\n images.forEach(img => {\n img.addEventListener('click', function() {\n const overlay = document.createElement('div');\n overlay.className = 'image-overlay';\n overlay.innerHTML = `\n <img src=\"${img.src}\" alt=\"${img.alt}\">\n <button class=\"close-button\">\u00d7</button>\n `;\n\n document.body.appendChild(overlay);\n\n overlay.querySelector('.close-button').addEventListener('click', () => {\n overlay.remove();\n });\n });\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6313","title":"6.3.1.3 \u952e\u76d8\u4e8b\u4ef6","text":"JavaScript// docs/javascripts/keyboard.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u952e\u76d8\u5bfc\u822a\n setupKeyboardNav();\n\n // \u641c\u7d22\u5feb\u6377\u952e\n setupSearchShortcut();\n});\n\n// \u952e\u76d8\u5bfc\u822a\nfunction setupKeyboardNav() {\n document.addEventListener('keydown', function(e) {\n // ALT + \u65b9\u5411\u952e\u5bfc\u822a\n if (e.altKey) {\n switch(e.key) {\n case 'ArrowLeft': // \u4e0a\u4e00\u9875\n navigatePage('prev');\n break;\n case 'ArrowRight': // \u4e0b\u4e00\u9875\n navigatePage('next');\n break;\n case 'ArrowUp': // \u56de\u5230\u9876\u90e8\n window.scrollTo({top: 0, behavior: 'smooth'});\n break;\n case 'ArrowDown': // \u5230\u8fbe\u5e95\u90e8\n window.scrollTo({\n top: document.documentElement.scrollHeight,\n behavior: 'smooth'\n });\n break;\n }\n }\n });\n}\n\n// \u641c\u7d22\u5feb\u6377\u952e\nfunction setupSearchShortcut() {\n document.addEventListener('keydown', function(e) {\n // \u6309\u4e0b '/' \u952e\u89e6\u53d1\u641c\u7d22\n if (e.key === '/' && !e.ctrlKey && !e.altKey && !e.metaKey) {\n e.preventDefault();\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.focus();\n }\n }\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#632","title":"6.3.2 \u52a8\u753b\u6548\u679c","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6321","title":"6.3.2.1 \u8fc7\u6e21\u52a8\u753b","text":"/* docs/stylesheets/transitions.css */\n\n/* \u9875\u9762\u5207\u6362\u8fc7\u6e21 */\n.md-content {\n animation: fadeIn 0.3s ease-in-out;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* \u5bfc\u822a\u8fc7\u6e21 */\n.md-nav__link {\n transition: color 0.2s ease, padding-left 0.2s ease;\n}\n\n.md-nav__link:hover {\n padding-left: 0.5rem;\n color: var(--md-accent-fg-color);\n}\n
// docs/javascripts/transitions.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u9875\u9762\u5207\u6362\u52a8\u753b\n setupPageTransitions();\n});\n\nfunction setupPageTransitions() {\n // \u76d1\u542c\u9875\u9762\u5207\u6362\u4e8b\u4ef6\n document.addEventListener('DOMContentLoaded', function() {\n document.body.classList.add('page-transition-ready');\n });\n\n // \u9875\u9762\u79bb\u5f00\u52a8\u753b\n window.addEventListener('beforeunload', function() {\n document.body.classList.add('page-transition-exit');\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6322","title":"6.3.2.2 \u52a0\u8f7d\u52a8\u753b","text":"/* docs/stylesheets/loading.css */\n\n/* \u52a0\u8f7d\u52a8\u753b\u5bb9\u5668 */\n.loading-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--md-default-bg-color);\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 999;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n/* \u52a0\u8f7d\u52a8\u753b */\n.loading-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid var(--md-primary-fg-color--light);\n border-top-color: var(--md-primary-fg-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n
// docs/javascripts/loading.js\nclass LoadingManager {\n constructor() {\n this.overlay = null;\n this.createLoadingOverlay();\n }\n\n createLoadingOverlay() {\n this.overlay = document.createElement('div');\n this.overlay.className = 'loading-overlay';\n this.overlay.innerHTML = '<div class=\"loading-spinner\"></div>';\n document.body.appendChild(this.overlay);\n }\n\n show() {\n this.overlay.style.opacity = '1';\n this.overlay.style.visibility = 'visible';\n }\n\n hide() {\n this.overlay.style.opacity = '0';\n setTimeout(() => {\n this.overlay.style.visibility = 'hidden';\n }, 300);\n }\n}\n\n// \u4f7f\u7528\u52a0\u8f7d\u7ba1\u7406\u5668\nconst loading = new LoadingManager();\n\n// \u9875\u9762\u52a0\u8f7d\u5b8c\u6210\u540e\u9690\u85cf\nwindow.addEventListener('load', () => {\n loading.hide();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6323","title":"6.3.2.3 \u4ea4\u4e92\u52a8\u753b","text":"// docs/javascripts/interactions.js\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u6309\u94ae\u6ce2\u7eb9\u6548\u679c\n setupRippleEffect();\n\n // \u5361\u7247\u60ac\u6d6e\u6548\u679c\n setupCardHover();\n\n // \u5217\u8868\u9879\u52a8\u753b\n setupListAnimations();\n});\n\n// \u6ce2\u7eb9\u6548\u679c\nfunction setupRippleEffect() {\n const buttons = document.querySelectorAll('.md-button');\n\n buttons.forEach(button => {\n button.addEventListener('click', function(e) {\n const ripple = document.createElement('div');\n ripple.className = 'ripple';\n\n const rect = button.getBoundingClientRect();\n const size = Math.max(rect.width, rect.height);\n\n ripple.style.width = ripple.style.height = `${size}px`;\n ripple.style.left = `${e.clientX - rect.left - size/2}px`;\n ripple.style.top = `${e.clientY - rect.top - size/2}px`;\n\n button.appendChild(ripple);\n\n setTimeout(() => ripple.remove(), 600);\n });\n });\n}\n\n// \u5361\u7247\u60ac\u6d6e\u6548\u679c\nfunction setupCardHover() {\n const cards = document.querySelectorAll('.md-card');\n\n cards.forEach(card => {\n card.addEventListener('mousemove', function(e) {\n const rect = card.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const centerX = rect.width / 2;\n const centerY = rect.height / 2;\n\n const angleY = -(x - centerX) / 20;\n const angleX = (y - centerY) / 20;\n\n card.style.transform = \n `perspective(1000px) rotateX(${angleX}deg) rotateY(${angleY}deg)`;\n });\n\n card.addEventListener('mouseleave', function() {\n card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';\n });\n });\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#633","title":"6.3.3 \u6570\u636e\u7edf\u8ba1","text":""},{"location":"Tools/Blog/Mkdocs_Material/#6331","title":"6.3.3.1 \u8bbf\u95ee\u7edf\u8ba1","text":"// docs/javascripts/analytics.js\nclass Analytics {\n constructor() {\n this.storageKey = 'site_analytics';\n this.data = this.loadData();\n }\n\n loadData() {\n const stored = localStorage.getItem(this.storageKey);\n return stored ? JSON.parse(stored) : {\n pageViews: {},\n totalVisits: 0,\n firstVisit: Date.now(),\n lastVisit: Date.now()\n };\n }\n\n saveData() {\n localStorage.setItem(this.storageKey, JSON.stringify(this.data));\n }\n\n recordPageView() {\n const path = window.location.pathname;\n this.data.pageViews[path] = (this.data.pageViews[path] || 0) + 1;\n this.data.totalVisits++;\n this.data.lastVisit = Date.now();\n this.saveData();\n }\n\n getStats() {\n return {\n totalVisits: this.data.totalVisits,\n uniquePages: Object.keys(this.data.pageViews).length,\n mostViewed: this.getMostViewedPages(5)\n };\n }\n\n getMostViewedPages(limit = 5) {\n return Object.entries(this.data.pageViews)\n .sort(([,a], [,b]) => b - a)\n .slice(0, limit);\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6332","title":"6.3.3.2 \u9605\u8bfb\u65f6\u957f","text":"JavaScript// docs/javascripts/read-time.js\nclass ReadTimeTracker {\n constructor() {\n this.startTime = Date.now();\n this.isReading = true;\n this.totalTime = 0;\n this.idleTimeout = null;\n this.setupTracking();\n }\n\n setupTracking() {\n // \u76d1\u542c\u7528\u6237\u6d3b\u52a8\n ['mousemove', 'keydown', 'scroll', 'click'].forEach(event => {\n document.addEventListener(event, () => this.handleActivity());\n });\n\n // \u9875\u9762\u5931\u7126\u6682\u505c\u8ba1\u65f6\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) {\n this.pauseTracking();\n } else {\n this.resumeTracking();\n }\n });\n }\n\n handleActivity() {\n if (!this.isReading) {\n this.resumeTracking();\n }\n\n clearTimeout(this.idleTimeout);\n this.idleTimeout = setTimeout(() => this.pauseTracking(), 60000); // 1\u5206\u949f\u65e0\u6d3b\u52a8\u6682\u505c\n }\n\n pauseTracking() {\n if (this.isReading) {\n this.totalTime += Date.now() - this.startTime;\n this.isReading = false;\n }\n }\n\n resumeTracking() {\n if (!this.isReading) {\n this.startTime = Date.now();\n this.isReading = true;\n }\n }\n\n getReadTime() {\n const currentTime = this.isReading ? \n this.totalTime + (Date.now() - this.startTime) : \n this.totalTime;\n\n return Math.floor(currentTime / 1000 / 60); // \u8fd4\u56de\u5206\u949f\n // \u663e\u793a\u9605\u8bfb\u65f6\u957f\n displayReadTime() {\n const readTimeElement = document.querySelector('.read-time');\n if (readTimeElement) {\n const minutes = this.getReadTime();\n readTimeElement.textContent = `\u9605\u8bfb\u65f6\u957f: ${minutes} \u5206\u949f`;\n }\n }\n\n // \u83b7\u53d6\u9605\u8bfb\u8fdb\u5ea6\n getReadProgress() {\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight - windowHeight;\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return Math.min((scrollTop / docHeight) * 100, 100);\n }\n\n // \u4fdd\u5b58\u9605\u8bfb\u8bb0\u5f55\n saveReadingHistory() {\n const path = window.location.pathname;\n const history = JSON.parse(localStorage.getItem('reading_history') || '{}');\n\n history[path] = {\n lastRead: Date.now(),\n readTime: this.getReadTime(),\n progress: this.getReadProgress()\n };\n\n localStorage.setItem('reading_history', JSON.stringify(history));\n }\n}\n\n// \u521d\u59cb\u5316\u9605\u8bfb\u65f6\u957f\u8ffd\u8e2a\nconst readTracker = new ReadTimeTracker();\n\n// \u5b9a\u671f\u66f4\u65b0\u663e\u793a\nsetInterval(() => {\n readTracker.displayReadTime();\n}, 30000); // \u6bcf30\u79d2\u66f4\u65b0\u4e00\u6b21\n\n// \u9875\u9762\u79bb\u5f00\u65f6\u4fdd\u5b58\u8bb0\u5f55\nwindow.addEventListener('beforeunload', () => {\n readTracker.saveReadingHistory();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#6333","title":"6.3.3.3 \u5206\u4eab\u7edf\u8ba1","text":"// docs/javascripts/share.js\nclass ShareTracker {\n constructor() {\n this.storageKey = 'share_statistics';\n this.data = this.loadData();\n this.setupShareButtons();\n }\n\n loadData() {\n return JSON.parse(localStorage.getItem(this.storageKey) || '{}');\n }\n\n saveData() {\n localStorage.setItem(this.storageKey, JSON.stringify(this.data));\n }\n\n setupShareButtons() {\n const shareButtons = document.querySelectorAll('.share-button');\n\n shareButtons.forEach(button => {\n button.addEventListener('click', (e) => {\n const platform = button.dataset.platform;\n this.shareContent(platform);\n this.recordShare(platform);\n });\n });\n }\n\n shareContent(platform) {\n const url = encodeURIComponent(window.location.href);\n const title = encodeURIComponent(document.title);\n const description = encodeURIComponent(\n document.querySelector('meta[name=\"description\"]')?.content || ''\n );\n\n let shareUrl;\n switch (platform) {\n case 'twitter':\n shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;\n break;\n case 'facebook':\n shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;\n break;\n case 'linkedin':\n shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;\n break;\n case 'weibo':\n shareUrl = `http://service.weibo.com/share/share.php?url=${url}&title=${title}`;\n break;\n }\n\n if (shareUrl) {\n window.open(shareUrl, '_blank', 'width=600,height=400');\n }\n }\n\n recordShare(platform) {\n const path = window.location.pathname;\n if (!this.data[path]) {\n this.data[path] = {};\n }\n if (!this.data[path][platform]) {\n this.data[path][platform] = 0;\n }\n this.data[path][platform]++;\n this.saveData();\n this.updateShareCount(platform);\n }\n\n updateShareCount(platform) {\n const countElement = document.querySelector(`.share-count[data-platform=\"${platform}\"]`);\n if (countElement) {\n const path = window.location.pathname;\n countElement.textContent = this.data[path][platform] || 0;\n }\n }\n\n getShareStats() {\n return Object.entries(this.data).map(([path, platforms]) => ({\n path,\n total: Object.values(platforms).reduce((a, b) => a + b, 0),\n platforms\n }));\n }\n\n displayShareStats() {\n const stats = this.getShareStats();\n console.table(stats);\n return stats;\n }\n}\n
// docs/javascripts/statistics-visualization.js\nclass StatisticsVisualizer {\n constructor(analytics, readTracker, shareTracker) {\n this.analytics = analytics;\n this.readTracker = readTracker;\n this.shareTracker = shareTracker;\n }\n\n createDashboard() {\n const dashboard = document.createElement('div');\n dashboard.className = 'statistics-dashboard';\n dashboard.innerHTML = `\n <div class=\"dashboard-section\">\n <h3>\u8bbf\u95ee\u7edf\u8ba1</h3>\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.analytics.data.totalVisits}</div>\n <div class=\"stat-label\">\u603b\u8bbf\u95ee\u91cf</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.readTracker.getReadTime()}</div>\n <div class=\"stat-label\">\u603b\u9605\u8bfb\u65f6\u957f(\u5206\u949f)</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-value\">${this.getTotalShares()}</div>\n <div class=\"stat-label\">\u603b\u5206\u4eab\u6b21\u6570</div>\n </div>\n </div>\n <div id=\"visitsChart\"></div>\n </div>\n `;\n\n document.body.appendChild(dashboard);\n this.renderCharts();\n }\n\n renderCharts() {\n // \u4f7f\u7528 Chart.js \u7ed8\u5236\u56fe\u8868\n const ctx = document.getElementById('visitsChart').getContext('2d');\n new Chart(ctx, {\n type: 'line',\n data: {\n labels: this.getTimeLabels(),\n datasets: [{\n label: '\u8bbf\u95ee\u8d8b\u52bf',\n data: this.getVisitData(),\n borderColor: 'rgb(75, 192, 192)',\n tension: 0.1\n }]\n },\n options: {\n responsive: true,\n scales: {\n y: {\n beginAtZero: true\n }\n }\n }\n });\n }\n\n getTotalShares() {\n const stats = this.shareTracker.getShareStats();\n return stats.reduce((total, page) => total + page.total, 0);\n }\n\n getTimeLabels() {\n // \u83b7\u53d6\u6700\u8fd17\u5929\u7684\u65e5\u671f\u6807\u7b7e\n return Array.from({length: 7}, (_, i) => {\n const d = new Date();\n d.setDate(d.getDate() - i);\n return d.toLocaleDateString();\n }).reverse();\n }\n\n getVisitData() {\n // \u5904\u7406\u8bbf\u95ee\u6570\u636e\n return this.analytics.getVisitsByDate(7);\n }\n}\n\n// \u6837\u5f0f\nconst styles = `\n .statistics-dashboard {\n padding: 2rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z2);\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1rem;\n margin: 1rem 0;\n }\n\n .stat-card {\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n text-align: center;\n }\n\n .stat-value {\n font-size: 2rem;\n font-weight: bold;\n color: var(--md-primary-fg-color);\n }\n\n .stat-label {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.5rem;\n }\n`;\n\n// \u5c06\u6837\u5f0f\u6dfb\u52a0\u5230\u6587\u6863\nconst styleSheet = document.createElement('style');\nstyleSheet.textContent = styles;\ndocument.head.appendChild(styleSheet);\n\n// \u521d\u59cb\u5316\u7edf\u8ba1\u53ef\u89c6\u5316\nconst visualizer = new StatisticsVisualizer(analytics, readTracker, shareTracker);\nvisualizer.createDashboard();\n
\u8fd9\u6837\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u5b8c\u6574\u7684\u6570\u636e\u7edf\u8ba1\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u4f7f\u7528\u65f6\uff0c\u53ea\u9700\u8981\u5728 mkdocs.yml \u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684 JavaScript \u6587\u4ef6\uff1a
YAMLextra_javascript:\n - javascripts/analytics.js\n - javascripts/read-time.js\n - javascripts/share.js\n - javascripts/statistics-visualization.js\n - https://cdn.jsdelivr.net/npm/chart.js\n
\u7136\u540e\u5728\u9875\u9762\u4e2d\u6dfb\u52a0\u5fc5\u8981\u7684 HTML \u5143\u7d20\u5373\u53ef\u542f\u7528\u8fd9\u4e9b\u529f\u80fd\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#7","title":"7 \u6a21\u677f\u590d\u5199","text":""},{"location":"Tools/Blog/Mkdocs_Material/#71","title":"7.1 \u91cd\u5199\u9875\u9762\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#711","title":"7.1.1 \u4e3b\u9875\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7111","title":"7.1.1.1 \u5e03\u5c40\u7ed3\u6784","text":"<!-- docs/overrides/main.html -->\n{% extends \"base.html\" %}\n\n{% block hero %}\n<section class=\"home-hero\">\n <div class=\"hero-content\">\n <h1>{{ config.site_name }}</h1>\n <p>{{ config.site_description }}</p>\n\n <!-- \u81ea\u5b9a\u4e49\u641c\u7d22\u6846 -->\n <div class=\"hero-search\">\n <input type=\"text\" placeholder=\"\u641c\u7d22\u6587\u6863...\" id=\"hero-search-input\">\n <button>\n <span class=\"twemoji\">\n {% include \".icons/material/magnify.svg\" %}\n </span>\n </button>\n </div>\n\n <!-- \u5feb\u901f\u5165\u53e3 -->\n <div class=\"hero-buttons\">\n <a href=\"{{ page.next_page.url | url }}\" class=\"md-button md-button--primary\">\n \u5feb\u901f\u5f00\u59cb\n <span class=\"twemoji\">\n {% include \".icons/material/arrow-right.svg\" %}\n </span>\n </a>\n <a href=\"{{ config.repo_url }}\" class=\"md-button\">\n \u67e5\u770b\u6e90\u7801\n <span class=\"twemoji\">\n {% include \".icons/material/github.svg\" %}\n </span>\n </a>\n </div>\n </div>\n</section>\n{% endblock %}\n\n{% block content %}\n<section class=\"home-features\">\n <h2>\u7279\u8272\u529f\u80fd</h2>\n <div class=\"features-grid\">\n <!-- \u529f\u80fd\u5361\u7247 -->\n <div class=\"feature-card\">\n <div class=\"feature-icon\">\n {% include \".icons/material/speedometer.svg\" %}\n </div>\n <h3>\u9ad8\u6027\u80fd</h3>\n <p>\u57fa\u4e8e\u9759\u6001\u7ad9\u70b9\u751f\u6210\uff0c\u52a0\u8f7d\u8fc5\u901f</p>\n </div>\n <!-- \u66f4\u591a\u529f\u80fd\u5361\u7247 -->\n </div>\n</section>\n\n<!-- \u6700\u8fd1\u66f4\u65b0 -->\n<section class=\"home-updates\">\n <h2>\u6700\u8fd1\u66f4\u65b0</h2>\n <div class=\"updates-list\">\n {% for update in config.theme.updates[:5] %}\n <div class=\"update-item\">\n <span class=\"update-date\">{{ update.date }}</span>\n <a href=\"{{ update.url | url }}\">{{ update.title }}</a>\n </div>\n {% endfor %}\n </div>\n</section>\n{% endblock %}\n
/* docs/stylesheets/home.css */\n\n/* \u4e3b\u9875\u82f1\u96c4\u533a */\n.home-hero {\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n background: linear-gradient(\n to bottom right,\n var(--md-primary-fg-color),\n var(--md-accent-fg-color)\n );\n color: var(--md-primary-bg-color);\n}\n\n.hero-content {\n max-width: 800px;\n padding: 2rem;\n}\n\n.hero-content h1 {\n font-size: 3rem;\n margin-bottom: 1rem;\n}\n\n/* \u641c\u7d22\u6846\u6837\u5f0f */\n.hero-search {\n margin: 2rem 0;\n position: relative;\n}\n\n.hero-search input {\n width: 100%;\n padding: 1rem 3rem 1rem 1rem;\n border: none;\n border-radius: 2rem;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n backdrop-filter: blur(10px);\n}\n\n/* \u529f\u80fd\u533a\u6837\u5f0f */\n.features-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 2rem;\n padding: 2rem;\n}\n\n.feature-card {\n padding: 2rem;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z1);\n transition: transform 0.3s ease;\n}\n\n.feature-card:hover {\n transform: translateY(-4px);\n}\n\n/* \u66f4\u65b0\u5217\u8868\u6837\u5f0f */\n.updates-list {\n max-width: 800px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.update-item {\n display: flex;\n align-items: center;\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .hero-content h1 {\n font-size: 2rem;\n }\n\n .features-grid {\n grid-template-columns: 1fr;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7112","title":"7.1.1.2 \u7ec4\u4ef6\u914d\u7f6e","text":"mkdocs.yml
\u4e2d\u914d\u7f6e\u4e3b\u9898\uff1atheme:\n name: material\n custom_dir: docs/overrides\n features:\n - navigation.tabs\n - navigation.sections\n - navigation.expand\n\n # \u4e3b\u9875\u914d\u7f6e\n homepage:\n hero:\n title: \u7f51\u7ad9\u6807\u9898\n subtitle: \u7f51\u7ad9\u63cf\u8ff0\n image: assets/hero.svg\n\n # \u529f\u80fd\u7279\u6027\n features:\n - title: \u9ad8\u6027\u80fd\n description: \u57fa\u4e8e\u9759\u6001\u7ad9\u70b9\u751f\u6210\uff0c\u52a0\u8f7d\u8fc5\u901f\n icon: material/speedometer\n - title: \u6613\u4e8e\u4f7f\u7528\n description: \u7b80\u5355\u7684\u914d\u7f6e\uff0c\u5feb\u901f\u4e0a\u624b\n icon: material/puzzle\n # \u66f4\u591a\u529f\u80fd\u7279\u6027...\n\n # \u66f4\u65b0\u5217\u8868\n updates:\n - date: 2024-01-20\n title: \u65b0\u589e\u529f\u80fdA\n url: /new-feature-a\n - date: 2024-01-18\n title: \u95ee\u9898\u4fee\u590dB\n url: /bug-fix-b\n # \u66f4\u591a\u66f4\u65b0...\n
// docs/javascripts/home.js\nclass HomePage {\n constructor() {\n this.searchInput = document.getElementById('hero-search-input');\n this.setupSearch();\n this.setupFeatureCards();\n }\n\n setupSearch() {\n this.searchInput?.addEventListener('keyup', (e) => {\n if (e.key === 'Enter') {\n const query = e.target.value;\n window.location.href = `${window.location.origin}/search.html?q=${encodeURIComponent(query)}`;\n }\n });\n }\n\n setupFeatureCards() {\n const cards = document.querySelectorAll('.feature-card');\n\n cards.forEach(card => {\n card.addEventListener('mousemove', (e) => {\n const rect = card.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n card.style.setProperty('--mouse-x', `${x}px`);\n card.style.setProperty('--mouse-y', `${y}px`);\n });\n });\n }\n}\n\n// \u521d\u59cb\u5316\u4e3b\u9875\ndocument.addEventListener('DOMContentLoaded', () => {\n new HomePage();\n});\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7113","title":"7.1.1.3 \u81ea\u5b9a\u4e49\u533a\u57df","text":"<!-- docs/overrides/partials/custom-content.html -->\n{% if page.meta.custom_content %}\n<section class=\"custom-content\">\n <!-- \u516c\u544a\u533a -->\n {% if page.meta.announcements %}\n <div class=\"announcements\">\n {% for announcement in page.meta.announcements %}\n <div class=\"announcement-item\">\n <span class=\"announcement-tag\">{{ announcement.tag }}</span>\n <p>{{ announcement.content }}</p>\n </div>\n {% endfor %}\n </div>\n {% endif %}\n\n <!-- \u8d21\u732e\u8005\u533a\u57df -->\n {% if page.meta.contributors %}\n <div class=\"contributors\">\n <h3>\u9879\u76ee\u8d21\u732e\u8005</h3>\n <div class=\"contributors-grid\">\n {% for contributor in page.meta.contributors %}\n <a href=\"{{ contributor.url }}\" class=\"contributor-card\">\n <img src=\"{{ contributor.avatar }}\" alt=\"{{ contributor.name }}\">\n <span>{{ contributor.name }}</span>\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n\n <!-- \u8d5e\u52a9\u5546\u533a\u57df -->\n {% if page.meta.sponsors %}\n <div class=\"sponsors\">\n <h3>\u8d5e\u52a9\u5546</h3>\n <div class=\"sponsors-grid\">\n {% for sponsor in page.meta.sponsors %}\n <a href=\"{{ sponsor.url }}\" class=\"sponsor-card\">\n <img src=\"{{ sponsor.logo }}\" alt=\"{{ sponsor.name }}\">\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n</section>\n{% endif %}\n
/* docs/stylesheets/custom-content.css */\n\n/* \u516c\u544a\u533a\u57df */\n.announcements {\n margin: 2rem 0;\n}\n\n.announcement-item {\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n margin-bottom: 1rem;\n}\n\n.announcement-tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n background: var(--md-accent-fg-color);\n color: white;\n border-radius: 2rem;\n font-size: 0.8rem;\n margin-right: 0.5rem;\n}\n\n/* \u8d21\u732e\u8005\u533a\u57df */\n.contributors-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 1rem;\n margin: 1rem 0;\n}\n\n.contributor-card {\n text-align: center;\n text-decoration: none;\n color: var(--md-default-fg-color);\n}\n\n.contributor-card img {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n margin-bottom: 0.5rem;\n}\n\n/* \u8d5e\u52a9\u5546\u533a\u57df */\n.sponsors-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 2rem;\n margin: 1rem 0;\n}\n\n.sponsor-card img {\n width: 100%;\n height: auto;\n filter: grayscale(100%);\n transition: filter 0.3s ease;\n}\n\n.sponsor-card:hover img {\n filter: grayscale(0%);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#712","title":"7.1.2 \u6587\u7ae0\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7121","title":"7.1.2.1 \u6587\u7ae0\u5934\u90e8","text":"HTML<!-- docs/overrides/partials/article-header.html -->\n<header class=\"article-header\">\n <!-- \u6587\u7ae0\u6807\u9898 -->\n <h1>{{ page.title }}</h1>\n\n <!-- \u6587\u7ae0\u5143\u4fe1\u606f -->\n <div class=\"article-meta\">\n {% if page.meta.author %}\n <div class=\"meta-item\">\n <span class=\"meta-icon\">\n {% include \".icons/material/account.svg\" %}\n </span>\n <span>{{ page.meta.author }}</span>\n </div>\n {% endif %}\n\n {% if page.meta.date %}\n <div class=\"meta-item\">\n <span class=\"meta-icon\">\n {% include \".icons/material/calendar.svg\" %}\n </span>\n <span>{{ page.meta.date }}</span>\n </div>\n {% endif %}\n\n {% if page.meta.tags %}\n <div class=\"article-tags\">\n {% for tag in page.meta.tags %}\n <a href=\"{{ base_url }}/tags/#{{ tag }}\" class=\"tag\">\n # {{ tag }}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n </div>\n\n <!-- \u6587\u7ae0\u6982\u8ff0 -->\n {% if page.meta.description %}\n <div class=\"article-description\">\n {{ page.meta.description }}\n </div>\n {% endif %}\n</header>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7122","title":"7.1.2.2 \u6b63\u6587\u6837\u5f0f","text":"CSS/* docs/stylesheets/article.css */\n\n/* \u6587\u7ae0\u5bb9\u5668 */\n.md-content article {\n max-width: 800px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n/* \u6587\u7ae0\u5934\u90e8 */\n.article-header {\n margin-bottom: 3rem;\n text-align: center;\n}\n\n.article-meta {\n display: flex;\n justify-content: center;\n gap: 1rem;\n margin: 1rem 0;\n color: var(--md-default-fg-color--light);\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.article-tags {\n margin-top: 1rem;\n}\n\n.tag {\n display: inline-block;\n padding: 0.2rem 0.5rem;\n margin: 0.2rem;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n font-size: 0.8rem;\n}\n\n/* \u6587\u7ae0\u5185\u5bb9\u6837\u5f0f */\n.md-content article {\n font-size: 1.1rem;\n line-height: 1.8;\n}\n\n/* \u6807\u9898\u6837\u5f0f */\n.md-content article h2 {\n margin-top: 3rem;\n padding-bottom: 0.5rem;\n border-bottom: 2px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u4ee3\u7801\u5757\u6837\u5f0f */\n.md-content pre {\n border-radius: 8px;\n margin: 1.5rem 0;\n}\n\n/* \u5f15\u7528\u6837\u5f0f */\n.md-content blockquote {\n border-left: 4px solid var(--md-accent-fg-color);\n padding: 1rem;\n background: var(--md-code-bg-color);\n margin: 1.5rem 0;\n}\n\n/* \u56fe\u7247\u6837\u5f0f */\n.md-content img {\n max-width: 100%;\n border-radius: 8px;\n margin: 1.5rem 0;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7123","title":"7.1.2.3 \u5e95\u90e8\u4fe1\u606f","text":"HTML<!-- docs/overrides/partials/article-footer.html -->\n<footer class=\"article-footer\">\n <!-- \u6587\u7ae0\u5bfc\u822a -->\n <nav class=\"article-nav\">\n {% if page.previous_page %}\n <a href=\"{{ page.previous_page.url | url }}\" class=\"nav-link nav-prev\">\n <span class=\"nav-icon\">\n {% include \".icons/material/arrow-left.svg\" %}\n </span>\n <span class=\"nav-text\">\n <span class=\"nav-direction\">\u4e0a\u4e00\u7bc7</span>\n <span class=\"nav-title\">{{ page.previous_page.title }}</span>\n </span>\n </a>\n {% endif %}\n\n {% if page.next_page %}\n <a href=\"{{ page.next_page.url | url }}\" class=\"nav-link nav-next\">\n <span class=\"nav-text\">\n <span class=\"nav-direction\">\u4e0b\u4e00\u7bc7</span>\n <span class=\"nav-title\">{{ page.next_page.title }}</span>\n </span>\n <span class=\"nav-icon\">\n {% include \".icons/material/arrow-right.svg\" %}\n </span>\n </a>\n {% endif %}\n </nav>\n\n <!-- \u5206\u4eab\u6309\u94ae -->\n <div class=\"article-share\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n <button class=\"share-button\" data-platform=\"twitter\">\n {% include \".icons/material/twitter.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"facebook\">\n {% include \".icons/material/facebook.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"linkedin\">\n {% include \".icons/material/linkedin.svg\" %}\n </button>\n <button class=\"share-button\" data-platform=\"weibo\">\n {% include \".icons/material/sina-weibo.svg\" %}\n </button>\n </div>\n </div>\n\n <!-- \u76f8\u5173\u6587\u7ae0 -->\n {% if page.meta.related_posts %}\n <div class=\"related-posts\">\n <h4>\u76f8\u5173\u6587\u7ae0</h4>\n <div class=\"related-grid\">\n {% for post in page.meta.related_posts %}\n <a href=\"{{ post.url | url }}\" class=\"related-post\">\n {% if post.image %}\n <img src=\"{{ post.image }}\" alt=\"{{ post.title }}\">\n {% endif %}\n <h5>{{ post.title }}</h5>\n <p>{{ post.excerpt }}</p>\n </a>\n {% endfor %}\n </div>\n </div>\n {% endif %}\n\n <!-- \u8bc4\u8bba\u533a -->\n <div class=\"article-comments\">\n <h4>\u8bc4\u8bba</h4>\n {% if config.extra.comments.provider == 'giscus' %}\n <script src=\"https://giscus.app/client.js\"\n data-repo=\"{{ config.extra.comments.repo }}\"\n data-repo-id=\"{{ config.extra.comments.repo_id }}\"\n data-category=\"{{ config.extra.comments.category }}\"\n data-category-id=\"{{ config.extra.comments.category_id }}\"\n data-mapping=\"pathname\"\n data-reactions-enabled=\"1\"\n data-emit-metadata=\"0\"\n data-theme=\"light\"\n crossorigin=\"anonymous\"\n async>\n </script>\n {% endif %}\n </div>\n</footer>\n\n<!-- \u6587\u7ae0\u5e95\u90e8\u6837\u5f0f -->\n<style>\n.article-footer {\n margin-top: 4rem;\n padding-top: 2rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n/* \u6587\u7ae0\u5bfc\u822a */\n.article-nav {\n display: flex;\n justify-content: space-between;\n margin-bottom: 2rem;\n}\n\n.nav-link {\n display: flex;\n align-items: center;\n padding: 1rem;\n text-decoration: none;\n color: var(--md-default-fg-color);\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n max-width: 45%;\n}\n\n.nav-link:hover {\n transform: translateY(-2px);\n}\n\n.nav-text {\n display: flex;\n flex-direction: column;\n}\n\n.nav-direction {\n font-size: 0.8rem;\n color: var(--md-default-fg-color--light);\n}\n\n.nav-title {\n font-weight: 500;\n}\n\n/* \u5206\u4eab\u6309\u94ae */\n.share-buttons {\n display: flex;\n gap: 1rem;\n margin: 1rem 0;\n}\n\n.share-button {\n padding: 0.8rem;\n border: none;\n border-radius: 50%;\n background: var(--md-code-bg-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n\n/* \u76f8\u5173\u6587\u7ae0 */\n.related-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin: 1rem 0;\n}\n\n.related-post {\n text-decoration: none;\n color: var(--md-default-fg-color);\n background: var(--md-code-bg-color);\n border-radius: 8px;\n overflow: hidden;\n transition: transform 0.2s ease;\n}\n\n.related-post:hover {\n transform: translateY(-4px);\n}\n\n.related-post img {\n width: 100%;\n height: 150px;\n object-fit: cover;\n}\n\n.related-post h5 {\n margin: 1rem;\n font-size: 1.1rem;\n}\n\n.related-post p {\n margin: 0 1rem 1rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u8bc4\u8bba\u533a */\n.article-comments {\n margin-top: 3rem;\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .article-nav {\n flex-direction: column;\n gap: 1rem;\n }\n\n .nav-link {\n max-width: 100%;\n }\n\n .related-grid {\n grid-template-columns: 1fr;\n }\n}\n</style>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#713-404","title":"7.1.3 404\u9875\u9762","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7131","title":"7.1.3.1 \u9519\u8bef\u63d0\u793a","text":"HTML<!-- docs/overrides/404.html -->\n{% extends \"base.html\" %}\n\n{% block content %}\n<div class=\"error-page\">\n <div class=\"error-content\">\n <!-- 404 \u56fe\u6807 -->\n <div class=\"error-icon\">\n {% include \".icons/material/alert-circle-outline.svg\" %}\n <span class=\"error-code\">404</span>\n </div>\n\n <!-- \u9519\u8bef\u4fe1\u606f -->\n <h1>\u9875\u9762\u672a\u627e\u5230</h1>\n <p>\u62b1\u6b49\uff0c\u60a8\u8bbf\u95ee\u7684\u9875\u9762\u4e0d\u5b58\u5728\u6216\u5df2\u88ab\u79fb\u52a8</p>\n\n <!-- \u641c\u7d22\u6846 -->\n <div class=\"error-search\">\n <input type=\"text\" \n id=\"error-search-input\" \n placeholder=\"\u5c1d\u8bd5\u641c\u7d22...\"\n autocomplete=\"off\">\n <button id=\"error-search-button\">\n {% include \".icons/material/magnify.svg\" %}\n </button>\n </div>\n\n <!-- \u5feb\u6377\u64cd\u4f5c -->\n <div class=\"error-actions\">\n <a href=\"{{ base_url }}\" class=\"md-button md-button--primary\">\n \u8fd4\u56de\u9996\u9875\n </a>\n <button class=\"md-button\" onclick=\"window.history.back()\">\n \u8fd4\u56de\u4e0a\u9875\n </button>\n </div>\n </div>\n\n <!-- \u641c\u7d22\u5efa\u8bae -->\n <div class=\"search-suggestions\" id=\"search-suggestions\">\n <h3>\u60a8\u662f\u5426\u5728\u627e\uff1a</h3>\n <div class=\"suggestions-list\" id=\"suggestions-list\">\n <!-- \u52a8\u6001\u751f\u6210\u7684\u5efa\u8bae\u5217\u8868 -->\n </div>\n </div>\n</div>\n\n<!-- 404\u9875\u9762\u6837\u5f0f -->\n<style>\n.error-page {\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n text-align: center;\n}\n\n.error-content {\n max-width: 600px;\n}\n\n.error-icon {\n font-size: 6rem;\n color: var(--md-primary-fg-color);\n margin-bottom: 2rem;\n position: relative;\n}\n\n.error-code {\n position: absolute;\n bottom: -1rem;\n right: -1rem;\n font-size: 2rem;\n font-weight: bold;\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0.5rem 1rem;\n border-radius: 1rem;\n}\n\n.error-search {\n margin: 2rem 0;\n position: relative;\n}\n\n.error-search input {\n width: 100%;\n padding: 1rem 3rem 1rem 1rem;\n border: 2px solid var(--md-default-fg-color--lightest);\n border-radius: 2rem;\n font-size: 1.1rem;\n}\n\n.error-search button {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: var(--md-default-fg-color);\n cursor: pointer;\n}\n\n.error-actions {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin: 2rem 0;\n}\n\n/* \u641c\u7d22\u5efa\u8bae\u6837\u5f0f */\n.search-suggestions {\n margin-top: 3rem;\n width: 100%;\n max-width: 600px;\n}\n\n.suggestions-list {\n margin-top: 1rem;\n}\n\n.suggestion-item {\n padding: 1rem;\n margin: 0.5rem 0;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.suggestion-item:hover {\n background: var(--md-accent-fg-color--transparent);\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .error-icon {\n font-size: 4rem;\n }\n\n .error-code {\n font-size: 1.5rem;\n }\n\n .error-actions {\n flex-direction: column;\n }\n}\n</style>\n\n<!-- 404\u9875\u9762\u811a\u672c -->\n<script>\ndocument.addEventListener('DOMContentLoaded', function() {\n // \u641c\u7d22\u5efa\u8bae\u529f\u80fd\n setupSearchSuggestions();\n // \u5168\u5c40\u70ed\u952e\n setupHotkeys();\n});\n\nfunction setupSearchSuggestions() {\n const searchInput = document.getElementById('error-search-input');\n const suggestionsList = document.getElementById('suggestions-list');\n\n searchInput?.addEventListener('input', debounce(async (e) => {\n const query = e.target.value;\n if (query.length < 2) {\n suggestionsList.innerHTML = '';\n return;\n }\n\n // \u83b7\u53d6\u641c\u7d22\u5efa\u8bae\n const suggestions = await getSearchSuggestions(query);\n\n // \u6e32\u67d3\u5efa\u8bae\u5217\u8868\n suggestionsList.innerHTML = suggestions\n .map(suggestion => `\n <div class=\"suggestion-item\" onclick=\"window.location.href='${suggestion.url}'\">\n <div class=\"suggestion-title\">${suggestion.title}</div>\n <div class=\"suggestion-excerpt\">${suggestion.excerpt}</div>\n </div>\n `)\n .join('');\n }, 300));\n}\n\nasync function getSearchSuggestions(query) {\n // \u8fd9\u91cc\u53ef\u4ee5\u5b9e\u73b0\u5b9e\u9645\u7684\u641c\u7d22\u903b\u8f91\n // \u793a\u4f8b\u8fd4\u56de\u6570\u636e\n return [\n {\n title: '\u76f8\u5173\u6587\u6863 1',\n excerpt: '\u8fd9\u662f\u4e00\u6bb5\u76f8\u5173\u7684\u6587\u6863\u63cf\u8ff0...',\n url: '#'\n },\n {\n title: '\u76f8\u5173\u6587\u6863 2',\n excerpt: '\u8fd9\u662f\u53e6\u4e00\u6bb5\u76f8\u5173\u7684\u6587\u6863\u63cf\u8ff0...',\n url: '#'\n }\n ];\n}\n\nfunction setupHotkeys() {\n document.addEventListener('keydown', (e) => {\n // \u6309 ESC \u8fd4\u56de\u4e0a\u9875\n if (e.key === 'Escape') {\n window.history.back();\n }\n\n // \u6309 Enter \u6267\u884c\u641c\u7d22\n if (e.key === 'Enter' && document.activeElement.id === 'error-search-input') {\n const query = document.activeElement.value;\n if (query) {\n window.location.href = `${window.location.origin}/search.html?q=${encodeURIComponent(query)}`;\n }\n }\n });\n}\n\n// \u9632\u6296\u51fd\u6570\nfunction debounce(fn, delay) {\n let timer = null;\n return function(...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n</script>\n
\u8fd9\u6837\uff0c\u6211\u4eec\u5c31\u5b8c\u6210\u4e86\u6587\u7ae0\u5e95\u90e8\u4fe1\u606f\u548c404\u9875\u9762\u7684\u6a21\u677f\u3002\u4e3b\u8981\u7279\u70b9\u5305\u62ec\uff1a
\u6587\u7ae0\u5e95\u90e8\uff1a - \u6e05\u6670\u7684\u4e0a\u4e0b\u6587\u7ae0\u5bfc\u822a - \u793e\u4ea4\u5206\u4eab\u6309\u94ae - \u76f8\u5173\u6587\u7ae0\u63a8\u8350 - \u96c6\u6210\u8bc4\u8bba\u7cfb\u7edf
404\u9875\u9762\uff1a - \u53cb\u597d\u7684\u9519\u8bef\u63d0\u793a - \u5b9e\u65f6\u641c\u7d22\u5efa\u8bae - \u591a\u79cd\u8fd4\u56de\u9009\u9879 - \u952e\u76d8\u5feb\u6377\u952e\u652f\u6301
\u4f7f\u7528\u8fd9\u4e9b\u6a21\u677f\u65f6\uff0c\u9700\u8981\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n custom_dir: docs/overrides\n features:\n - navigation.tracking\n - search.suggest\n - search.highlight\n\nextra:\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your-repo-id\n category: Comments\n category_id: your-category-id\n
"},{"location":"Tools/Blog/Mkdocs_Material/#72","title":"7.2 \u4fee\u6539\u7ec4\u4ef6\u6a21\u677f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#721","title":"7.2.1 \u5bfc\u822a\u680f","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7211","title":"7.2.1.1 \u5bfc\u822a\u9879\u5b9a\u5236","text":"HTML<!-- docs/overrides/partials/nav.html -->\n{% extends \"base.html\" %}\n\n{% block site_nav %}\n<nav class=\"md-nav md-nav--primary\">\n <!-- \u81ea\u5b9a\u4e49\u5bfc\u822a\u5934\u90e8 -->\n <div class=\"nav-header\">\n {% if config.theme.logo %}\n <img src=\"{{ config.theme.logo }}\" alt=\"logo\" class=\"nav-logo\">\n {% endif %}\n <span class=\"nav-title\">{{ config.site_name }}</span>\n </div>\n\n <!-- \u81ea\u5b9a\u4e49\u5bfc\u822a\u9879 -->\n <ul class=\"nav-items\">\n {% for nav_item in nav %}\n {% include \"partials/nav-item.html\" %}\n {% endfor %}\n\n <!-- \u6dfb\u52a0\u81ea\u5b9a\u4e49\u5bfc\u822a\u9879 -->\n {% if config.extra.nav_links %}\n {% for link in config.extra.nav_links %}\n <li class=\"nav-item custom\">\n <a href=\"{{ link.url }}\" class=\"nav-link\" {% if link.target %}target=\"{{ link.target }}\"{% endif %}>\n {% if link.icon %}\n <span class=\"nav-icon\">\n {% include \".icons/\" ~ link.icon ~ \".svg\" %}\n </span>\n {% endif %}\n {{ link.title }}\n </a>\n </li>\n {% endfor %}\n {% endif %}\n </ul>\n</nav>\n
\u914d\u7f6e\u548c\u6837\u5f0f\uff1a
YAML# mkdocs.yml\nextra:\n nav_links:\n - title: GitHub\n url: https://github.com/your/repo\n icon: material/github\n target: _blank\n - title: \u6587\u6863\n url: /docs/\n icon: material/file-document\n
CSS/* docs/stylesheets/nav.css */\n.nav-header {\n display: flex;\n align-items: center;\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.nav-logo {\n width: 32px;\n height: 32px;\n margin-right: 0.8rem;\n}\n\n.nav-items {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.nav-item {\n margin: 0.2rem 0;\n}\n\n.nav-link {\n display: flex;\n align-items: center;\n padding: 0.8rem 1rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: background-color 0.2s ease;\n}\n\n.nav-link:hover {\n background-color: var(--md-code-bg-color);\n}\n\n.nav-icon {\n margin-right: 0.8rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n/* \u81ea\u5b9a\u4e49\u5bfc\u822a\u9879\u6837\u5f0f */\n.nav-item.custom .nav-link {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7212","title":"7.2.1.2 \u641c\u7d22\u6846\u4f4d\u7f6e","text":"HTML<!-- docs/overrides/partials/search.html -->\n{% block search_box %}\n<div class=\"md-search\" data-md-component=\"search\" role=\"dialog\">\n <label class=\"md-search__overlay\" for=\"__search\"></label>\n <div class=\"md-search__inner\" role=\"search\">\n <!-- \u641c\u7d22\u8f93\u5165\u6846 -->\n <form class=\"md-search__form\">\n <input\n type=\"text\"\n class=\"md-search__input\"\n name=\"query\"\n aria-label=\"\u641c\u7d22\"\n placeholder=\"\u641c\u7d22\u6587\u6863...\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n data-md-component=\"search-query\"\n >\n <!-- \u641c\u7d22\u5feb\u6377\u952e\u63d0\u793a -->\n <div class=\"md-search__shortcuts\">\n <kbd>Ctrl</kbd> + <kbd>K</kbd>\n </div>\n </form>\n\n <!-- \u641c\u7d22\u7ed3\u679c -->\n <div class=\"md-search__output\">\n <div class=\"md-search__scrollwrap\" data-md-scrollfix>\n <div class=\"md-search-result\" data-md-component=\"search-result\">\n <div class=\"md-search-result__meta\">\n \u6b63\u5728\u641c\u7d22...\n </div>\n <ol class=\"md-search-result__list\"></ol>\n </div>\n </div>\n </div>\n </div>\n</div>\n
\u6837\u5f0f\u5b9a\u5236\uff1a
CSS/* docs/stylesheets/search.css */\n/* \u641c\u7d22\u6846\u5bb9\u5668 */\n.md-search {\n margin: 0 1rem;\n padding: 0;\n position: relative;\n}\n\n/* \u641c\u7d22\u8f93\u5165\u6846 */\n.md-search__input {\n width: 100%;\n height: 2.4rem;\n padding: 0 2.4rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color);\n background-color: var(--md-default-bg-color);\n border: 1px solid var(--md-default-fg-color--lightest);\n border-radius: 1.2rem;\n}\n\n/* \u641c\u7d22\u56fe\u6807 */\n.md-search__icon {\n position: absolute;\n left: 0.8rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--md-default-fg-color--light);\n}\n\n/* \u5feb\u6377\u952e\u63d0\u793a */\n.md-search__shortcuts {\n position: absolute;\n right: 0.8rem;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n gap: 0.2rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u641c\u7d22\u7ed3\u679c\u5bb9\u5668 */\n.md-search__output {\n position: absolute;\n top: 100%;\n width: 100%;\n margin-top: 0.4rem;\n background-color: var(--md-default-bg-color);\n border-radius: 0.2rem;\n box-shadow: var(--md-shadow-z2);\n overflow: auto;\n z-index: 1;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7213","title":"7.2.1.3 \u79fb\u52a8\u7aef\u9002\u914d","text":"CSS/* \u79fb\u52a8\u7aef\u5bfc\u822a\u6837\u5f0f */\n@media screen and (max-width: 76.1875em) {\n /* \u5bfc\u822a\u5207\u6362\u6309\u94ae */\n .md-header-nav__button.md-icon {\n padding: 0.4rem;\n margin: 0.4rem;\n }\n\n /* \u5bfc\u822a\u62bd\u5c49 */\n .md-nav--primary {\n position: fixed;\n top: 0;\n left: -18rem;\n width: 18rem;\n height: 100%;\n background-color: var(--md-default-bg-color);\n transition: left 0.25s;\n z-index: 2;\n }\n\n /* \u5bfc\u822a\u62bd\u5c49\u6253\u5f00\u72b6\u6001 */\n .md-nav--primary.md-nav--opened {\n left: 0;\n }\n\n /* \u641c\u7d22\u6846\u5168\u5c4f */\n .md-search__inner {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 1rem;\n background-color: var(--md-default-bg-color);\n z-index: 3;\n }\n\n /* \u641c\u7d22\u7ed3\u679c\u5168\u5c4f */\n .md-search__output {\n position: fixed;\n top: 4rem;\n height: calc(100% - 4rem);\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) and (max-width: 96.25em) {\n .md-nav--primary {\n width: 16rem;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#722","title":"7.2.2 \u9875\u811a","text":"HTML<!-- docs/overrides/partials/footer.html -->\n<footer class=\"md-footer\">\n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <!-- \u7248\u6743\u4fe1\u606f -->\n <div class=\"md-footer-copyright\">\n {% if config.copyright %}\n <div class=\"md-footer-copyright__highlight\">\n {{ config.copyright }}\n </div>\n {% endif %}\n\n <!-- \u6784\u5efa\u4fe1\u606f -->\n <div class=\"md-footer-build\">\n Documentation built with\n <a href=\"https://www.mkdocs.org\" target=\"_blank\" rel=\"noopener\">\n MkDocs\n </a>\n and\n <a href=\"https://squidfunk.github.io/mkdocs-material/\" target=\"_blank\" rel=\"noopener\">\n Material for MkDocs\n </a>\n </div>\n </div>\n\n <!-- \u793e\u4ea4\u94fe\u63a5 -->\n {% if config.extra.social %}\n <div class=\"md-footer-social\">\n {% for social in config.extra.social %}\n <a href=\"{{ social.link }}\" \n target=\"_blank\" \n rel=\"noopener\" \n title=\"{{ social.name }}\"\n class=\"md-footer-social__link\">\n {% include \".icons/\" ~ social.icon ~ \".svg\" %}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n\n <!-- \u5907\u6848\u4fe1\u606f -->\n {% if config.extra.icp %}\n <div class=\"md-footer-icp\">\n <a href=\"https://beian.miit.gov.cn/\" target=\"_blank\" rel=\"noopener\">\n {{ config.extra.icp }}\n </a>\n </div>\n {% endif %}\n </div>\n </div>\n</footer>\n
\u914d\u7f6e\uff1a
YAML# mkdocs.yml\ncopyright: Copyright © 2024 Your Name\nextra:\n social:\n - icon: material/github\n name: GitHub\n link: https://github.com/your-username\n - icon: material/twitter\n name: Twitter\n link: https://twitter.com/your-username\n icp: \u4eacICP\u5907xxxxxxxx\u53f7\n
\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/footer.css */\n.md-footer {\n background-color: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n padding: 2rem 0;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.md-footer-meta__inner {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n}\n\n/* \u7248\u6743\u4fe1\u606f */\n.md-footer-copyright {\n font-size: 0.8rem;\n}\n\n.md-footer-copyright__highlight {\n margin-bottom: 0.5rem;\n}\n\n.md-footer-build {\n color: var(--md-default-fg-color--light);\n}\n\n/* \u793e\u4ea4\u94fe\u63a5 */\n.md-footer-social {\n display: flex;\n gap: 1rem;\n}\n\n.md-footer-social__link {\n width: 2rem;\n height: 2rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--md-default-fg-color);\n border-radius: 50%;\n transition: all 0.2s ease;\n}\n\n.md-footer-social__link:hover {\n background-color: var(--md-code-bg-color);\n color: var(--md-accent-fg-color);\n}\n\n/* \u5907\u6848\u4fe1\u606f */\n.md-footer-icp {\n width: 100%;\n text-align: center;\n margin-top: 1rem;\n font-size: 0.8rem;\n}\n\n.md-footer-icp a {\n color: var(--md-default-fg-color--light);\n text-decoration: none;\n}\n\n/* \u54cd\u5e94\u5f0f\u9002\u914d */\n@media screen and (max-width: 76.1875em) {\n .md-footer-meta__inner {\n flex-direction: column;\n text-align: center;\n }\n\n .md-footer-social {\n justify-content: center;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#723","title":"7.2.3 \u641c\u7d22\u6846","text":"HTML<!-- docs/overrides/partials/search-modal.html -->\n<div class=\"md-search-modal\" data-md-component=\"search-modal\">\n <div class=\"md-search-modal__overlay\" data-md-component=\"search-modal-overlay\"></div>\n\n <div class=\"md-search-modal__inner\">\n <!-- \u641c\u7d22\u5934\u90e8 -->\n <header class=\"md-search-modal__header\">\n <form class=\"md-search-modal__form\">\n <input\n type=\"text\"\n class=\"md-search-modal__input\"\n name=\"query\"\n placeholder=\"\u641c\u7d22\u6587\u6863...\"\n data-md-component=\"search-query\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n >\n <!-- \u5feb\u6377\u952e\u63d0\u793a -->\n <div class=\"md-search-modal__shortcuts\">\n <kbd>\u2191</kbd><kbd>\u2193</kbd> \u9009\u62e9\n <kbd>\u21b5</kbd> \u6253\u5f00\n <kbd>ESC</kbd> \u5173\u95ed\n </div>\n </form>\n </header>\n\n <!-- \u641c\u7d22\u7ed3\u679c -->\n <main class=\"md-search-modal__body\">\n <div class=\"md-search-modal__scrollwrap\">\n <div class=\"md-search-modal__meta\">\n \u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22\n </div>\n\n <div class=\"md-search-modal__results\">\n <!-- \u641c\u7d22\u7ed3\u679c\u5217\u8868 -->\n <div class=\"md-search-modal__list\"></div>\n\n <!-- \u641c\u7d22\u5efa\u8bae -->\n <div class=\"md-search-modal__suggestions\">\n <h3>\u60a8\u53ef\u80fd\u611f\u5174\u8da3\uff1a</h3>\n <div class=\"suggestions-list\">\n <!-- \u52a8\u6001\u751f\u6210\u7684\u5efa\u8bae\u5217\u8868 -->\n </div>\n </div>\n </div>\n </div>\n </main>\n </div>\n</div>\n
\u641c\u7d22\u529f\u80fd\u811a\u672c\uff1a
JavaScript// docs/javascripts/search.js\nclass SearchModal {\n constructor() {\n this.modal = document.querySelector('.md-search-modal');\n this.overlay = document.querySelector('.md-search-modal__overlay');\n this.input = document.querySelector('.md-search-modal__input');\n this.resultsList = document.querySelector('.md-search-modal__list');\n this.suggestions = document.querySelector('.md-search-modal__suggestions');\n\n this.searchIndex = null;\n this.searchResults = [];\n this.currentFocus = -1;\n\n this.init();\n }\n\n init() {\n // \u521d\u59cb\u5316\u641c\u7d22\u7d22\u5f15\n this.buildSearchIndex();\n // \u7ed1\u5b9a\u4e8b\u4ef6\n this.bindEvents();\n // \u8bbe\u7f6e\u5feb\u6377\u952e\n this.setupShortcuts();\n }\n\n async buildSearchIndex() {\n // \u6784\u5efa\u641c\u7d22\u7d22\u5f15\n const response = await fetch('/search/search_index.json');\n const data = await response.json();\n\n // \u4f7f\u7528 lunr.js \u6784\u5efa\u7d22\u5f15\n this.searchIndex = lunr(function() {\n this.field('title', { boost: 10 });\n this.field('text');\n this.ref('location');\n\n data.docs.forEach(function(doc) {\n this.add(doc);\n }, this);\n });\n }\n\n bindEvents() {\n // \u641c\u7d22\u6846\u8f93\u5165\u4e8b\u4ef6\n this.input.addEventListener('input', debounce(() => {\n const query = this.input.value;\n if (query.length >= 2) {\n this.performSearch(query);\n } else {\n this.clearResults();\n }\n }, 200));\n\n // \u641c\u7d22\u7ed3\u679c\u5bfc\u822a\n this.input.addEventListener('keydown', (e) => {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault();\n this.navigateResults('up');\n break;\n case 'ArrowDown':\n e.preventDefault();\n this.navigateResults('down');\n break;\n case 'Enter':\n e.preventDefault();\n this.openResult();\n break;\n case 'Escape':\n e.preventDefault();\n this.closeModal();\n break;\n }\n });\n\n // \u70b9\u51fb\u906e\u7f69\u5173\u95ed\n this.overlay.addEventListener('click', () => this.closeModal());\n }\n\n setupShortcuts() {\n // \u5168\u5c40\u641c\u7d22\u5feb\u6377\u952e\n document.addEventListener('keydown', (e) => {\n // Ctrl/Cmd + K \u6253\u5f00\u641c\u7d22\n if ((e.ctrlKey || e.metaKey) && e.key === 'k') {\n e.preventDefault();\n this.openModal();\n }\n });\n }\n\n async performSearch(query) {\n if (!this.searchIndex) return;\n\n // \u6267\u884c\u641c\u7d22\n this.searchResults = this.searchIndex.search(query).map(result => {\n return {\n ref: result.ref,\n score: result.score,\n ...this.getDocumentByRef(result.ref)\n };\n });\n\n // \u6e32\u67d3\u7ed3\u679c\n this.renderResults();\n // \u66f4\u65b0\u5efa\u8bae\n this.updateSuggestions(query);\n }\n\n renderResults() {\n this.resultsList.innerHTML = this.searchResults\n .map((result, index) => `\n <div class=\"search-result-item ${index === this.currentFocus ? 'focused' : ''}\"\n data-index=\"${index}\">\n <div class=\"result-title\">${this.highlightText(result.title)}</div>\n <div class=\"result-excerpt\">${this.highlightText(result.excerpt)}</div>\n <div class=\"result-location\">${result.location}</div>\n </div>\n `)\n .join('');\n }\n\n highlightText(text) {\n const query = this.input.value;\n if (!query) return text;\n\n const regex = new RegExp(`(${query})`, 'gi');\n return text.replace(regex, '<mark>$1</mark>');\n }\n\n updateSuggestions(query) {\n // \u6839\u636e\u641c\u7d22\u5386\u53f2\u548c\u70ed\u95e8\u641c\u7d22\u751f\u6210\u5efa\u8bae\n const suggestions = this.generateSuggestions(query);\n\n this.suggestions.innerHTML = suggestions\n .map(suggestion => `\n <div class=\"suggestion-item\" data-query=\"${suggestion.query}\">\n <span class=\"suggestion-icon\">\n ${suggestion.type === 'history' ? '\u23f1\ufe0f' : '\ud83d\udd25'}\n </span>\n ${suggestion.query}\n </div>\n `)\n .join('');\n }\n\n navigateResults(direction) {\n const maxIndex = this.searchResults.length - 1;\n\n if (direction === 'up') {\n this.currentFocus = this.currentFocus > 0 ? this.currentFocus - 1 : maxIndex;\n } else {\n this.currentFocus = this.currentFocus < maxIndex ? this.currentFocus + 1 : 0;\n }\n\n this.renderResults();\n this.scrollToFocused();\n }\n\n scrollToFocused() {\n const focused = this.resultsList.querySelector('.focused');\n if (focused) {\n focused.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest'\n });\n }\n }\n\n openResult() {\n const result = this.searchResults[this.currentFocus];\n if (result) {\n window.location.href = result.location;\n }\n }\n\n openModal() {\n this.modal.classList.add('active');\n this.input.focus();\n document.body.style.overflow = 'hidden';\n }\n\n closeModal() {\n this.modal.classList.remove('active');\n this.input.value = '';\n this.clearResults();\n document.body.style.overflow = '';\n }\n\n clearResults() {\n this.searchResults = [];\n this.currentFocus = -1;\n this.resultsList.innerHTML = '';\n this.suggestions.innerHTML = '';\n }\n}\n\n// \u521d\u59cb\u5316\u641c\u7d22\u529f\u80fd\ndocument.addEventListener('DOMContentLoaded', () => {\n new SearchModal();\n});\n
\u641c\u7d22\u6846\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search-modal.css */\n.md-search-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1000;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n}\n\n.md-search-modal.active {\n opacity: 1;\n visibility: visible;\n}\n\n.md-search-modal__overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n}\n\n.md-search-modal__inner {\n position: relative;\n width: 90%;\n max-width: 800px;\n margin: 2rem auto;\n background: var(--md-default-bg-color);\n border-radius: 8px;\n box-shadow: var(--md-shadow-z3);\n}\n\n/* \u641c\u7d22\u7ed3\u679c\u6837\u5f0f */\n.search-result-item {\n padding: 1rem;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.search-result-item:hover,\n.search-result-item.focused {\n background: var(--md-code-bg-color);\n}\n\n.result-title {\n font-size: 1.1rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n}\n\n.result-excerpt {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-bottom: 0.5rem;\n}\n\n.result-location {\n font-size: 0.8rem;\n color: var(--md-accent-fg-color);\n}\n\n/* \u9ad8\u4eae\u5339\u914d\u6587\u672c */\nmark {\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0 0.2rem;\n border-radius: 2px;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#724","title":"7.2.4 \u76ee\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#7241","title":"7.2.4.1 \u76ee\u5f55\u7ed3\u6784","text":"HTML<!-- docs/overrides/partials/toc.html -->\n<nav class=\"md-toc\" aria-label=\"\u76ee\u5f55\">\n <div class=\"md-toc__header\">\n <h2 class=\"md-toc__title\">\u76ee\u5f55</h2>\n <button class=\"md-toc__toggle\" aria-label=\"\u5c55\u5f00/\u6536\u8d77\">\n {% include \".icons/material/chevron-down.svg\" %}\n </button>\n </div>\n\n <div class=\"md-toc__inner\">\n {% set toc = page.toc %}\n <ul class=\"md-toc__list\">\n {% for toc_item in toc %}\n {% include \"partials/toc-item.html\" %}\n {% endfor %}\n </ul>\n </div>\n</nav>\n\n<!-- docs/overrides/partials/toc-item.html -->\n<li class=\"md-toc__item\">\n <a href=\"{{ toc_item.url }}\" class=\"md-toc__link\">\n {{ toc_item.title }}\n </a>\n\n {% if toc_item.children %}\n <ul class=\"md-toc__list\">\n {% for toc_item in toc_item.children %}\n {% include \"partials/toc-item.html\" %}\n {% endfor %}\n </ul>\n {% endif %}\n</li>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7242","title":"7.2.4.2 \u6eda\u52a8\u540c\u6b65","text":"JavaScript// docs/javascripts/toc.js\nclass TableOfContents {\n constructor() {\n this.toc = document.querySelector('.md-toc');\n this.tocLinks = this.toc.querySelectorAll('.md-toc__link');\n this.headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');\n this.intersectionObserver = null;\n\n this.init();\n }\n\n init() {\n this.setupIntersectionObserver();\n this.setupScrollSpy();\n this.setupToggle();\n }\n\n setupIntersectionObserver() {\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n const id = entry.target.getAttribute('id');\n this.highlightTocItem(id);\n }\n });\n },\n {\n rootMargin: '0px 0px -80% 0px'\n }\n );\n\n this.headings.forEach(heading => {\n this.intersectionObserver.observe(heading);\n });\n }\n\n setupScrollSpy() {\n this.tocLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const id = link.getAttribute('href').substring(1);\n const target = document.getElementById(id);\n\n if (target) {\n window.scrollTo({\n top: target.offsetTop - 100,\n behavior: 'smooth'\n });\n\n // \u66f4\u65b0 URL\n history.pushState(null, null, `#${id}`);\n }\n });\n });\n }\n\n highlightTocItem(id) {\n // \u79fb\u9664\u6240\u6709\u9ad8\u4eae\n this.tocLinks.forEach(link => {\n link.classList.remove('active');\n });\n\n // \u6dfb\u52a0\u65b0\u9ad8\u4eae\n const activeLink = this.toc.querySelector(`a[href=\"#${id}\"]`);\n if (activeLink) {\n activeLink.classList.add('active');\n this.expandParents(activeLink);\n }\n }\n\n expandParents(element) {\n let parent = element.parentElement;\n while (parent && parent.classList.contains('md-toc__item')) {\n const list = parent.querySelector('.md-toc__list');\n if (list) {\n list.style.height = 'auto';\n parent.classList.add('expanded');\n }\n parent = parent.parentElement;\n }\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#7243","title":"7.2.4.3 \u5c55\u5f00\u6536\u8d77","text":"JavaScriptsetupToggle() {\n const toggleButton = this.toc.querySelector('.md-toc__toggle');\n const tocInner = this.toc.querySelector('.md-toc__inner');\n\n toggleButton?.addEventListener('click', () => {\n const isExpanded = this.toc.classList.contains('expanded');\n\n if (isExpanded) {\n this.toc.classList.remove('expanded');\n tocInner.style.height = '0';\n } else {\n this.toc.classList.add('expanded');\n tocInner.style.height = tocInner.scrollHeight + 'px';\n }\n });\n\n // \u6dfb\u52a0\u5c55\u5f00/\u6536\u8d77\u6240\u6709\u6309\u94ae\n const expandAllButton = document.createElement('button');\n expandAllButton.className = 'md-toc__expand-all';\n expandAllButton.innerHTML = '\u5c55\u5f00\u5168\u90e8';\n expandAllButton.addEventListener('click', () => this.toggleAll(true));\n\n const collapseAllButton = document.createElement('button');\n collapseAllButton.className = 'md-toc__collapse-all';\n collapseAllButton.innerHTML = '\u6536\u8d77\u5168\u90e8';\n collapseAllButton.addEventListener('click', () => this.toggleAll(false));\n\n const buttonGroup = document.createElement('div');\n buttonGroup.className = 'md-toc__button-group';\n buttonGroup.appendChild(expandAllButton);\n buttonGroup.appendChild(collapseAllButton);\n\n this.toc.querySelector('.md-toc__header').appendChild(buttonGroup);\n}\n\ntoggleAll(expand) {\n const lists = this.toc.querySelectorAll('.md-toc__list');\n lists.forEach(list => {\n if (expand) {\n list.style.height = 'auto';\n list.parentElement.classList.add('expanded');\n } else {\n list.style.height = '0';\n list.parentElement.classList.remove('expanded');\n }\n });\n}\n
\u76ee\u5f55\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/toc.css */\n.md-toc {\n position: sticky;\n top: 4rem;\n padding: 1rem;\n max-height: calc(100vh - 4rem);\n overflow-y: auto;\n background: var(--md-default-bg-color);\n border-left: 1px solid var(--md-default-fg-color--lightest);\n font-size: 0.8rem;\n}\n\n/* \u76ee\u5f55\u5934\u90e8 */\n.md-toc__header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n padding-bottom: 0.5rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.md-toc__title {\n font-size: 1rem;\n font-weight: 600;\n margin: 0;\n}\n\n.md-toc__button-group {\n display: flex;\n gap: 0.5rem;\n}\n\n.md-toc__button-group button {\n padding: 0.2rem 0.5rem;\n font-size: 0.7rem;\n color: var(--md-default-fg-color--light);\n background: var(--md-code-bg-color);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.md-toc__button-group button:hover {\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color--light);\n}\n\n/* \u76ee\u5f55\u5217\u8868 */\n.md-toc__list {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.md-toc__item {\n margin: 0.2rem 0;\n}\n\n/* \u76ee\u5f55\u94fe\u63a5 */\n.md-toc__link {\n display: block;\n padding: 0.2rem 0;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: all 0.2s ease;\n border-radius: 4px;\n}\n\n.md-toc__link:hover {\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color);\n padding-left: 0.5rem;\n}\n\n/* \u5f53\u524d\u6fc0\u6d3b\u9879 */\n.md-toc__link.active {\n color: var(--md-accent-fg-color);\n font-weight: 500;\n background: var(--md-code-bg-color);\n padding-left: 0.5rem;\n}\n\n/* \u5d4c\u5957\u5c42\u7ea7 */\n.md-toc__item .md-toc__list {\n margin-left: 1rem;\n border-left: 1px solid var(--md-default-fg-color--lightest);\n overflow: hidden;\n height: 0;\n transition: height 0.3s ease;\n}\n\n.md-toc__item.expanded > .md-toc__list {\n height: auto;\n}\n\n/* \u6298\u53e0\u6307\u793a\u5668 */\n.md-toc__item > .md-toc__link::before {\n content: '';\n display: inline-block;\n width: 0.8rem;\n height: 0.8rem;\n margin-right: 0.2rem;\n background-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z\"/></svg>');\n background-size: contain;\n transform: rotate(0);\n transition: transform 0.3s ease;\n}\n\n.md-toc__item.expanded > .md-toc__link::before {\n transform: rotate(90deg);\n}\n\n/* \u6eda\u52a8\u6761\u6837\u5f0f */\n.md-toc::-webkit-scrollbar {\n width: 4px;\n}\n\n.md-toc::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.md-toc::-webkit-scrollbar-thumb {\n background: var(--md-default-fg-color--lighter);\n border-radius: 2px;\n}\n\n/* \u54cd\u5e94\u5f0f\u8bbe\u8ba1 */\n@media screen and (max-width: 76.1875em) {\n .md-toc {\n position: fixed;\n top: 0;\n right: -18rem;\n width: 18rem;\n height: 100vh;\n max-height: none;\n margin: 0;\n padding: 1rem;\n background: var(--md-default-bg-color);\n border-left: 1px solid var(--md-default-fg-color--lightest);\n box-shadow: var(--md-shadow-z3);\n transition: right 0.3s ease;\n z-index: 3;\n }\n\n .md-toc.expanded {\n right: 0;\n }\n\n /* \u79fb\u52a8\u7aef\u8986\u76d6\u5c42 */\n .md-toc-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.3);\n z-index: 2;\n }\n\n .md-toc.expanded + .md-toc-overlay {\n display: block;\n }\n}\n\n/* \u5e73\u677f\u9002\u914d */\n@media screen and (min-width: 76.25em) and (max-width: 96.25em) {\n .md-toc {\n padding: 0.8rem;\n }\n\n .md-toc__list {\n margin-left: 0.8rem;\n }\n}\n
\u5b8c\u6574\u7684\u76ee\u5f55\u529f\u80fd\u5b9e\u73b0\uff1a
JavaScript// docs/javascripts/toc.js\nclass TableOfContents {\n constructor() {\n this.toc = document.querySelector('.md-toc');\n this.tocLinks = this.toc.querySelectorAll('.md-toc__link');\n this.headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');\n this.intersectionObserver = null;\n this.isScrolling = false;\n this.scrollTimeout = null;\n\n this.init();\n }\n\n init() {\n this.setupIntersectionObserver();\n this.setupScrollSpy();\n this.setupToggle();\n this.setupMobileToggle();\n this.handleInitialHash();\n }\n\n handleInitialHash() {\n // \u5904\u7406\u9875\u9762\u52a0\u8f7d\u65f6\u7684 hash\n if (window.location.hash) {\n const id = window.location.hash.substring(1);\n const target = document.getElementById(id);\n if (target) {\n setTimeout(() => {\n target.scrollIntoView();\n this.highlightTocItem(id);\n }, 100);\n }\n }\n }\n\n setupMobileToggle() {\n // \u521b\u5efa\u79fb\u52a8\u7aef\u5f00\u5173\u6309\u94ae\n const toggleButton = document.createElement('button');\n toggleButton.className = 'md-toc-toggle';\n toggleButton.innerHTML = `\n <span class=\"md-toc-toggle__icon\">\n {% include \".icons/material/menu.svg\" %}\n </span>\n `;\n\n // \u521b\u5efa\u906e\u7f69\u5c42\n const overlay = document.createElement('div');\n overlay.className = 'md-toc-overlay';\n\n document.body.appendChild(toggleButton);\n document.body.appendChild(overlay);\n\n // \u7ed1\u5b9a\u4e8b\u4ef6\n toggleButton.addEventListener('click', () => {\n this.toc.classList.toggle('expanded');\n document.body.style.overflow = this.toc.classList.contains('expanded') ? 'hidden' : '';\n });\n\n overlay.addEventListener('click', () => {\n this.toc.classList.remove('expanded');\n document.body.style.overflow = '';\n });\n }\n\n updateTocHeight() {\n const lists = this.toc.querySelectorAll('.md-toc__list');\n lists.forEach(list => {\n if (list.parentElement.classList.contains('expanded')) {\n list.style.height = list.scrollHeight + 'px';\n }\n });\n }\n\n onResize() {\n // \u76d1\u542c\u7a97\u53e3\u5927\u5c0f\u53d8\u5316\uff0c\u66f4\u65b0\u76ee\u5f55\u9ad8\u5ea6\n window.addEventListener('resize', debounce(() => {\n this.updateTocHeight();\n }, 100));\n }\n}\n\n// \u5de5\u5177\u51fd\u6570\nfunction debounce(fn, delay) {\n let timer = null;\n return function(...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n// \u521d\u59cb\u5316\u76ee\u5f55\ndocument.addEventListener('DOMContentLoaded', () => {\n new TableOfContents();\n});\n
\u4f7f\u7528\u8fd9\u4e9b\u4ee3\u7801\uff0c\u9700\u8981\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u914d\u7f6e\uff1a
theme:\n name: material\n custom_dir: docs/overrides\n features:\n - toc.integrate\n - toc.follow\n\nextra_css:\n - stylesheets/toc.css\n\nextra_javascript:\n - javascripts/toc.js\n
\u8fd9\u6837\u5c31\u5b8c\u6210\u4e86\u4e00\u4e2a\u529f\u80fd\u5b8c\u6574\u3001\u4ea4\u4e92\u53cb\u597d\u7684\u76ee\u5f55\u5bfc\u822a\u7cfb\u7edf\uff0c\u4e3b\u8981\u7279\u70b9\u5305\u62ec\uff1a
pip install mkdocs-material\n
# mkdocs.yml\nplugins:\n - search:\n # \u641c\u7d22\u7d22\u5f15\u8bbe\u7f6e\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.]+' # \u5206\u8bcd\u5206\u9694\u7b26\n min_search_length: 2 # \u6700\u5c0f\u641c\u7d22\u957f\u5ea6\n prebuild_index: true # \u9884\u6784\u5efa\u7d22\u5f15\n\n # \u641c\u7d22\u5185\u5bb9\u914d\u7f6e\n indexing:\n full_sections: true # \u7d22\u5f15\u5b8c\u6574\u7ae0\u8282\n headings: true # \u7d22\u5f15\u6807\u9898\n content: true # \u7d22\u5f15\u5185\u5bb9\n tags: true # \u7d22\u5f15\u6807\u7b7e\n\n # \u641c\u7d22\u7ed3\u679c\u6392\u5e8f\n scoring:\n title_boost: 10 # \u6807\u9898\u6743\u91cd\n heading_boost: 5 # \u6807\u9898\u6743\u91cd\n content_boost: 1 # \u5185\u5bb9\u6743\u91cd\n
theme:\n features:\n - search.highlight # \u641c\u7d22\u9ad8\u4eae\n - search.share # \u641c\u7d22\u5206\u4eab\n - search.suggest # \u641c\u7d22\u5efa\u8bae\n\n # \u641c\u7d22\u754c\u9762\u6587\u5b57\n language: zh\n palette:\n - search:\n placeholder: \u641c\u7d22\u6587\u6863\n result:\n no_results_text: \u672a\u627e\u5230\u76f8\u5173\u7ed3\u679c\n searching_text: \u6b63\u5728\u641c\u7d22...\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8113","title":"8.1.1.3 \u4e2d\u6587\u641c\u7d22","text":"plugins:\n - search:\n jieba_dict: dict.txt # \u81ea\u5b9a\u4e49\u8bcd\u5178\u8def\u5f84\n jieba_dict_user: user_dict.txt # \u7528\u6237\u8bcd\u5178\u8def\u5f84\n\n # \u4e2d\u6587\u5206\u8bcd\u89c4\u5219\n separator: '[\uff0c\u3002\uff01\uff1f,!?]+'\n\n # \u4e2d\u6587\u505c\u7528\u8bcd\n stopwords:\n - \u7684\n - \u4e86\n - \u548c\n - \u662f\n - \u5c31\n - \u90fd\n - \u800c\n - \u53ca\n - \u4e0e\n - \u8fd9\n
\u6280\u672f\u6587\u6863 5\n\u5f00\u53d1\u6307\u5357 5\n\u6700\u4f73\u5b9e\u8df5 5\n\u4f7f\u7528\u6559\u7a0b 5\n\u914d\u7f6e\u8bf4\u660e 5\n\u5e38\u89c1\u95ee\u9898 5\n
# docs/search_optimize.py\nimport jieba\nimport json\nfrom pathlib import Path\n\ndef optimize_search_index(index_file, dict_file):\n # \u52a0\u8f7d\u81ea\u5b9a\u4e49\u8bcd\u5178\n jieba.load_userdict(dict_file)\n\n # \u8bfb\u53d6\u641c\u7d22\u7d22\u5f15\n with open(index_file, 'r', encoding='utf-8') as f:\n index = json.load(f)\n\n # \u4f18\u5316\u5206\u8bcd\n for doc in index['docs']:\n # \u5206\u8bcd\u5904\u7406\u6807\u9898\n title_words = list(jieba.cut(doc['title']))\n doc['title'] = ' '.join(title_words)\n\n # \u5206\u8bcd\u5904\u7406\u5185\u5bb9\n if 'text' in doc:\n text_words = list(jieba.cut(doc['text']))\n doc['text'] = ' '.join(text_words)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7d22\u5f15\n with open(index_file, 'w', encoding='utf-8') as f:\n json.dump(index, f, ensure_ascii=False, indent=2)\n\nif __name__ == '__main__':\n index_file = 'site/search/search_index.json'\n dict_file = 'docs/dict.txt'\n optimize_search_index(index_file, dict_file)\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8114","title":"8.1.1.4 \u641c\u7d22\u4f18\u5316","text":"# docs/search_index_optimizer.py\nfrom pathlib import Path\nimport json\nimport re\n\nclass SearchIndexOptimizer:\n def __init__(self, index_path):\n self.index_path = Path(index_path)\n self.index = self.load_index()\n\n def load_index(self):\n with open(self.index_path, 'r', encoding='utf-8') as f:\n return json.load(f)\n\n def save_index(self):\n with open(self.index_path, 'w', encoding='utf-8') as f:\n json.dump(self.index, f, ensure_ascii=False, indent=2)\n\n def optimize(self):\n # \u6e05\u7406\u65e0\u7528\u6570\u636e\n self._clean_data()\n # \u4f18\u5316\u6587\u672c\n self._optimize_text()\n # \u6dfb\u52a0\u6743\u91cd\n self._add_weights()\n # \u6784\u5efa\u53cd\u5411\u7d22\u5f15\n self._build_inverted_index()\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u7d22\u5f15\n self.save_index()\n\n def _clean_data(self):\n # \u79fb\u9664\u7a7a\u6587\u6863\n self.index['docs'] = [\n doc for doc in self.index['docs']\n if doc.get('text') or doc.get('title')\n ]\n\n # \u79fb\u9664\u91cd\u590d\u6587\u6863\n seen = set()\n unique_docs = []\n for doc in self.index['docs']:\n key = f\"{doc['location']}:{doc['title']}\"\n if key not in seen:\n seen.add(key)\n unique_docs.append(doc)\n self.index['docs'] = unique_docs\n\n def _optimize_text(self):\n for doc in self.index['docs']:\n # \u6e05\u7406HTML\u6807\u7b7e\n if 'text' in doc:\n doc['text'] = re.sub(r'<[^>]+>', '', doc['text'])\n\n # \u538b\u7f29\u7a7a\u767d\u5b57\u7b26\n for field in ['title', 'text']:\n if field in doc:\n doc[field] = ' '.join(doc[field].split())\n\n def _add_weights(self):\n for doc in self.index['docs']:\n # \u57fa\u7840\u6743\u91cd\n doc['weight'] = 1.0\n\n # \u6807\u9898\u957f\u5ea6\u6743\u91cd\n if 'title' in doc:\n title_len = len(doc['title'])\n doc['weight'] *= 1 + (1.0 / (1 + title_len))\n\n # \u6587\u672c\u957f\u5ea6\u6743\u91cd\n if 'text' in doc:\n text_len = len(doc['text'])\n doc['weight'] *= 1 + (100.0 / (1 + text_len))\n\n # URL\u6df1\u5ea6\u6743\u91cd\n depth = doc['location'].count('/')\n doc['weight'] *= 1 + (1.0 / (1 + depth))\n\n def _build_inverted_index(self):\n # \u6784\u5efa\u53cd\u5411\u7d22\u5f15\n inverted_index = {}\n for i, doc in enumerate(self.index['docs']):\n terms = set()\n\n # \u6dfb\u52a0\u6807\u9898\u8bcd\n if 'title' in doc:\n terms.update(doc['title'].lower().split())\n\n # \u6dfb\u52a0\u6587\u672c\u8bcd\n if 'text' in doc:\n terms.update(doc['text'].lower().split())\n\n # \u66f4\u65b0\u53cd\u5411\u7d22\u5f15\n for term in terms:\n if term not in inverted_index:\n inverted_index[term] = []\n inverted_index[term].append({\n 'id': i,\n 'weight': doc['weight']\n })\n\n self.index['inverted_index'] = inverted_index\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = SearchIndexOptimizer('site/search/search_index.json')\noptimizer.optimize()\n
// docs/javascripts/search-monitor.js\nclass SearchMonitor {\n constructor() {\n this.metrics = {\n searches: 0,\n avgTime: 0,\n slowest: 0,\n fastest: Infinity\n };\n\n this.init();\n }\n\n init() {\n this.monitorSearchInput();\n this.monitorSearchResults();\n this.setupReporting();\n }\n\n monitorSearchInput() {\n const searchInput = document.querySelector('.md-search__input');\n let startTime;\n\n searchInput?.addEventListener('input', () => {\n startTime = performance.now();\n });\n\n searchInput?.addEventListener('search', () => {\n const endTime = performance.now();\n const duration = endTime - startTime;\n\n this.updateMetrics(duration);\n });\n }\n\n updateMetrics(duration) {\n this.metrics.searches++;\n this.metrics.avgTime = (\n (this.metrics.avgTime * (this.metrics.searches - 1) + duration) /\n this.metrics.searches\n );\n this.metrics.slowest = Math.max(this.metrics.slowest, duration);\n this.metrics.fastest = Math.min(this.metrics.fastest, duration);\n\n // \u53d1\u9001\u7edf\u8ba1\u6570\u636e\n this.sendMetrics();\n }\n\n sendMetrics() {\n // \u53ef\u4ee5\u53d1\u9001\u5230\u7edf\u8ba1\u670d\u52a1\n console.log('Search Metrics:', this.metrics);\n }\n}\n\n// \u521d\u59cb\u5316\u76d1\u63a7\nnew SearchMonitor();\n
"},{"location":"Tools/Blog/Mkdocs_Material/#812-glightbox","title":"8.1.2 glightbox","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8121","title":"8.1.2.1 \u56fe\u7247\u9884\u89c8","text":"pip install mkdocs-glightbox\n
# mkdocs.yml\nplugins:\n - glightbox:\n # \u57fa\u7840\u8bbe\u7f6e\n auto_caption: true # \u81ea\u52a8\u6dfb\u52a0\u6807\u9898\n caption_position: bottom # \u6807\u9898\u4f4d\u7f6e\n display_description: true # \u663e\u793a\u63cf\u8ff0\n\n # \u89e6\u6478\u8bbe\u7f6e\n touchNavigation: true # \u89e6\u6478\u5bfc\u822a\n loop: true # \u5faa\u73af\u6d4f\u89c8\n effect: zoom # \u8fc7\u6e21\u6548\u679c\n\n # \u56fe\u7247\u8bbe\u7f6e\n width: 100% # \u56fe\u7247\u5bbd\u5ea6\n height: auto # \u56fe\u7247\u9ad8\u5ea6\n zoomable: true # \u542f\u7528\u7f29\u653e\n draggable: true # \u542f\u7528\u62d6\u52a8\n
/* docs/stylesheets/glightbox.css */\n.glightbox-clean {\n /* \u5bb9\u5668\u6837\u5f0f */\n --glow-padding: 2rem;\n --glow-bg: rgba(0, 0, 0, 0.95);\n\n /* \u63a7\u5236\u6309\u94ae */\n --glow-btn-color: rgba(255, 255, 255, 0.8);\n --glow-btn-hover: #fff;\n\n /* \u52a0\u8f7d\u52a8\u753b */\n --glow-loading-bg: rgba(0, 0, 0, 0.5);\n --glow-loading-width: 40px;\n --glow-loading-height: 40px;\n}\n\n/* \u6807\u9898\u6837\u5f0f */\n.glightbox-caption {\n font-family: var(--md-font-family);\n font-size: 0.9rem;\n padding: 1rem;\n background: rgba(0, 0, 0, 0.8);\n}\n\n/* \u63cf\u8ff0\u6837\u5f0f */\n.glightbox-description {\n font-size: 0.8rem;\n color: rgba(255, 255, 255, 0.7);\n margin-top: 0.5rem;\n}\n\n/* \u52a0\u8f7d\u52a8\u753b */\n.glightbox-loading {\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #fff;\n border-radius: 50%;\n animation: glow-spin 1s linear infinite;\n}\n\n@keyframes glow-spin {\n to { transform: rotate(360deg); }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8122","title":"8.1.2.2 \u753b\u5eca\u6a21\u5f0f","text":"plugins:\n - glightbox:\n # \u753b\u5eca\u8bbe\u7f6e\n gallery: true # \u542f\u7528\u753b\u5eca\n gallery_mode: true # \u753b\u5eca\u6a21\u5f0f\n gallery_trigger: click # \u89e6\u53d1\u65b9\u5f0f\n\n # \u7f29\u7565\u56fe\u8bbe\u7f6e\n thumb_width: 150 # \u7f29\u7565\u56fe\u5bbd\u5ea6\n thumb_height: 100 # \u7f29\u7565\u56fe\u9ad8\u5ea6\n thumb_fit: cover # \u7f29\u7565\u56fe\u9002\u5e94\u65b9\u5f0f\n
<!-- docs/overrides/gallery.html -->\n<div class=\"gallery\">\n {% for image in page.meta.gallery %}\n <a href=\"{{ image.url }}\" \n class=\"gallery-item\"\n data-gallery=\"gallery\"\n data-glightbox=\"title: {{ image.title }}; description: {{ image.description }}\">\n <img src=\"{{ image.thumbnail or image.url }}\" \n alt=\"{{ image.title }}\"\n loading=\"lazy\">\n {% if image.title %}\n <div class=\"gallery-caption\">{{ image.title }}</div>\n {% endif %}\n </a>\n {% endfor %}\n</div>\n
/* docs/stylesheets/gallery.css */\n.gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 1rem;\n padding: 1rem;\n}\n\n.gallery-item {\n position: relative;\n overflow: hidden;\n border-radius: 4px;\n cursor: pointer;\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover {\n transform: translateY(-4px);\n}\n\n.gallery-item img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover img {\n transform: scale(1.1);\n}\n\n.gallery-caption {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 0.5rem;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n font-size: 0.8rem;\n transform: translateY(100%);\n transition: transform 0.3s ease;\n}\n\n.gallery-item:hover .gallery-caption {\n transform: translateY(0);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#82","title":"8.2 \u63a8\u8350\u63d2\u4ef6","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8211-git-revision-date","title":"8.2.1.1 git-revision-date","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8212","title":"8.2.1.2 \u65f6\u95f4\u663e\u793a","text":"pip install mkdocs-git-revision-date-localized-plugin\n
# mkdocs.yml\nplugins:\n - git-revision-date-localized:\n enabled: true\n type: date # \u663e\u793a\u7c7b\u578b\uff1adate, datetime, iso_date, iso_datetime, timeago\n timezone: Asia/Shanghai # \u65f6\u533a\u8bbe\u7f6e\n locale: zh # \u672c\u5730\u5316\u8bed\u8a00\n fallback_to_build_date: true # \u65e0 git \u4fe1\u606f\u65f6\u4f7f\u7528\u6784\u5efa\u65f6\u95f4\n\n # \u65f6\u95f4\u683c\u5f0f\n enable_creation_date: true # \u663e\u793a\u521b\u5efa\u65f6\u95f4\n exclude:\n - index.md\n - 404.md\n
<!-- docs/overrides/partials/date.html -->\n{% if page.meta.git_revision_date_localized %}\n<div class=\"page-date\">\n <!-- \u6700\u540e\u66f4\u65b0\u65f6\u95f4 -->\n <div class=\"date-item\">\n <span class=\"date-icon\">\n {% include \".icons/material/update.svg\" %}\n </span>\n <span class=\"date-text\">\n \u6700\u540e\u66f4\u65b0: {{ page.meta.git_revision_date_localized }}\n </span>\n </div>\n\n <!-- \u521b\u5efa\u65f6\u95f4 -->\n {% if page.meta.git_creation_date_localized %}\n <div class=\"date-item\">\n <span class=\"date-icon\">\n {% include \".icons/material/clock-outline.svg\" %}\n </span>\n <span class=\"date-text\">\n \u521b\u5efa\u65f6\u95f4: {{ page.meta.git_creation_date_localized }}\n </span>\n </div>\n {% endif %}\n</div>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8213","title":"8.2.1.3 \u66f4\u65b0\u8bb0\u5f55","text":"<!-- docs/overrides/partials/revision.html -->\n{% if page.meta.git_revision_date_localized %}\n<div class=\"revision-history\">\n <h3>\u66f4\u65b0\u8bb0\u5f55</h3>\n <div class=\"revision-list\">\n {% for revision in page.meta.git_history %}\n <div class=\"revision-item\">\n <div class=\"revision-date\">\n {{ revision.date }}\n </div>\n <div class=\"revision-message\">\n {{ revision.message }}\n </div>\n </div>\n {% endfor %}\n </div>\n</div>\n
/* docs/stylesheets/revision.css */\n.revision-history {\n margin: 2rem 0;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n}\n\n.revision-item {\n display: flex;\n padding: 0.5rem 0;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.revision-date {\n flex: 0 0 200px;\n color: var(--md-default-fg-color--light);\n}\n\n.revision-message {\n flex: 1;\n}\n\n/* \u65f6\u95f4\u7ebf\u6837\u5f0f */\n.revision-item {\n position: relative;\n padding-left: 2rem;\n}\n\n.revision-item::before {\n content: '';\n position: absolute;\n left: 0;\n top: 1rem;\n width: 12px;\n height: 12px;\n background: var(--md-accent-fg-color);\n border-radius: 50%;\n}\n\n.revision-item::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1.5rem;\n bottom: -0.5rem;\n width: 2px;\n background: var(--md-default-fg-color--lightest);\n}\n\n.revision-item:last-child::after {\n display: none;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8214","title":"8.2.1.4 \u4f5c\u8005\u4fe1\u606f","text":"plugins:\n - git-revision-date-localized:\n enabled: true\n type: date\n enable_authors: true # \u542f\u7528\u4f5c\u8005\u4fe1\u606f\n authors_file: authors.yaml # \u4f5c\u8005\u914d\u7f6e\u6587\u4ef6\n
authors:\n john:\n name: John Doe\n email: john@example.com\n avatar: assets/authors/john.jpg\n bio: \u8d44\u6df1\u6280\u672f\u4f5c\u8005\n social:\n github: johndoe\n twitter: johndoe\n\n jane:\n name: Jane Smith\n email: jane@example.com\n avatar: assets/authors/jane.jpg\n bio: \u524d\u7aef\u5f00\u53d1\u4e13\u5bb6\n social:\n github: janesmith\n linkedin: janesmith\n
<!-- docs/overrides/partials/author.html -->\n{% if page.meta.git_authors %}\n<div class=\"page-authors\">\n {% for author in page.meta.git_authors %}\n <div class=\"author-card\">\n <!-- \u4f5c\u8005\u5934\u50cf -->\n <div class=\"author-avatar\">\n {% if author.avatar %}\n <img src=\"{{ author.avatar }}\" alt=\"{{ author.name }}\">\n {% else %}\n <div class=\"avatar-placeholder\">\n {{ author.name[0] }}\n </div>\n {% endif %}\n </div>\n\n <!-- \u4f5c\u8005\u4fe1\u606f -->\n <div class=\"author-info\">\n <h4 class=\"author-name\">{{ author.name }}</h4>\n {% if author.bio %}\n <p class=\"author-bio\">{{ author.bio }}</p>\n {% endif %}\n\n <!-- \u793e\u4ea4\u94fe\u63a5 -->\n {% if author.social %}\n <div class=\"author-social\">\n {% for platform, username in author.social.items() %}\n <a href=\"https://{{ platform }}.com/{{ username }}\" \n target=\"_blank\"\n class=\"social-link\">\n {% include \".icons/material/\" ~ platform ~ \".svg\" %}\n </a>\n {% endfor %}\n </div>\n {% endif %}\n </div>\n </div>\n {% endfor %}\n</div>\n
/* docs/stylesheets/author.css */\n.page-authors {\n margin: 2rem 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1rem;\n}\n\n.author-card {\n display: flex;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.author-card:hover {\n transform: translateY(-2px);\n}\n\n.author-avatar {\n flex: 0 0 80px;\n margin-right: 1rem;\n}\n\n.author-avatar img {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n object-fit: cover;\n}\n\n.avatar-placeholder {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--md-accent-fg-color);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 2rem;\n}\n\n.author-info {\n flex: 1;\n}\n\n.author-name {\n margin: 0 0 0.5rem;\n font-size: 1.1rem;\n}\n\n.author-bio {\n color: var(--md-default-fg-color--light);\n font-size: 0.9rem;\n margin: 0 0 0.5rem;\n}\n\n.author-social {\n display: flex;\n gap: 0.5rem;\n}\n\n.social-link {\n color: var(--md-default-fg-color--light);\n transition: color 0.2s ease;\n}\n\n.social-link:hover {\n color: var(--md-accent-fg-color);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#822-minify","title":"8.2.2 minify","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8221-html","title":"8.2.2.1 HTML \u538b\u7f29","text":"pip install mkdocs-minify-plugin\n
# mkdocs.yml\nplugins:\n - minify:\n minify_html: true\n htmlmin_opts:\n # HTML\u538b\u7f29\u9009\u9879\n remove_comments: true # \u79fb\u9664\u6ce8\u91ca\n remove_empty_space: true # \u79fb\u9664\u7a7a\u767d\n remove_all_empty_space: true # \u79fb\u9664\u6240\u6709\u7a7a\u767d\n reduce_boolean_attributes: true # \u7b80\u5316\u5e03\u5c14\u5c5e\u6027\n remove_optional_tags: false # \u4fdd\u7559\u53ef\u9009\u6807\u7b7e\n remove_redundant_attributes: true # \u79fb\u9664\u5197\u4f59\u5c5e\u6027\n minify_js: true # \u538b\u7f29\u5185\u8054JS\n minify_css: true # \u538b\u7f29\u5185\u8054CSS\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8222-css","title":"8.2.2.2 CSS \u538b\u7f29","text":"plugins:\n - minify:\n minify_css: true\n css_files:\n - stylesheets/extra.css\n - stylesheets/custom.css\n cssmin_opts:\n # CSS\u538b\u7f29\u9009\u9879\n level: 2 # \u538b\u7f29\u7ea7\u522b(1-2)\n compatibility: ie9 # \u517c\u5bb9\u6027\n format: beautify # \u683c\u5f0f\u5316\u8f93\u51fa\n
# docs/tools/css_optimizer.py\nimport re\nfrom pathlib import Path\nfrom csscompressor import compress\n\nclass CSSOptimizer:\n def __init__(self, input_dir, output_dir):\n self.input_dir = Path(input_dir)\n self.output_dir = Path(output_dir)\n self.output_dir.mkdir(exist_ok=True)\n\n def optimize(self):\n \"\"\"\u4f18\u5316\u6240\u6709CSS\u6587\u4ef6\"\"\"\n for css_file in self.input_dir.glob('**/*.css'):\n # \u8bfb\u53d6CSS\u5185\u5bb9\n content = css_file.read_text(encoding='utf-8')\n\n # \u4f18\u5316CSS\n optimized = self.optimize_css(content)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u6587\u4ef6\n output_file = self.output_dir / css_file.name\n output_file.write_text(optimized, encoding='utf-8')\n\n def optimize_css(self, content):\n \"\"\"\u4f18\u5316\u5355\u4e2aCSS\u6587\u4ef6\u5185\u5bb9\"\"\"\n # \u79fb\u9664\u6ce8\u91ca\n content = re.sub(r'/\\*[\\s\\S]*?\\*/', '', content)\n\n # \u79fb\u9664\u591a\u4f59\u7a7a\u767d\n content = re.sub(r'\\s+', ' ', content)\n\n # \u538b\u7f29CSS\n content = compress(content)\n\n return content\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = CSSOptimizer(\n input_dir='docs/stylesheets',\n output_dir='docs/stylesheets/min'\n)\noptimizer.optimize()\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8223-js","title":"8.2.2.3 JS \u538b\u7f29","text":"plugins:\n - minify:\n minify_js: true\n js_files:\n - javascripts/extra.js\n - javascripts/custom.js\n jsmin_opts:\n # JS\u538b\u7f29\u9009\u9879\n mangle: true # \u6df7\u6dc6\u53d8\u91cf\u540d\n compress: true # \u538b\u7f29\u4ee3\u7801\n output:\n beautify: false # \u4e0d\u7f8e\u5316\u8f93\u51fa\n
# docs/tools/js_optimizer.py\nimport re\nfrom pathlib import Path\nimport terser\n\nclass JSOptimizer:\n def __init__(self, input_dir, output_dir):\n self.input_dir = Path(input_dir)\n self.output_dir = Path(output_dir)\n self.output_dir.mkdir(exist_ok=True)\n\n def optimize(self):\n \"\"\"\u4f18\u5316\u6240\u6709JS\u6587\u4ef6\"\"\"\n for js_file in self.input_dir.glob('**/*.js'):\n # \u8bfb\u53d6JS\u5185\u5bb9\n content = js_file.read_text(encoding='utf-8')\n\n # \u4f18\u5316JS\n optimized = self.optimize_js(content)\n\n # \u4fdd\u5b58\u4f18\u5316\u540e\u7684\u6587\u4ef6\n output_file = self.output_dir / js_file.name\n output_file.write_text(optimized, encoding='utf-8')\n\n def optimize_js(self, content):\n \"\"\"\u4f18\u5316\u5355\u4e2aJS\u6587\u4ef6\u5185\u5bb9\"\"\"\n options = {\n 'compress': {\n 'pure_funcs': ['console.log'], # \u79fb\u9664console.log\n 'drop_debugger': True, # \u79fb\u9664debugger\n 'unsafe': True, # \u542f\u7528\u4e0d\u5b89\u5168\u4f18\u5316\n 'passes': 2 # \u4f18\u5316\u6b21\u6570\n },\n 'mangle': {\n 'toplevel': True, # \u6df7\u6dc6\u9876\u7ea7\u4f5c\u7528\u57df\n 'eval': True # \u6df7\u6dc6eval\u4e2d\u7684\u53d8\u91cf\n }\n }\n\n # \u4f7f\u7528terser\u538b\u7f29\n result = terser.minify(content, options)\n return result['code']\n\n# \u4f7f\u7528\u4f18\u5316\u5668\noptimizer = JSOptimizer(\n input_dir='docs/javascripts',\n output_dir='docs/javascripts/min'\n)\noptimizer.optimize()\n
\u8fd9\u4e9b\u914d\u7f6e\u548c\u811a\u672c\u53ef\u4ee5\u6709\u6548\u51cf\u5c0f\u7ad9\u70b9\u8d44\u6e90\u5927\u5c0f\uff0c\u63d0\u5347\u52a0\u8f7d\u901f\u5ea6\u3002\u8bb0\u5f97\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u538b\u7f29\u540e\u7684\u8d44\u6e90\u3002
"},{"location":"Tools/Blog/Mkdocs_Material/#823-social","title":"8.2.3 social","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8231","title":"8.2.3.1 \u793e\u4ea4\u94fe\u63a5","text":"pip install mkdocs-social-plugin\n
# mkdocs.yml\nplugins:\n - social:\n enabled: true\n # \u793e\u4ea4\u5e73\u53f0\u914d\u7f6e\n cards: true # \u542f\u7528\u793e\u4ea4\u5361\u7247\n cards_color: # \u5361\u7247\u989c\u8272\n fill: \"#0FF1CE\" # \u80cc\u666f\u8272\n text: \"#FFFFFF\" # \u6587\u5b57\u8272\n cards_font: Roboto # \u5361\u7247\u5b57\u4f53\n\nextra:\n social:\n - icon: material/github\n link: https://github.com/username\n name: GitHub\n - icon: material/twitter\n link: https://twitter.com/username\n name: Twitter\n - icon: material/linkedin\n link: https://linkedin.com/in/username\n name: LinkedIn\n
<!-- docs/overrides/partials/social.html -->\n{% if config.extra.social %}\n<div class=\"social-links\">\n {% for social in config.extra.social %}\n <a href=\"{{ social.link }}\" \n target=\"_blank\"\n rel=\"noopener\"\n title=\"{{ social.name }}\"\n class=\"social-link\">\n <span class=\"social-icon\">\n {% include \".icons/\" ~ social.icon ~ \".svg\" %}\n </span>\n <span class=\"social-name\">{{ social.name }}</span>\n </a>\n {% endfor %}\n</div>\n{% endif %}\n
\u6837\u5f0f\u914d\u7f6e\uff1a
CSS/* docs/stylesheets/social.css */\n.social-links {\n display: flex;\n gap: 1rem;\n margin: 2rem 0;\n}\n\n.social-link {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n transition: all 0.2s ease;\n}\n\n.social-link:hover {\n transform: translateY(-2px);\n color: var(--md-accent-fg-color);\n background: var(--md-code-bg-color--light);\n}\n\n.social-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n.social-name {\n font-size: 0.9rem;\n}\n\n/* \u52a8\u753b\u6548\u679c */\n.social-link .social-icon {\n transition: transform 0.2s ease;\n}\n\n.social-link:hover .social-icon {\n transform: scale(1.2);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8232","title":"8.2.3.2 \u5206\u4eab\u529f\u80fd","text":"# mkdocs.yml\nextra:\n social_share:\n - platform: twitter\n text: \u5206\u4eab\u5230 Twitter\n icon: material/twitter\n - platform: facebook\n text: \u5206\u4eab\u5230 Facebook\n icon: material/facebook\n - platform: linkedin\n text: \u5206\u4eab\u5230 LinkedIn\n icon: material/linkedin\n - platform: weibo\n text: \u5206\u4eab\u5230\u5fae\u535a\n icon: material/sina-weibo\n
<!-- docs/overrides/partials/share.html -->\n<div class=\"page-share\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n {% for share in config.extra.social_share %}\n <button class=\"share-button\" \n data-platform=\"{{ share.platform }}\"\n onclick=\"shareContent('{{ share.platform }}')\">\n <span class=\"share-icon\">\n {% include \".icons/\" ~ share.icon ~ \".svg\" %}\n </span>\n <span class=\"share-text\">{{ share.text }}</span>\n </button>\n {% endfor %}\n </div>\n</div>\n\n<script>\nfunction shareContent(platform) {\n const url = encodeURIComponent(window.location.href);\n const title = encodeURIComponent(document.title);\n const text = encodeURIComponent(document.querySelector('meta[name=\"description\"]')?.content || '');\n\n let shareUrl;\n switch(platform) {\n case 'twitter':\n shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;\n break;\n case 'facebook':\n shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;\n break;\n case 'linkedin':\n shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;\n break;\n case 'weibo':\n shareUrl = `http://service.weibo.com/share/share.php?url=${url}&title=${title}`;\n break;\n }\n\n window.open(shareUrl, '_blank', 'width=600,height=400');\n}\n</script>\n
/* docs/stylesheets/share.css */\n.page-share {\n margin: 2rem 0;\n padding: 1rem;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n}\n\n.share-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n}\n\n.share-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n border: none;\n border-radius: 2rem;\n background: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n\n.share-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8233","title":"8.2.3.3 \u5173\u6ce8\u6309\u94ae","text":"extra:\n follow_buttons:\n - platform: github\n username: your-username\n icon: material/github\n text: \u5173\u6ce8\u6211\u7684 GitHub\n - platform: twitter\n username: your-username\n icon: material/twitter\n text: \u5173\u6ce8\u6211\u7684 Twitter\n
<!-- docs/overrides/partials/follow.html -->\n<div class=\"follow-buttons\">\n {% for btn in config.extra.follow_buttons %}\n <a href=\"https://{{ btn.platform }}.com/{{ btn.username }}\"\n target=\"_blank\"\n class=\"follow-button\"\n data-platform=\"{{ btn.platform }}\">\n <span class=\"follow-icon\">\n {% include \".icons/\" ~ btn.icon ~ \".svg\" %}\n </span>\n <span class=\"follow-text\">{{ btn.text }}</span>\n <span class=\"follow-count\" id=\"{{ btn.platform }}-count\">\n <!-- \u5c06\u901a\u8fc7API\u52a8\u6001\u66f4\u65b0 -->\n </span>\n </a>\n {% endfor %}\n</div>\n\n<script>\nasync function updateFollowCounts() {\n const buttons = document.querySelectorAll('.follow-button');\n\n for (const button of buttons) {\n const platform = button.dataset.platform;\n const username = button.href.split('/').pop();\n\n // \u83b7\u53d6\u5173\u6ce8\u6570\n const count = await getFollowCount(platform, username);\n\n // \u66f4\u65b0\u663e\u793a\n const countElement = button.querySelector('.follow-count');\n if (countElement && count) {\n countElement.textContent = formatCount(count);\n }\n }\n}\n\nasync function getFollowCount(platform, username) {\n switch (platform) {\n case 'github':\n const response = await fetch(`https://api.github.com/users/${username}`);\n const data = await response.json();\n return data.followers;\n\n // \u5176\u4ed6\u5e73\u53f0API\u5b9e\u73b0...\n default:\n return null;\n }\n}\n\nfunction formatCount(count) {\n if (count >= 1000000) {\n return (count / 1000000).toFixed(1) + 'M';\n }\n if (count >= 1000) {\n return (count / 1000).toFixed(1) + 'K';\n }\n return count.toString();\n}\n\n// \u521d\u59cb\u5316\nupdateFollowCounts();\n</script>\n
/* docs/stylesheets/follow.css */\n.follow-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 2rem 0;\n}\n\n.follow-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n text-decoration: none;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n transition: all 0.2s ease;\n}\n\n.follow-button:hover {\n transform: translateY(-2px);\n}\n\n/* \u5e73\u53f0\u7279\u5b9a\u6837\u5f0f */\n.follow-button[data-platform=\"github\"] {\n color: #333;\n}\n\n.follow-button[data-platform=\"github\"]:hover {\n background: #333;\n color: white;\n}\n\n.follow-button[data-platform=\"twitter\"] {\n color: #1DA1F2;\n}\n\n.follow-button[data-platform=\"twitter\"]:hover {\n background: #1DA1F2;\n color: white;\n}\n\n.follow-icon {\n margin-right: 0.5rem;\n width: 1.2rem;\n height: 1.2rem;\n}\n\n.follow-count {\n margin-left: 0.5rem;\n padding: 0.2rem 0.5rem;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 1rem;\n font-size: 0.8rem;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#824-tags","title":"8.2.4 tags","text":""},{"location":"Tools/Blog/Mkdocs_Material/#8241","title":"8.2.4.1 \u6807\u7b7e\u7cfb\u7edf","text":"pip install mkdocs-tags-plugin\n
# mkdocs.yml\nplugins:\n - tags:\n tags_file: tags.md\n tags_allowed: # \u5141\u8bb8\u7684\u6807\u7b7e\u5217\u8868\n - Python\n - JavaScript\n - CSS\n - HTML\n tags_extra_files:\n cloud: tag_cloud.md # \u6807\u7b7e\u4e91\u9875\u9762\n list: tag_list.md # \u6807\u7b7e\u5217\u8868\u9875\u9762\n
---\ntags:\n - Python\n - \u6559\u7a0b\n---\n\n# Python \u5165\u95e8\u6559\u7a0b\n
<!-- docs/overrides/partials/tags.html -->\n{% if page.meta.tags %}\n<div class=\"page-tags\">\n {% for tag in page.meta.tags %}\n <a href=\"{{ base_url }}/tags/#{{ tag|lower }}\" class=\"tag\">\n <span class=\"tag-icon\">\n {% include \".icons/material/tag.svg\" %}\n </span>\n <span class=\"tag-text\">{{ tag }}</span>\n </a>\n {% endfor %}\n</div>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8242","title":"8.2.4.2 \u6807\u7b7e\u4e91","text":"# docs/plugins/tags/cloud.py\nfrom collections import Counter\nimport math\n\nclass TagCloud:\n def __init__(self, tags):\n self.tags = Counter(tags)\n self.min_size = 0.8\n self.max_size = 2.0\n\n def get_tag_sizes(self):\n \"\"\"\u8ba1\u7b97\u6807\u7b7e\u5927\u5c0f\"\"\"\n if not self.tags:\n return {}\n\n # \u83b7\u53d6\u6700\u5927\u548c\u6700\u5c0f\u9891\u7387\n max_freq = max(self.tags.values())\n min_freq = min(self.tags.values())\n\n # \u8ba1\u7b97\u6bcf\u4e2a\u6807\u7b7e\u7684\u5927\u5c0f\n sizes = {}\n for tag, freq in self.tags.items():\n if max_freq == min_freq:\n sizes[tag] = (self.max_size + self.min_size) / 2\n else:\n size = self.min_size + (self.max_size - self.min_size) * \\\n ((freq - min_freq) / (max_freq - min_freq))\n sizes[tag] = round(size, 2)\n\n return sizes\n\ndef generate_tag_cloud(tags):\n \"\"\"\u751f\u6210\u6807\u7b7e\u4e91HTML\"\"\"\n cloud = TagCloud(tags)\n sizes = cloud.get_tag_sizes()\n\n html = ['<div class=\"tag-cloud\">']\n\n for tag, size in sizes.items():\n html.append(f'''\n <a href=\"#tag-{tag.lower()}\" \n class=\"tag-cloud-item\"\n style=\"font-size: {size}rem\">\n {tag}\n </a>\n ''')\n\n html.append('</div>')\n return '\\n'.join(html)\n
/* docs/stylesheets/tags.css */\n.tag-cloud {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 1rem;\n padding: 2rem;\n}\n\n.tag-cloud-item {\n color: var(--md-default-fg-color);\n text-decoration: none;\n padding: 0.5rem 1rem;\n border-radius: 2rem;\n background: var(--md-code-bg-color);\n transition: all 0.2s ease;\n}\n\n.tag-cloud-item:hover {\n transform: scale(1.1);\n background: var(--md-accent-fg-color);\n color: white;\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#8243","title":"8.2.4.3 \u6807\u7b7e\u9875\u9762","text":"# \u6807\u7b7e\u7d22\u5f15\n\n## \u6807\u7b7e\u4e91\n[TAGS_CLOUD]\n\n## \u6807\u7b7e\u5217\u8868\n[TAGS_LIST]\n
# docs/plugins/tags/generator.py\nfrom pathlib import Path\nimport yaml\n\nclass TagPageGenerator:\n def __init__(self, config):\n self.config = config\n self.tags = {}\n\n def collect_tags(self):\n \"\"\"\u6536\u96c6\u6240\u6709\u6807\u7b7e\"\"\"\n docs_dir = Path(self.config['docs_dir'])\n\n for md_file in docs_dir.glob('**/*.md'):\n # \u8bfb\u53d6\u6587\u4ef6frontmatter\n content = md_file.read_text(encoding='utf-8')\n if content.startswith('---'):\n try:\n # \u89e3\u6790frontmatter\n _, frontmatter, _ = content.split('---', 2)\n meta = yaml.safe_load(frontmatter)\n\n if 'tags' in meta:\n # \u83b7\u53d6\u76f8\u5bf9\u8def\u5f84\n rel_path = md_file.relative_to(docs_dir)\n url = str(rel_path).replace('\\\\', '/')[:-3] # \u79fb\u9664.md\n\n # \u6dfb\u52a0\u5230\u6807\u7b7e\u7d22\u5f15\n for tag in meta['tags']:\n if tag not in self.tags:\n self.tags[tag] = []\n self.tags[tag].append({\n 'title': meta.get('title', url),\n 'url': url,\n 'description': meta.get('description', '')\n })\n except:\n continue\n\n def generate_tag_pages(self):\n \"\"\"\u751f\u6210\u6807\u7b7e\u76f8\u5173\u9875\u9762\"\"\"\n self.collect_tags()\n\n # \u751f\u6210\u6807\u7b7e\u5217\u8868\u9875\u9762\n if 'list' in self.config['tags_extra_files']:\n self.generate_list_page()\n\n # \u751f\u6210\u6bcf\u4e2a\u6807\u7b7e\u7684\u8be6\u60c5\u9875\u9762\n self.generate_tag_detail_pages()\n\n def generate_list_page(self):\n \"\"\"\u751f\u6210\u6807\u7b7e\u5217\u8868\u9875\u9762\"\"\"\n template = \"\"\"\n# \u6807\u7b7e\u5217\u8868\n\n{% for tag, posts in tags.items() %}\n## {{ tag }}\n\n{% for post in posts %}\n- [{{ post.title }}]({{ post.url }}){% if post.description %} - {{ post.description }}{% endif %}\n{% endfor %}\n\n{% endfor %}\n\"\"\"\n # \u4f7f\u7528 Jinja2 \u6e32\u67d3\u6a21\u677f\n from jinja2 import Template\n content = Template(template).render(tags=self.tags)\n\n # \u4fdd\u5b58\u9875\u9762\n output_file = Path(self.config['docs_dir']) / 'tags' / 'list.md'\n output_file.parent.mkdir(exist_ok=True)\n output_file.write_text(content, encoding='utf-8')\n\n def generate_tag_detail_pages(self):\n \"\"\"\u751f\u6210\u6bcf\u4e2a\u6807\u7b7e\u7684\u8be6\u60c5\u9875\u9762\"\"\"\n template = \"\"\"\n# \u6807\u7b7e: {{ tag }}\n\n## \u76f8\u5173\u6587\u7ae0\n\n{% for post in posts %}\n### [{{ post.title }}]({{ post.url }})\n{% if post.description %}\n{{ post.description }}\n{% endif %}\n{% endfor %}\n\n## \u76f8\u5173\u6807\u7b7e\n{% for related_tag in related_tags %}\n- [{{ related_tag }}](../{{ related_tag | lower }})\n{% endfor %}\n\"\"\"\n # \u6807\u7b7e\u76ee\u5f55\n tags_dir = Path(self.config['docs_dir']) / 'tags'\n tags_dir.mkdir(exist_ok=True)\n\n # \u4e3a\u6bcf\u4e2a\u6807\u7b7e\u751f\u6210\u9875\u9762\n for tag, posts in self.tags.items():\n # \u67e5\u627e\u76f8\u5173\u6807\u7b7e\n related_tags = self.find_related_tags(tag)\n\n # \u6e32\u67d3\u5185\u5bb9\n content = Template(template).render(\n tag=tag,\n posts=posts,\n related_tags=related_tags\n )\n\n # \u4fdd\u5b58\u9875\u9762\n output_file = tags_dir / f\"{tag.lower()}.md\"\n output_file.write_text(content, encoding='utf-8')\n\n def find_related_tags(self, current_tag):\n \"\"\"\u67e5\u627e\u76f8\u5173\u6807\u7b7e\"\"\"\n related = set()\n\n # \u83b7\u53d6\u5f53\u524d\u6807\u7b7e\u7684\u6240\u6709\u6587\u7ae0\n current_posts = self.tags[current_tag]\n\n # \u904d\u5386\u6240\u6709\u5176\u4ed6\u6807\u7b7e\n for tag, posts in self.tags.items():\n if tag == current_tag:\n continue\n\n # \u8ba1\u7b97\u6587\u7ae0\u4ea4\u96c6\n intersection = set(p['url'] for p in posts) & \\\n set(p['url'] for p in current_posts)\n\n # \u5982\u679c\u6709\u5171\u540c\u6587\u7ae0\uff0c\u8ba4\u4e3a\u662f\u76f8\u5173\u6807\u7b7e\n if intersection:\n related.add(tag)\n\n return list(related)\n
/* docs/stylesheets/tags-page.css */\n/* \u6807\u7b7e\u5217\u8868\u9875\u9762 */\n.tags-list {\n margin: 2rem 0;\n}\n\n.tag-section {\n margin-bottom: 3rem;\n}\n\n.tag-section h2 {\n color: var(--md-accent-fg-color);\n border-bottom: 2px solid var(--md-accent-fg-color);\n padding-bottom: 0.5rem;\n}\n\n.tag-section .post-list {\n margin-left: 1rem;\n}\n\n.post-list-item {\n margin: 1rem 0;\n}\n\n.post-list-item .post-title {\n font-weight: 500;\n color: var(--md-default-fg-color);\n text-decoration: none;\n}\n\n.post-list-item .post-description {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-top: 0.2rem;\n}\n\n/* \u6807\u7b7e\u8be6\u60c5\u9875\u9762 */\n.tag-detail {\n padding: 2rem;\n}\n\n.tag-detail-header {\n text-align: center;\n margin-bottom: 3rem;\n}\n\n.tag-detail-title {\n font-size: 2rem;\n color: var(--md-primary-fg-color);\n}\n\n.tag-detail-count {\n color: var(--md-default-fg-color--light);\n}\n\n.related-posts {\n margin: 2rem 0;\n}\n\n.related-post {\n padding: 1rem;\n margin: 1rem 0;\n background: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.related-post:hover {\n transform: translateX(0.5rem);\n}\n\n.related-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin: 2rem 0;\n}\n\n.related-tag {\n padding: 0.2rem 0.8rem;\n background: var(--md-code-bg-color);\n border-radius: 2rem;\n font-size: 0.9rem;\n color: var(--md-default-fg-color);\n text-decoration: none;\n transition: all 0.2s ease;\n}\n\n.related-tag:hover {\n background: var(--md-accent-fg-color);\n color: white;\n}\n
// docs/javascripts/tags.js\nclass TagsManager {\n constructor() {\n this.initializeFilters();\n this.setupSearch();\n this.setupSorting();\n }\n\n initializeFilters() {\n const tagList = document.querySelector('.tags-list');\n if (!tagList) return;\n\n // \u521b\u5efa\u8fc7\u6ee4\u5668\n const filterContainer = document.createElement('div');\n filterContainer.className = 'tags-filter';\n filterContainer.innerHTML = `\n <input type=\"text\" \n class=\"filter-input\" \n placeholder=\"\u641c\u7d22\u6807\u7b7e...\">\n <select class=\"sort-select\">\n <option value=\"name\">\u6309\u540d\u79f0\u6392\u5e8f</option>\n <option value=\"count\">\u6309\u6587\u7ae0\u6570\u91cf\u6392\u5e8f</option>\n </select>\n `;\n\n tagList.insertBefore(filterContainer, tagList.firstChild);\n }\n\n setupSearch() {\n const input = document.querySelector('.filter-input');\n if (!input) return;\n\n input.addEventListener('input', () => {\n const query = input.value.toLowerCase();\n const sections = document.querySelectorAll('.tag-section');\n\n sections.forEach(section => {\n const tag = section.querySelector('h2').textContent.toLowerCase();\n section.style.display = tag.includes(query) ? 'block' : 'none';\n });\n });\n }\n\n setupSorting() {\n const select = document.querySelector('.sort-select');\n if (!select) return;\n\n select.addEventListener('change', () => {\n const sections = Array.from(document.querySelectorAll('.tag-section'));\n const container = sections[0].parentElement;\n\n sections.sort((a, b) => {\n const aTag = a.querySelector('h2').textContent;\n const bTag = b.querySelector('h2').textContent;\n const aCount = this.getPostCount(a);\n const bCount = this.getPostCount(b);\n\n if (select.value === 'name') {\n return aTag.localeCompare(bTag);\n } else {\n return bCount - aCount;\n }\n });\n\n // \u91cd\u65b0\u63d2\u5165\u6392\u5e8f\u540e\u7684\u7ae0\u8282\n sections.forEach(section => container.appendChild(section));\n });\n }\n\n getPostCount(section) {\n return section.querySelectorAll('.post-list-item').length;\n }\n}\n\n// \u521d\u59cb\u5316\u6807\u7b7e\u7ba1\u7406\u5668\ndocument.addEventListener('DOMContentLoaded', () => {\n new TagsManager();\n});\n
\u4f7f\u7528\u4ee5\u4e0a\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5b8c\u6574\u7684\u6807\u7b7e\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u914d\u7f6e\u6587\u4ef6\u9700\u8981\u6dfb\u52a0\u76f8\u5e94\u7684\u5f15\u7528\uff1a
YAML# mkdocs.yml\nextra_css:\n - stylesheets/tags.css\n - stylesheets/tags-page.css\n\nextra_javascript:\n - javascripts/tags.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#9","title":"9 \u529f\u80fd\u6269\u5c55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#91","title":"9.1 \u8bc4\u8bba\u7cfb\u7edf","text":""},{"location":"Tools/Blog/Mkdocs_Material/#911-giscus","title":"9.1.1 Giscus \u914d\u7f6e","text":"# mkdocs.yml\nextra:\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your_repo_id\n category: Comments\n category_id: your_category_id\n
<!-- docs/overrides/partials/comments.html -->\n{% if config.extra.comments.provider == 'giscus' %}\n<div class=\"comments-container\">\n <h3>\u8bc4\u8bba</h3>\n <div class=\"giscus\"></div>\n\n <script>\n function loadGiscus() {\n const script = document.createElement('script');\n script.src = 'https://giscus.app/client.js';\n script.setAttribute('data-repo', '{{ config.extra.comments.repo }}');\n script.setAttribute('data-repo-id', '{{ config.extra.comments.repo_id }}');\n script.setAttribute('data-category', '{{ config.extra.comments.category }}');\n script.setAttribute('data-category-id', '{{ config.extra.comments.category_id }}');\n script.setAttribute('data-mapping', 'pathname');\n script.setAttribute('data-reactions-enabled', '1');\n script.setAttribute('data-emit-metadata', '0');\n script.setAttribute('data-theme', 'preferred_color_scheme');\n script.setAttribute('crossorigin', 'anonymous');\n script.async = true;\n\n document.querySelector('.giscus').appendChild(script);\n }\n\n // \u5ef6\u8fdf\u52a0\u8f7d\u8bc4\u8bba\n if ('IntersectionObserver' in window) {\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) {\n loadGiscus();\n observer.disconnect();\n }\n });\n\n observer.observe(document.querySelector('.comments-container'));\n } else {\n loadGiscus();\n }\n </script>\n</div>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#912","title":"9.1.2 \u81ea\u5b9a\u4e49\u8bc4\u8bba\u6837\u5f0f","text":"CSS/* docs/stylesheets/comments.css */\n.comments-container {\n margin: 3rem 0;\n padding-top: 2rem;\n border-top: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.giscus {\n width: 100%;\n}\n\n/* Giscus \u4e3b\u9898\u9002\u914d */\n.giscus-frame {\n background-color: var(--md-default-bg-color);\n color: var(--md-default-fg-color);\n}\n\n/* \u6697\u8272\u6a21\u5f0f\u9002\u914d */\n[data-md-color-scheme=\"slate\"] .giscus-frame {\n background-color: var(--md-default-bg-color--dark);\n color: var(--md-default-fg-color--dark);\n}\n\n/* \u8bc4\u8bba\u6846\u6837\u5f0f */\n.giscus .gsc-comment-box {\n background-color: var(--md-code-bg-color);\n border-radius: 8px;\n padding: 1rem;\n}\n\n/* \u8bc4\u8bba\u5217\u8868\u6837\u5f0f */\n.giscus .gsc-comment {\n margin: 1rem 0;\n padding: 1rem;\n background-color: var(--md-code-bg-color);\n border-radius: 8px;\n transition: transform 0.2s ease;\n}\n\n.giscus .gsc-comment:hover {\n transform: translateX(4px);\n}\n\n/* \u6309\u94ae\u6837\u5f0f */\n.giscus .gsc-button {\n background-color: var(--md-primary-fg-color);\n color: var(--md-primary-bg-color);\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.giscus .gsc-button:hover {\n background-color: var(--md-primary-fg-color--dark);\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#92","title":"9.2 \u6570\u636e\u7edf\u8ba1","text":""},{"location":"Tools/Blog/Mkdocs_Material/#921-google-analytics","title":"9.2.1 Google Analytics","text":"# mkdocs.yml\nextra:\n analytics:\n provider: google\n property: G-XXXXXXXXXX\n\n # \u4e8b\u4ef6\u8ffd\u8e2a\n events: true\n # \u7528\u6237\u884c\u4e3a\u8ffd\u8e2a\n behavior: true\n
<!-- docs/overrides/partials/analytics.html -->\n{% if config.extra.analytics.provider == 'google' %}\n<!-- Google Analytics -->\n<script async src=\"https://www.googletagmanager.com/gtag/js?id={{ config.extra.analytics.property }}\"></script>\n<script>\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '{{ config.extra.analytics.property }}');\n\n // \u4e8b\u4ef6\u8ffd\u8e2a\n if ({{ config.extra.analytics.events|tojson }}) {\n document.addEventListener('DOMContentLoaded', function() {\n // \u70b9\u51fb\u4e8b\u4ef6\u8ffd\u8e2a\n document.addEventListener('click', function(e) {\n const target = e.target.closest('a');\n if (target) {\n gtag('event', 'click', {\n 'event_category': 'link',\n 'event_label': target.href\n });\n }\n });\n\n // \u6eda\u52a8\u4e8b\u4ef6\u8ffd\u8e2a\n let lastScrollDepth = 0;\n window.addEventListener('scroll', debounce(function() {\n const scrollDepth = Math.round(\n (window.scrollY + window.innerHeight) / \n document.documentElement.scrollHeight * 100\n );\n\n if (scrollDepth > lastScrollDepth) {\n gtag('event', 'scroll_depth', {\n 'depth': scrollDepth\n });\n lastScrollDepth = scrollDepth;\n }\n }, 500));\n\n // \u641c\u7d22\u4e8b\u4ef6\u8ffd\u8e2a\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.addEventListener('search', function() {\n gtag('event', 'search', {\n 'search_term': this.value\n });\n });\n }\n });\n }\n\n // \u7528\u6237\u884c\u4e3a\u8ffd\u8e2a\n if ({{ config.extra.analytics.behavior|tojson }}) {\n // \u9875\u9762\u505c\u7559\u65f6\u95f4\n let startTime = Date.now();\n window.addEventListener('beforeunload', function() {\n const duration = Math.round((Date.now() - startTime) / 1000);\n gtag('event', 'time_on_page', {\n 'duration': duration\n });\n });\n\n // \u590d\u5236\u884c\u4e3a\u8ffd\u8e2a\n document.addEventListener('copy', function() {\n gtag('event', 'content_copy');\n });\n }\n</script>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#922","title":"9.2.2 \u4e0d\u849c\u5b50\u7edf\u8ba1","text":"extra:\n analytics:\n busuanzi: true\n
<!-- docs/overrides/partials/busuanzi.html -->\n{% if config.extra.analytics.busuanzi %}\n<script async src=\"//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js\"></script>\n\n<div class=\"page-views\">\n <!-- \u603b\u8bbf\u95ee\u91cf -->\n <span id=\"busuanzi_container_site_pv\">\n \u603b\u8bbf\u95ee\u91cf: <span id=\"busuanzi_value_site_pv\"></span>\u6b21\n </span>\n\n <!-- \u603b\u8bbf\u5ba2\u6570 -->\n <span id=\"busuanzi_container_site_uv\">\n \u8bbf\u5ba2\u6570: <span id=\"busuanzi_value_site_uv\"></span>\u4eba\n </span>\n\n <!-- \u9875\u9762\u8bbf\u95ee\u91cf -->\n <span id=\"busuanzi_container_page_pv\">\n \u672c\u6587\u8bbf\u95ee\u91cf: <span id=\"busuanzi_value_page_pv\"></span>\u6b21\n </span>\n</div>\n\n<style>\n.page-views {\n display: flex;\n gap: 1rem;\n margin: 1rem 0;\n padding: 0.5rem;\n background: var(--md-code-bg-color);\n border-radius: 4px;\n font-size: 0.9rem;\n}\n\n.page-views span {\n color: var(--md-default-fg-color--light);\n}\n\n.page-views span span {\n color: var(--md-accent-fg-color);\n font-weight: bold;\n}\n</style>\n{% endif %}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#93","title":"9.3 \u793e\u4ea4\u5206\u4eab","text":""},{"location":"Tools/Blog/Mkdocs_Material/#931","title":"9.3.1 \u5206\u4eab\u6309\u94ae","text":"extra:\n social_share:\n enabled: true\n platforms:\n - name: twitter\n icon: material/twitter\n color: '#1DA1F2'\n - name: facebook\n icon: material/facebook\n color: '#4267B2'\n - name: linkedin\n icon: material/linkedin\n color: '#0A66C2'\n - name: weibo\n icon: material/sina-weibo\n color: '#E6162D'\n
<!-- docs/overrides/partials/share.html -->\n{% if config.extra.social_share.enabled %}\n<div class=\"share-container\">\n <h4>\u5206\u4eab\u6587\u7ae0</h4>\n <div class=\"share-buttons\">\n {% for platform in config.extra.social_share.platforms %}\n <button class=\"share-button\" \n data-platform=\"{{ platform.name }}\"\n style=\"--platform-color: {{ platform.color }}\"\n onclick=\"shareContent('{{ platform.name }}')\">\n <span class=\"share-icon\">\n {% include \".icons/\" ~ platform.icon ~ \".svg\" %}\n </span>\n <span class=\"share-text\">\u5206\u4eab\u5230 {{ platform.name|title }}</span>\n </button>\n {% endfor %}\n </div>\n</div>\n\n<style>\n.share-container {\n margin: 2rem 0;\n}\n\n.share-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n}\n\n.share-button {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n border: none;\n border-radius: 4px;\n background: var(--md-code-bg-color);\n color: var(--platform-color);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.share-button:hover {\n background: var(--platform-color);\n color: white;\n transform: translateY(-2px);\n}\n\n.share-icon {\n margin-right: 0.5rem;\n}\n</style>\n
"},{"location":"Tools/Blog/Mkdocs_Material/#932","title":"9.3.2 \u5206\u4eab\u94fe\u63a5\u751f\u6210","text":"JavaScript// docs/javascripts/share.js\nclass ShareManager {\n constructor() {\n this.title = document.title;\n this.url = window.location.href;\n this.description = document\n .querySelector('meta[name=\"description\"]')\n ?.content || '';\n }\n\n generateShareUrl(platform) {\n const params = new URLSearchParams();\n switch (platform) {\n case 'twitter':\n return `https://twitter.com/intent/tweet?${\n params.set('text', this.title),\n params.set('url', this.url)\n }`;\n\n case 'facebook':\n return `https://www.facebook.com/sharer/sharer.php?${\n params.set('u', this.url)\n }`;\n\n case 'linkedin':\n return `https://www.linkedin.com/sharing/share-offsite/?${\n params.set('url', this.url)\n }`;\n\n case 'weibo':\n return `http://service.weibo.com/share/share.php?${\n params.set('title', this.title),\n params.set('url', this.url)\n }`;\n\n default:\n return null;\n }\n }\n\n async share(platform) {\n // \u68c0\u67e5\u662f\u5426\u652f\u6301\u539f\u751f\u5206\u4eab\n if (navigator.share && platform === 'native') {\n try {\n await navigator.share({\n title: this.title,\n text: this.description,\n url: this.url\n });\n return true;\n } catch (err) {\n console.warn('Native share failed:', err);\n return false;\n }\n }\n\n // \u4f7f\u7528\u5f39\u7a97\u5206\u4eab\n const url = this.generateShareUrl(platform);\n if (url) {\n window.open(url, '_blank', 'width=600,height=400');\n return true;\n }\n\n return false;\n }\n\n // \u81ea\u5b9a\u4e49\u5206\u4eab\u5185\u5bb9\n setContent(title, description) {\n this.title = title;\n this.description = description;\n }\n}\n\n// \u5168\u5c40\u5206\u4eab\u529f\u80fd\nwindow.shareContent = async function(platform) {\n const shareManager = new ShareManager();\n const success = await shareManager.share(platform);\n\n // \u8bb0\u5f55\u5206\u4eab\u4e8b\u4ef6\n if (success) {\n recordShare(platform);\n }\n};\n\n// \u5206\u4eab\u7edf\u8ba1\nfunction recordShare(platform) {\n // GA4 \u4e8b\u4ef6\u8ffd\u8e2a\n if (typeof gtag !== 'undefined') {\n gtag('event', 'share', {\n 'platform': platform,\n 'title': document.title,\n 'url': window.location.href\n });\n }\n\n // \u672c\u5730\u5b58\u50a8\u7edf\u8ba1\n const stats = JSON.parse(localStorage.getItem('share_stats') || '{}');\n stats[platform] = (stats[platform] || 0) + 1;\n localStorage.setItem('share_stats', JSON.stringify(stats));\n\n updateShareCount(platform);\n}\n\n// \u66f4\u65b0\u5206\u4eab\u8ba1\u6570\nfunction updateShareCount(platform) {\n const countElement = document.querySelector(\n `.share-count[data-platform=\"${platform}\"]`\n );\n if (countElement) {\n const stats = JSON.parse(localStorage.getItem('share_stats') || '{}');\n countElement.textContent = stats[platform] || 0;\n }\n}\n
"},{"location":"Tools/Blog/Mkdocs_Material/#94","title":"9.4 \u7ad9\u5185\u641c\u7d22","text":""},{"location":"Tools/Blog/Mkdocs_Material/#941","title":"9.4.1 \u641c\u7d22\u4f18\u5316","text":"plugins:\n - search:\n lang:\n - en\n - zh\n separator: '[\\s\\-\\.,!\\?\uff0c\u3002\uff01\uff1f]+' # \u5206\u8bcd\u5206\u9694\u7b26\n prebuild_index: true\n indexing:\n full_sections: true\n headings: true\n content: true\n tags: true\n\n # \u9ad8\u7ea7\u641c\u7d22\u914d\u7f6e\n search_boost: true # \u542f\u7528\u641c\u7d22\u63d0\u5347\n search_threshold: 0.3 # \u641c\u7d22\u9608\u503c\n search_fields: # \u641c\u7d22\u5b57\u6bb5\u6743\u91cd\n title: 10\n tags: 8\n content: 5\n
\u641c\u7d22\u4f18\u5316\u5b9e\u73b0\uff1a
JavaScript// docs/javascripts/search-enhance.js\nclass SearchEnhancer {\n constructor() {\n this.searchIndex = null;\n this.searchResults = [];\n this.searchHistory = [];\n this.maxHistoryItems = 10;\n\n this.init();\n }\n\n async init() {\n // \u52a0\u8f7d\u641c\u7d22\u7d22\u5f15\n await this.loadSearchIndex();\n // \u52a0\u8f7d\u641c\u7d22\u5386\u53f2\n this.loadSearchHistory();\n // \u521d\u59cb\u5316\u641c\u7d22\u7ec4\u4ef6\n this.setupSearch();\n }\n\n async loadSearchIndex() {\n try {\n const response = await fetch('/search/search_index.json');\n const data = await response.json();\n\n // \u4f7f\u7528 Lunr.js \u6784\u5efa\u7d22\u5f15\n this.searchIndex = lunr(function() {\n this.use(lunr.multiLanguage('en', 'zh'));\n\n this.ref('location');\n this.field('title', { boost: 10 });\n this.field('tags', { boost: 8 });\n this.field('text', { boost: 5 });\n\n data.docs.forEach(function(doc) {\n this.add(doc);\n }, this);\n });\n } catch (error) {\n console.error('Failed to load search index:', error);\n }\n }\n\n setupSearch() {\n const searchInput = document.querySelector('.md-search__input');\n if (!searchInput) return;\n\n // \u9632\u6296\u5904\u7406\n searchInput.addEventListener('input', debounce((e) => {\n const query = e.target.value;\n if (query.length >= 2) {\n this.performSearch(query);\n } else {\n this.clearResults();\n }\n }, 200));\n\n // \u641c\u7d22\u5386\u53f2\n searchInput.addEventListener('focus', () => {\n this.showSearchHistory();\n });\n }\n\n performSearch(query) {\n if (!this.searchIndex) return;\n\n try {\n // \u6267\u884c\u641c\u7d22\n this.searchResults = this.searchIndex.search(query);\n\n // \u7ed3\u679c\u540e\u5904\u7406\n this.searchResults = this.postProcessResults(this.searchResults, query);\n\n // \u663e\u793a\u7ed3\u679c\n this.displayResults(this.searchResults);\n\n // \u663e\u793a\u641c\u7d22\u5efa\u8bae\n this.showSearchSuggestions(query);\n } catch (error) {\n console.error('Search failed:', error);\n }\n }\n\n postProcessResults(results, query) {\n return results\n .map(result => {\n // \u8ba1\u7b97\u76f8\u5173\u5ea6\u5206\u6570\n const score = this.calculateRelevanceScore(result, query);\n\n return {\n ...result,\n score: score,\n highlights: this.generateHighlights(result, query)\n };\n })\n // \u6309\u5206\u6570\u6392\u5e8f\n .sort((a, b) => b.score - a.score)\n // \u9650\u5236\u7ed3\u679c\u6570\u91cf\n .slice(0, 10);\n }\n\n calculateRelevanceScore(result, query) {\n let score = result.score;\n\n // \u6807\u9898\u5339\u914d\u52a0\u5206\n if (result.title?.toLowerCase().includes(query.toLowerCase())) {\n score *= 1.5;\n }\n\n // \u6807\u7b7e\u5339\u914d\u52a0\u5206\n if (result.tags?.some(tag => \n tag.toLowerCase().includes(query.toLowerCase())\n )) {\n score *= 1.2;\n }\n\n return score;\n }\n\n generateHighlights(result, query) {\n const text = result.text || '';\n const words = query.toLowerCase().split(/\\s+/);\n const context = 50; // \u4e0a\u4e0b\u6587\u957f\u5ea6\n\n let highlights = [];\n\n words.forEach(word => {\n let index = text.toLowerCase().indexOf(word);\n while (index > -1) {\n const start = Math.max(0, index - context);\n const end = Math.min(text.length, index + word.length + context);\n const highlight = text.slice(start, end);\n\n highlights.push({\n text: highlight,\n position: start\n });\n\n index = text.toLowerCase().indexOf(word, index + 1);\n }\n });\n\n // \u5408\u5e76\u91cd\u53e0\u7684\u9ad8\u4eae\u7247\u6bb5\n return this.mergeHighlights(highlights);\n }\n\n mergeHighlights(highlights) {\n if (highlights.length === 0) return [];\n\n highlights.sort((a, b) => a.position - b.position);\n\n let merged = [highlights[0]];\n for (let i = 1; i < highlights.length; i++) {\n let current = highlights[i];\n let last = merged[merged.length - 1];\n\n if (current.position <= last.position + last.text.length) {\n // \u5408\u5e76\u91cd\u53e0\u7684\u7247\u6bb5\n last.text = last.text.slice(0, current.position - last.position) +\n current.text;\n } else {\n merged.push(current);\n }\n }\n\n return merged;\n }\n\n loadSearchHistory() {\n try {\n this.searchHistory = JSON.parse(\n localStorage.getItem('search_history')\n ) || [];\n } catch (error) {\n this.searchHistory = [];\n }\n }\n\n saveSearchHistory(query) {\n if (!query) return;\n\n // \u79fb\u9664\u91cd\u590d\u9879\n this.searchHistory = this.searchHistory.filter(item => \n item.query !== query\n );\n\n // \u6dfb\u52a0\u65b0\u9879\n this.searchHistory.unshift({\n query: query,\n timestamp: Date.now()\n });\n\n // \u9650\u5236\u5386\u53f2\u8bb0\u5f55\u6570\u91cf\n if (this.searchHistory.length > this.maxHistoryItems) {\n this.searchHistory.pop();\n }\n\n // \u4fdd\u5b58\u5230\u672c\u5730\u5b58\u50a8\n localStorage.setItem(\n 'search_history',\n JSON.stringify(this.searchHistory)\n );\n }\n\n showSearchHistory() {\n const container = document.querySelector('.md-search__history');\n if (!container) return;\n\n // \u6e05\u7a7a\u5bb9\u5668\n container.innerHTML = '';\n\n // \u663e\u793a\u5386\u53f2\u8bb0\u5f55\n this.searchHistory.forEach(item => {\n const element = document.createElement('div');\n element.className = 'search-history-item';\n element.innerHTML = `\n <span class=\"history-icon\">\n {% include \".icons/material/history.svg\" %}\n </span>\n <span class=\"history-query\">${item.query}</span>\n <span class=\"history-time\">\n ${this.formatTime(item.timestamp)}\n </span>\n `;\n\n element.addEventListener('click', () => {\n const searchInput = document.querySelector('.md-search__input');\n if (searchInput) {\n searchInput.value = item.query;\n searchInput.dispatchEvent(new Event('input'));\n }\n });\n\n container.appendChild(element);\n });\n }\n\n formatTime(timestamp) {\n const now = Date.now();\n const diff = now - timestamp;\n\n if (diff < 60000) return '\u521a\u521a';\n if (diff < 3600000) return `${Math.floor(diff/60000)}\u5206\u949f\u524d`;\n if (diff < 86400000) return `${Math.floor(diff/3600000)}\u5c0f\u65f6\u524d`;\n return `${Math.floor(diff/86400000)}\u5929\u524d`;\n }\n}\n\n// \u521d\u59cb\u5316\u641c\u7d22\u589e\u5f3a\nnew SearchEnhancer();\n
\u641c\u7d22\u76f8\u5173\u6837\u5f0f\uff1a
CSS/* docs/stylesheets/search.css */\n/* \u641c\u7d22\u5386\u53f2 */\n.search-history-item {\n display: flex;\n align-items: center;\n padding: 0.5rem 1rem;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.search-history-item:hover {\n background: var(--md-code-bg-color);\n}\n\n.history-icon {\n margin-right: 0.5rem;\n color: var(--md-default-fg-color--light);\n}\n\n.history-query {\n flex: 1;\n font-weight: 500;\n}\n\n.history-time {\n font-size: 0.8rem;\n color: var(--md-default-fg-color--light);\n}\n\n/* \u641c\u7d22\u5efa\u8bae */\n.search-suggestions {\n padding: 1rem;\n}\n\n.suggestion-item {\n padding: 0.5rem;\n border-radius: 4px;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.suggestion-item:hover {\n background: var(--md-code-bg-color);\n}\n\n/* \u9ad8\u4eae\u6587\u672c */\n.search-highlight {\n background: var(--md-accent-fg-color);\n color: white;\n padding: 0 0.2rem;\n border-radius: 2px;\n}\n\n/* \u641c\u7d22\u7ed3\u679c */\n.search-result {\n padding: 1rem;\n border-bottom: 1px solid var(--md-default-fg-color--lightest);\n}\n\n.result-title {\n font-size: 1.1rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n}\n\n.result-excerpt {\n font-size: 0.9rem;\n color: var(--md-default-fg-color--light);\n margin-bottom: 0.5rem;\n}\n\n.result-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.8rem;\n color: var(--md-default-fg-color--lighter);\n}\n
\u4f7f\u7528\u8fd9\u4e9b\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e2a\u529f\u80fd\u5b8c\u5584\u7684\u641c\u7d22\u7cfb\u7edf\uff0c\u5305\u62ec\uff1a
\u8bb0\u5f97\u5728 mkdocs.yml
\u4e2d\u6dfb\u52a0\u76f8\u5e94\u7684\u5f15\u7528\uff1a
extra_css:\n - stylesheets/search.css\n\nextra_javascript:\n - https://unpkg.com/lunr/lunr.js\n - https://unpkg.com/lunr-languages/lunr.stemmer.support.js\n - https://unpkg.com/lunr-languages/lunr.zh.js\n - javascripts/search-enhance.js\n
"},{"location":"Tools/Blog/Mkdocs_Material/#10","title":"10 \u90e8\u7f72\u65b9\u6848","text":""},{"location":"Tools/Blog/Mkdocs_Material/#101","title":"10.1 \u672c\u5730\u90e8\u7f72","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1011","title":"10.1.1 \u6784\u5efa\u9759\u6001\u6587\u4ef6","text":"\u4f7f\u7528 MkDocs \u6784\u5efa\u9759\u6001\u6587\u4ef6\uff1a
Bash# \u6784\u5efa\u7ad9\u70b9\nmkdocs build\n\n# \u6307\u5b9a\u8f93\u51fa\u76ee\u5f55\nmkdocs build -d custom_site_dir\n\n# \u6e05\u7406\u5e76\u6784\u5efa\nmkdocs build --clean\n
\u6784\u5efa\u9009\u9879\u8bf4\u660e\uff1a
YAML# mkdocs.yml\nsite_dir: site # \u8f93\u51fa\u76ee\u5f55\ndocs_dir: docs # \u6587\u6863\u6e90\u76ee\u5f55\nstrict: true # \u4e25\u683c\u6a21\u5f0f\nuse_directory_urls: true # \u4f7f\u7528\u76ee\u5f55 URL\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1012","title":"10.1.2 \u672c\u5730\u670d\u52a1\u5668","text":"\u5f00\u53d1\u670d\u52a1\u5668\u914d\u7f6e\uff1a
Bash# \u542f\u52a8\u5f00\u53d1\u670d\u52a1\u5668\nmkdocs serve\n\n# \u6307\u5b9a\u7aef\u53e3\nmkdocs serve -a localhost:8080\n\n# \u81ea\u52a8\u91cd\u8f7d\nmkdocs serve --dirtyreload\n
\u5f00\u53d1\u670d\u52a1\u5668\u9ad8\u7ea7\u914d\u7f6e\uff1a
YAML# mkdocs.yml\ndev_addr: 127.0.0.1:8000 # \u5f00\u53d1\u670d\u52a1\u5668\u5730\u5740\nwatch: [docs, includes] # \u76d1\u89c6\u7684\u76ee\u5f55\n
"},{"location":"Tools/Blog/Mkdocs_Material/#102-github-pages","title":"10.2 GitHub Pages \u90e8\u7f72","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1021","title":"10.2.1 \u4ed3\u5e93\u914d\u7f6e","text":"\u521b\u5efa GitHub \u4ed3\u5e93\uff1a - \u521b\u5efa\u65b0\u4ed3\u5e93\u6216\u4f7f\u7528\u73b0\u6709\u4ed3\u5e93 - \u4ed3\u5e93\u540d\u683c\u5f0f\uff1a username.github.io
\u6216\u666e\u901a\u4ed3\u5e93\u540d
\u914d\u7f6e\u6587\u4ef6\uff1a
# mkdocs.yml\nsite_url: https://username.github.io/repository/\nrepo_url: https://github.com/username/repository\nedit_uri: edit/main/docs/\n
# \u521d\u59cb\u5316 Git \u4ed3\u5e93\ngit init\n\n# \u6dfb\u52a0\u8fdc\u7a0b\u4ed3\u5e93\ngit remote add origin https://github.com/username/repository.git\n\n# \u63d0\u4ea4\u521d\u59cb\u6587\u4ef6\ngit add .\ngit commit -m \"Initial commit\"\ngit push -u origin main\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1022-github-actions","title":"10.2.2 GitHub Actions","text":"\u521b\u5efa GitHub Actions \u5de5\u4f5c\u6d41\u6587\u4ef6\uff1a
YAML# .github/workflows/ci.yml\nname: ci \non:\n push:\n branches: \n - main\npermissions:\n contents: write\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Configure Git Credentials\n run: |\n git config user.name github-actions[bot]\n git config user.email 41898282+github-actions[bot]@users.noreply.github.com\n - uses: actions/setup-python@v4\n with:\n python-version: 3.x\n - run: echo \"cache_id=$(date --utc '+%V')\" >> $GITHUB_ENV \n - uses: actions/cache@v3\n with:\n key: mkdocs-material-${{ env.cache_id }}\n path: .cache\n restore-keys: |\n mkdocs-material-\n - name: Install dependencies\n run: |\n pip install mkdocs-material\n pip install mkdocs-glightbox\n pip install mkdocs-git-revision-date-localized-plugin\n - name: Deploy\n run: mkdocs gh-deploy --force\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1023","title":"10.2.3 \u81ea\u52a8\u90e8\u7f72","text":"\u914d\u7f6e\u81ea\u52a8\u90e8\u7f72\uff1a
\u542f\u7528 GitHub Pages\uff1a - \u8fdb\u5165\u4ed3\u5e93\u8bbe\u7f6e -> Pages - Source \u9009\u62e9 gh-pages
\u5206\u652f - \u4fdd\u5b58\u8bbe\u7f6e
\u914d\u7f6e\u90e8\u7f72\u5206\u652f\uff1a
# mkdocs.yml\nremote_branch: gh-pages # GitHub Pages \u5206\u652f\nremote_name: origin # \u8fdc\u7a0b\u4ed3\u5e93\u540d\n
# \u90e8\u7f72\u5230 GitHub Pages\nmkdocs gh-deploy\n\n# \u5f3a\u5236\u90e8\u7f72\nmkdocs gh-deploy --force\n\n# \u6307\u5b9a\u5206\u652f\nmkdocs gh-deploy --remote-branch custom-branch\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1024","title":"10.2.4 \u81ea\u5b9a\u4e49\u57df\u540d","text":"# docs/CNAME\ndocs.example.com\n
DNS \u914d\u7f6e\uff1a - \u6dfb\u52a0 CNAME \u8bb0\u5f55\u6307\u5411 username.github.io
- \u6216\u6dfb\u52a0 A \u8bb0\u5f55\u6307\u5411 GitHub Pages IP
\u914d\u7f6e\u6587\u4ef6\u66f4\u65b0\uff1a
# mkdocs.yml\nsite_url: https://docs.example.com/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#103","title":"10.3 \u6301\u7eed\u96c6\u6210","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1031-cicd","title":"10.3.1 CI/CD \u914d\u7f6e","text":"\u9ad8\u7ea7 GitHub Actions \u914d\u7f6e\uff1a
YAMLname: CI/CD Pipeline\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Set up Python\n uses: actions/setup-python@v4\n with:\n python-version: 3.x\n\n - name: Cache dependencies\n uses: actions/cache@v3\n with:\n path: ~/.cache/pip\n key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n restore-keys: |\n ${{ runner.os }}-pip-\n\n - name: Install dependencies\n run: |\n python -m pip install --upgrade pip\n pip install -r requirements.txt\n\n - name: Run tests\n run: |\n mkdocs build --strict\n\n deploy:\n needs: test\n if: github.ref == 'refs/heads/main'\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Deploy to GitHub Pages\n run: |\n mkdocs gh-deploy --force\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1032","title":"10.3.2 \u81ea\u52a8\u5316\u6d4b\u8bd5","text":"name: Link Check\non:\n schedule:\n - cron: '0 0 * * *' # \u6bcf\u5929\u8fd0\u884c\njobs:\n linkCheck:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Link Checker\n uses: lycheeverse/lychee-action@v1.8.0\n with:\n args: --verbose --no-progress 'docs/**/*.md'\n
name: HTML Validation\njobs:\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Build site\n run: mkdocs build\n - name: Validate HTML\n uses: Cyb3r-Jak3/html5validator-action@v7.2.0\n with:\n root: site/\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1033","title":"10.3.3 \u90e8\u7f72\u7b56\u7565","text":"# \u4fdd\u62a4\u5206\u652f\u8bbe\u7f6e\nbranches:\n - name: main\n protection:\n required_status_checks:\n strict: true\n contexts: ['test', 'build']\n required_pull_request_reviews:\n required_approving_review_count: 1\n
# \u73af\u5883\u53d8\u91cf\u8bbe\u7f6e\nenv:\n production:\n url: https://docs.example.com\n branch: main\n staging:\n url: https://staging.docs.example.com\n branch: staging\n
name: Deployment\non:\n push:\n branches: [main, staging]\njobs:\n deploy:\n runs-on: ubuntu-latest\n environment:\n name: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}\n steps:\n - uses: actions/checkout@v4\n\n - name: Build and Deploy\n env:\n DEPLOY_URL: ${{ github.ref == 'refs/heads/main' && env.production.url || env.staging.url }}\n run: |\n mkdocs build\n # \u90e8\u7f72\u5230\u76f8\u5e94\u73af\u5883\n
"},{"location":"Tools/Blog/Mkdocs_Material/#11","title":"11 \u9644\u5f55","text":""},{"location":"Tools/Blog/Mkdocs_Material/#111-a","title":"11.1 A. \u5e38\u7528\u914d\u7f6e\u793a\u4f8b","text":""},{"location":"Tools/Blog/Mkdocs_Material/#1111-a1-mkdocs-yml","title":"11.1.1 A.1 mkdocs. yml \u5b8c\u6574\u793a\u4f8b","text":"YAML# \u7ad9\u70b9\u57fa\u672c\u4fe1\u606f\u914d\u7f6e\nsite_name: \u9879\u76ee\u6587\u6863 # \u7ad9\u70b9\u540d\u79f0\nsite_url: https://example.com # \u7ad9\u70b9URL\nsite_author: \u4f5c\u8005\u540d\u79f0 # \u4f5c\u8005\u4fe1\u606f\nsite_description: >- # \u7ad9\u70b9\u63cf\u8ff0\n \u8fd9\u662f\u4e00\u4e2a\u5b8c\u6574\u7684\u6587\u6863\u793a\u4f8b\uff0c\u5305\u542b\u4e86MkDocs Material\u4e3b\u9898\u7684\u6240\u6709\u4e3b\u8981\u529f\u80fd\u914d\u7f6e\u3002\n\n# \u4ee3\u7801\u4ed3\u5e93\u4fe1\u606f\nrepo_name: username/repo # \u4ed3\u5e93\u540d\u79f0\nrepo_url: https://github.com/username/repo # \u4ed3\u5e93\u5730\u5740\nedit_uri: edit/main/docs/ # \u7f16\u8f91\u94fe\u63a5\n\n# \u7248\u6743\u4fe1\u606f\ncopyright: Copyright © 2024 # \u7248\u6743\u58f0\u660e\n\n# \u4e3b\u9898\u914d\u7f6e\ntheme:\n name: material # \u4f7f\u7528Material\u4e3b\u9898\n custom_dir: overrides # \u81ea\u5b9a\u4e49\u76ee\u5f55\n\n # \u4e3b\u9898\u7279\u6027\u914d\u7f6e\n features:\n # \u5bfc\u822a\u76f8\u5173\n - navigation.tabs # \u9876\u90e8\u6807\u7b7e\u5bfc\u822a\n - navigation.sections # \u4fa7\u8fb9\u680f\u5206\u7ec4\n - navigation.expand # \u9ed8\u8ba4\u5c55\u5f00\u5bfc\u822a\n - navigation.indexes # \u5bfc\u822a\u7d22\u5f15\u9875\n - navigation.top # \u8fd4\u56de\u9876\u90e8\u6309\u94ae\n - navigation.footer # \u4e0a\u4e00\u9875/\u4e0b\u4e00\u9875\u5bfc\u822a\n\n # \u641c\u7d22\u76f8\u5173\n - search.suggest # \u641c\u7d22\u5efa\u8bae\n - search.highlight # \u641c\u7d22\u9ad8\u4eae\n - search.share # \u641c\u7d22\u5206\u4eab\n\n # \u4ee3\u7801\u76f8\u5173\n - content.code.annotate # \u4ee3\u7801\u6ce8\u91ca\n - content.code.copy # \u4ee3\u7801\u590d\u5236\n\n # \u5176\u4ed6\u529f\u80fd\n - announce.dismiss # \u53ef\u5173\u95ed\u516c\u544a\n - header.autohide # \u81ea\u52a8\u9690\u85cf\u5934\u90e8\n\n # \u914d\u8272\u65b9\u6848\n palette:\n # \u4eae\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: light)\"\n scheme: default\n primary: indigo # \u4e3b\u8272\n accent: indigo # \u5f3a\u8c03\u8272\n toggle:\n icon: material/brightness-7\n name: \u5207\u6362\u81f3\u6697\u8272\u6a21\u5f0f\n\n # \u6697\u8272\u4e3b\u9898\n - media: \"(prefers-color-scheme: dark)\"\n scheme: slate\n primary: indigo\n accent: indigo\n toggle:\n icon: material/brightness-4\n name: \u5207\u6362\u81f3\u4eae\u8272\u6a21\u5f0f\n\n # \u56fe\u6807\u548c\u5b57\u4f53\n icon:\n logo: material/book-open-page-variant # Logo\u56fe\u6807\n repo: fontawesome/brands/github # \u4ed3\u5e93\u56fe\u6807\n\n font:\n text: Roboto # \u6b63\u6587\u5b57\u4f53\n code: Roboto Mono # \u4ee3\u7801\u5b57\u4f53\n\n language: zh # \u754c\u9762\u8bed\u8a00\n\n# \u6269\u5c55\u914d\u7f6e\nmarkdown_extensions:\n # \u5185\u7f6e\u6269\u5c55\n - toc: # \u76ee\u5f55\n permalink: true # \u6c38\u4e45\u94fe\u63a5\n toc_depth: 3 # \u76ee\u5f55\u6df1\u5ea6\n - tables # \u8868\u683c\u652f\u6301\n - attr_list # \u5c5e\u6027\u5217\u8868\n - def_list # \u5b9a\u4e49\u5217\u8868\n - footnotes # \u811a\u6ce8\n - abbr # \u7f29\u5199\n\n # PyMdown Extensions\n - pymdownx.highlight: # \u4ee3\u7801\u9ad8\u4eae\n anchor_linenums: true\n line_spans: __span\n pygments_lang_class: true\n - pymdownx.inlinehilite # \u884c\u5185\u4ee3\u7801\u9ad8\u4eae\n - pymdownx.snippets # \u4ee3\u7801\u7247\u6bb5\n - pymdownx.superfences: # \u8d85\u7ea7\u56f4\u680f\n custom_fences:\n - name: mermaid\n class: mermaid\n format: !!python/name:pymdownx.superfences.fence_code_format\n - pymdownx.tabbed: # \u6807\u7b7e\u9875\n alternate_style: true\n - pymdownx.tasklist: # \u4efb\u52a1\u5217\u8868\n custom_checkbox: true\n - pymdownx.emoji: # \u8868\u60c5\u652f\u6301\n emoji_index: !!python/name:material.extensions.emoji.twemoji\n emoji_generator: !!python/name:material.extensions.emoji.to_svg\n - pymdownx.details # \u8be6\u7ec6\u4fe1\u606f\n - pymdownx.caret # \u4e0a\u6807\n - pymdownx.mark # \u6807\u8bb0\n - pymdownx.tilde # \u4e0b\u6807\n - pymdownx.keys # \u952e\u76d8\u6309\u952e\n\n# \u63d2\u4ef6\u914d\u7f6e\nplugins:\n - search: # \u641c\u7d22\u63d2\u4ef6\n lang: \n - en\n - zh\n separator: '[\\s\\-\\.,!\\?\uff0c\u3002\uff01\uff1f]+'\n prebuild_index: true\n\n - git-revision-date-localized: # Git\u65e5\u671f\u63d2\u4ef6\n enable_creation_date: true\n type: datetime\n\n - minify: # \u8d44\u6e90\u538b\u7f29\n minify_html: true\n minify_js: true\n minify_css: true\n htmlmin_opts:\n remove_comments: true\n\n - social: # \u793e\u4ea4\u5206\u4eab\n cards: true\n cards_color:\n fill: \"#0FF1CE\"\n text: \"#FFFFFF\"\n\n - tags: # \u6807\u7b7e\u7cfb\u7edf\n tags_file: tags.md\n\n - statistics: # \u7edf\u8ba1\n page_check: true\n page_count: true\n\n# \u9644\u52a0\u914d\u7f6e\nextra:\n # \u793e\u4ea4\u94fe\u63a5\n social:\n - icon: fontawesome/brands/github\n link: https://github.com/username\n - icon: fontawesome/brands/twitter\n link: https://twitter.com/username\n\n # \u8bc4\u8bba\u7cfb\u7edf\n comments:\n provider: giscus\n repo: username/repo\n repo_id: your_repo_id\n category: Comments\n category_id: your_category_id\n\n # \u5206\u6790\u7edf\u8ba1\n analytics:\n provider: google\n property: G-XXXXXXXXXX\n feedback:\n title: \u8fd9\u7bc7\u6587\u6863\u5bf9\u60a8\u6709\u5e2e\u52a9\u5417\uff1f\n ratings:\n - icon: material/thumb-up-outline\n name: \u6709\u5e2e\u52a9\n data: 1\n note: >-\n \u611f\u8c22\u60a8\u7684\u53cd\u9988\uff01\n - icon: material/thumb-down-outline\n name: \u6ca1\u5e2e\u52a9\n data: 0\n note: >- \n \u611f\u8c22\u60a8\u7684\u53cd\u9988\uff0c\u8bf7\u544a\u8bc9\u6211\u4eec\u5982\u4f55\u6539\u8fdb\u3002\n\n# \u989d\u5916\u7684CSS\u548cJavaScript\nextra_css:\n - stylesheets/extra.css # \u81ea\u5b9a\u4e49\u6837\u5f0f\n - stylesheets/custom.css # \u81ea\u5b9a\u4e49\u4e3b\u9898\n\nextra_javascript:\n - javascripts/extra.js # \u81ea\u5b9a\u4e49\u811a\u672c\n - https://unpkg.com/mermaid/dist/mermaid.min.js # \u5916\u90e8\u5e93\n
"},{"location":"Tools/Blog/Mkdocs_Material/#1112-a2-github-actions","title":"11.1.2 A.2 GitHub Actions \u5de5\u4f5c\u6d41\u793a\u4f8b","text":"YAML# .github/workflows/deploy.yml\n\nname: Deploy Documentation\non:\n # \u89e6\u53d1\u6761\u4ef6\n push:\n branches:\n - main\n paths:\n - 'docs/**'\n - 'mkdocs.yml'\n - '.github/workflows/deploy.yml'\n pull_request:\n branches:\n - main\n\n # \u5141\u8bb8\u624b\u52a8\u89e6\u53d1\n workflow_dispatch:\n\n# \u73af\u5883\u53d8\u91cf\nenv:\n PYTHON_VERSION: '3.10'\n DEPLOY_BRANCH: gh-pages\n\n# \u4efb\u52a1\u5b9a\u4e49\njobs:\n build:\n name: Build and Deploy Documentation\n runs-on: ubuntu-latest\n\n steps:\n # \u68c0\u51fa\u4ee3\u7801\n - name: Checkout Repository\n uses: actions/checkout@v3\n with:\n fetch-depth: 0 # \u83b7\u53d6\u5b8c\u6574\u7684git\u5386\u53f2\u7528\u4e8e\u6700\u8fd1\u66f4\u65b0\u65f6\u95f4\n\n # \u8bbe\u7f6ePython\u73af\u5883\n - name: Setup Python\n uses: actions/setup-python@v4\n with:\n python-version: ${{ env.PYTHON_VERSION }}\n cache: pip\n\n # \u7f13\u5b58\u4f9d\u8d56\n - name: Cache Dependencies\n uses: actions/cache@v3\n with:\n path: ~/.cache/pip\n key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}\n restore-keys: |\n ${{ runner.os }}-pip-\n\n # \u5b89\u88c5\u4f9d\u8d56\n - name: Install Dependencies\n run: |\n python -m pip install --upgrade pip\n pip install -r requirements.txt\n\n # \u914d\u7f6eGit\n - name: Configure Git\n run: |\n git config --global user.name \"${{ github.actor }}\"\n git config --global user.email \"${{ github.actor }}@users.noreply.github.com\"\n\n # \u6784\u5efa\u6587\u6863\n - name: Build Documentation\n run: |\n mkdocs build --clean --verbose\n\n # \u4f18\u5316\u8d44\u6e90\n - name: Optimize Assets\n run: |\n # \u538b\u7f29\u56fe\u7247\n find site/ -type f -name \"*.png\" -exec optipng -o5 {} \\;\n find site/ -type f -name \"*.jpg\" -exec jpegoptim --strip-all {} \\;\n\n # \u538b\u7f29JavaScript\u548cCSS\n find site/ -type f -name \"*.js\" -exec uglifyjs {} -o {} \\;\n find site/ -type f -name \"*.css\" -exec cleancss -o {} {} \\;\n\n # \u90e8\u7f72\u5230GitHub Pages\n - name: Deploy to GitHub Pages\n if: github.ref == 'refs/heads/main' # \u53ea\u5728main\u5206\u652f\u90e8\u7f72\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.GITHUB_TOKEN }}\n publish_dir: ./site\n publish_branch: ${{ env.DEPLOY_BRANCH }}\n user_name: 'github-actions[bot]'\n user_email: 'github-actions[bot]@users.noreply.github.com'\n commit_message: ${{ github.event.head_commit.message }}\n full_commit_message: |\n Deploy Documentation\n\n Commit: ${{ github.sha }}\n Workflow: ${{ github.workflow }}\n\n ${{ github.event.head_commit.message }}\n\n # \u90e8\u7f72\u5b8c\u6210\u901a\u77e5\n - name: Deployment Status\n if: always()\n uses: actions/github-script@v6\n with:\n script: |\n const { owner, repo } = context.repo;\n const run_id = context.runId;\n const run_url = `https://github.com/${owner}/${repo}/actions/runs/${run_id}`;\n\n if (context.job.status === 'success') {\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body: `\u2705 Documentation deployed successfully!\\nPreview: https://${owner}.github.io/${repo}/\\nWorkflow: ${run_url}`\n });\n } else {\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body: `\u274c Documentation deployment failed.\\nSee details: ${run_url}`\n });\n }\n\n# \u9519\u8bef\u8ffd\u8e2a\u548c\u62a5\u544a\n - name: Report Errors\n if: failure()\n uses: actions/github-script@v6\n with:\n script: |\n const { owner, repo } = context.repo;\n const run_id = context.runId;\n\n await github.rest.issues.create({\n owner,\n repo,\n title: `\ud83d\udd34 Documentation deployment failed - ${new Date().toISOString()}`,\n body: `Deployment failed for commit: ${context.sha}\\n\\nSee workflow run: https://github.com/${owner}/${repo}/actions/runs/${run_id}\\n\\nPlease check the logs for more details.`,\n labels: ['deployment', 'bug']\n });\n
"},{"location":"Tools/Environment/Ubuntu_setup/","title":"Ubuntu \u914d\u7f6e","text":""},{"location":"Tools/Environment/Ubuntu_setup/#ubuntu","title":"Ubuntu \u914d\u7f6e","text":"\u7ea6 77 \u4e2a\u5b57 14 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
visudo /etc/sudoers \n%sudo ALL=(ALL:ALL) NOPASSWD: ALL\n
Bashgit clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting\n\ngit clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions\n\ngit clone git://github.com/joelthelion/autojump.git\ncd autojump\n./install.py\n\n[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] && . ~/.autojump/etc/profile.d/autojump.sh\n
sudo apt-get install flameshot\nflameshot gui\n
\u7ea6 227 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u7ea6 1281 \u4e2a\u5b57 55 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 7 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Environment
#Obsidian
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#obsidian","title":"obsidian \u914d\u7f6e","text":"Note \u5982\u679c\u61d2\u5f97\u641e\uff0c\u53ef\u4ee5\u76f4\u63a5 clone \u6211\u7684\u914d\u7f6e\uff0c\u653e\u5230 .obsidian \u6587\u4ef6\u91cc\u3002 \u8fd9\u662f\u914d\u7f6e\u6587\u4ef6\u3002
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#1","title":"1 \u4f7f\u7528\u8bed\u8a00","text":"mk
\u5c31\u53ef\u4ee5\u81ea\u52a8\u66ff\u6362\u4e3a $\\displaystyle $
\u5982\u679c\u4f60\u7684 \\(\\displaystyle \\LaTeX\\) \u4e66\u5199\u901f\u5ea6\u6bd4\u8f83\u6162\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u4f7f\u7528 ocr \u8f6f\u4ef6\uff0c\u6bd4\u5982 simpleTex\uff0c\u4f46\u662f\u8fd9\u4e2a\u53ea\u6709 Windows \u5e73\u53f0\u652f\u6301\u3002\u5bf9\u4e8e Linux\uff0c\u6211\u6682\u65f6\u8fd8\u6ca1\u6709\u6bd4\u8f83\u597d\u7684\u8f6f\u4ef6\u3002
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#22","title":"2.2 \u7f16\u8f91\u589e\u5f3a","text":"\u5bf9\u4e8e\u56fe\u7247\uff0c\u4e00\u822c\u6709\u4e24\u79cd\u65b9\u6848\uff1a
\"obsidian-auto-link-title\",\n\"obsidian-latex-suite\",\n\"number-headings-obsidian\",\n\"mathlinks\",\n\"obsidian-outliner\",\n\"obsidian-completr\",\n\"calendar\",\n\"periodic-notes\",\n\"obsidian-wakatime\",\n\"obsidian-image-auto-upload-plugin\",\n\"obsidian-paste-image-rename\",\n\"dataview\",\n\"obsidian-export-image\",\n\"obsidian-day-planner\",\n\"templater-obsidian\",\n\"obsidian-git\",\n\"easy-typing-obsidian\",\n\"obsidian-linter\",\n\"obsidian-style-settings\",\n\"obsidian-image-toolkit\",\n\"tag-wrangler\",\n\"obsidian-tagfolder\"\n
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#_1","title":"\u6211\u7684\u6a21\u677f","text":"\u9700\u8981\u5b89\u88c5 dataview + periodic notes \u63d2\u4ef6\u3002
Note
\u7531\u4e8e markdown \u4ee3\u7801\u5757\u5d4c\u5957\u4e0d\u592a\u884c\uff0c\u6240\u4ee5\u8981\u624b\u52a8\u4fee\u590d\u3002\u6ce8\u610f\u4fee\u590d '' \u5e26\u6765\u7684\u4ee3\u7801\u5757\u95ee\u9898, \u8bb0\u5f97\u8865\u5168\u3002
dailyweekly Note Text Only---\ntitle: \"{{date}}\"\ntags:\n - \" #\u65e5\u8bb0 \"\ncategories: dairy\ndate: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\nmodify: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\ndir: dairy\nshare: false\ncdate: \" {{ date:YYYY-MM-DD }} \"\nmdate: \" {{ date:YYYY-MM-DD }} \"\n---\n\n# {{date}}\n\n## Daily Plan\n\n### Morning\n\n#### Plan\n\n### Afternoon\n\n#### Plan\n\n### Night\n\n#### Plan\n\n## NOTES\n\n```dataview\nLIST FROM \"\" \nWHERE cdate = this.cdate\n Or mdate = this.mdate\n``\n\n## LINKS\n\n## TODOs\n\n```dataview\nTASK FROM \"dairy\"\nWHERE !completed\n AND mdate >= (this.mdate - dur(7 days))\n AND mdate <= this.mdate\nSORT file.cday DESC\n``\n\n## THOUGHTS\n
Note Text Only ---\ntitle: \" {{date}} \"\ntags:\n - \" #\u5468\u8bb0 \"\ncategories: dairy\ndate: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\nmodify: \" {{ date:YYYY-MM-DDTHH:mm:ss+08:00 }} \"\ndir: dairy\nshare: false\ncdate: \" {{ date:YYYY-MM-DD }} \"\nmdate: \" {{ date:YYYY-MM-DD }} \"\n---\n\n# {{date:YYYY}} -W {{date:WW}} - {{date:MM}}\n\n## Review\n\n## Next Week Plan\n\n## Time Line\n\n## THOUGHTS\n\n## LINKS\n\n```dataviewjs\n// Configuration for collecting LINKS sections from daily notes\nconst tars = {\n 'LINKS': 2, // Collect second-level LINKS headings\n}\n\nawait dv.view('zob_config/js/dv-\u68c0\u7d22', {\n // Get only daily notes from dairy folder\n files: dv.pages('\"dairy\"')\n .where(p => {\n // Extract the week number from the current file name (weekly note)\n const weekMatch = dv.current().file.name.match(/(\\d{4})-W(\\d{1,2})/);\n if (!weekMatch) return false;\n\n const [_, weekYear, weekNum] = weekMatch;\n\n // Extract date components from daily note name (2024-49-12-08-7 format)\n const dateMatch = p.file.name.match(/(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})/);\n if (!dateMatch) return false;\n\n const [__, year, week, month, day] = dateMatch;\n\n // Check if the daily note belongs to the same week and year\n return year === weekYear && week === weekNum;\n })\n .sort(p => {\n // Create sortable date string from daily note format\n const [_, year, week, month, day] = p.file.name.match(/^(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})$/);\n // Sort by YYYYMMDD format (descending)\n return -1 * parseInt(`${year}${month.padStart(2, '0')}${day.padStart(2, '0')}`);\n }),\n\n kwd: false, // Don't filter by keywords\n showHead: false, // Don't include heading in output\n tars, // Target sections to collect (LINKS)\n obsidian, // Pass obsidian object\n scale: 0.8, // Scale of rendered content\n\n // List item configuration\n li: ([p, li]) => {\n const [_, year, week, month, day] = p.file.name.match(/^(\\d{4})-(\\d{1,2})-(\\d{2})-(\\d{2})-(\\d{1})$/);\n const formattedDate = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;\n // Create a header with date and file link, followed by the content\n return dv.paragraph(`### ${formattedDate} [[${p.file.path}|${p.file.name}]]\\n${li}`);\n },\n});\n``\n
","tags":["Environment","Obsidian"]},{"location":"Tools/Environment/obsidian_setup/#3","title":"3 \u76f8\u5173\u94fe\u63a5","text":"\u7ea6 161 \u4e2a\u5b57 13 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Make/CMake/#1","title":"1 \u6784\u5efa\u6700\u5c0f\u9879\u76ee","text":"mkdir build\ncd build\ncmake -G\"MinGW Makefiles\" ..\ncmake --build .\n
\u4e4b\u540e\u4f1a\u751f\u6210\u53ef\u6267\u884c\u6587\u4ef6
Text Onlystep1/\n build/\n CMakeLists.txt\n tutorial.cpp\n
"},{"location":"Tools/Make/CMake/#2-cmakelists-txt","title":"2 \u4f18\u5316 CMakeLists. txt \u6587\u4ef6","text":"CMakecmake_minimum_required(VERSION 3.15)\n\n# set the project name\nproject(Tutorial)\n\nSET(SRC_LIST tutorial.cpp)\n\n# add the executable\nadd_executable(${PROJECT_NAME} ${SRC_LIST})\n
1.0.2 \u5206\u522b\u5bf9\u5e94 MAJOR MINOR PATCH
\u7ea6 220 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Make/Makeflie/#make_1","title":"\u4ec0\u4e48\u662f Make","text":"Make \u662f\u4e00\u4e2a\u81ea\u52a8\u5316\u6784\u5efa\u5de5\u5177\uff0c\u4f7f\u7528 Makefile \u6587\u4ef6\u6765\u5b9a\u4e49\u5982\u4f55\u7f16\u8bd1\u548c\u94fe\u63a5\u7a0b\u5e8f\u3002\u5b83\u901a\u8fc7\u68c0\u67e5\u6587\u4ef6\u7684\u65f6\u95f4\u6233\u6765\u51b3\u5b9a\u54ea\u4e9b\u6587\u4ef6\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u3002
"},{"location":"Tools/Make/Makeflie/#makefile","title":"Makefile \u7684\u57fa\u672c\u7ed3\u6784","text":"Makefile \u7684\u57fa\u672c\u7ed3\u6784\u7531\u76ee\u6807\u3001\u4f9d\u8d56\u548c\u547d\u4ee4\u7ec4\u6210\uff0c\u901a\u5e38\u5f62\u5f0f\u4e3a\uff1a
Text Onlytarget: dependencies \n command\n
"},{"location":"Tools/Make/Makeflie/#makefile_1","title":"Makefile \u793a\u4f8b","text":"\u8ba9\u6211\u4eec\u8003\u8651\u4e00\u4e2a\u7b80\u5355\u7684 C \u8bed\u8a00\u9879\u76ee\uff0c\u8be5\u793a\u4f8b\u5c06\u5c55\u793a\u5982\u4f55\u4f7f\u7528 Makefile \u6765\u7f16\u8bd1\u4e00\u4e2a\u5177\u6709\u591a\u4e2a\u6e90\u6587\u4ef6\u548c\u5934\u6587\u4ef6\u7684\u7a0b\u5e8f\uff0c\u5e76\u5c55\u793a Makefile \u76f8\u6bd4\u624b\u52a8\u547d\u4ee4\u884c\u7f16\u8bd1\u7684\u4f18\u52bf\u3002 \u7f16\u8bd1\u8fdb\u9636 - HPC\u5165\u95e8\u6307\u5357
"},{"location":"Tools/Make/Makeflie/#make_2","title":"Make \u7684\u5e38\u7528\u547d\u4ee4","text":"make
\uff1a\u6267\u884c\u9ed8\u8ba4\u76ee\u6807\uff0c\u4e0emake all
\u7b49\u6548\u3002make <target>
\uff1a\u6267\u884c\u5b9a\u4e49\u7684<target>
\u76ee\u6807\uff0c\u5982\u679c\u6ca1\u6709\u8fd9\u4e2a\u76ee\u6807\u5c06\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\u3002make -j
\uff1a\u5e76\u884c\u6267\u884c\u6784\u5efa\uff0c\u4f7f\u7528\u672c\u673a\u7684\u5168\u90e8\u7ebf\u7a0b\u7ea6 512 \u4e2a\u5b57 142 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 4 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
\u672c\u6307\u5357\u5c06\u5e2e\u52a9\u4f60\u4f7f\u7528 chezmoi \u7ba1\u7406\u4f60\u7684\u914d\u7f6e\u6587\u4ef6\uff08dotfiles\uff09\uff0c\u5e76\u4f7f\u7528\u5305\u7ba1\u7406\u5668\u7ef4\u62a4\u8f6f\u4ef6\u5217\u8868\u3002
"},{"location":"Tools/Others/Chezmoi/#_1","title":"\u524d\u671f\u51c6\u5907","text":""},{"location":"Tools/Others/Chezmoi/#1","title":"1. \u9700\u8981\u7684\u5de5\u5177","text":"Windows \u5e38\u7528\u914d\u7f6e\u6587\u4ef6:
Text Only%USERPROFILE%/\n\u251c\u2500\u2500 .gitconfig # Git\u914d\u7f6e\n\u251c\u2500\u2500 .ssh/ # SSH\u914d\u7f6e\n\u251c\u2500\u2500 Documents/\n\u2502 \u2514\u2500\u2500 PowerShell/\n\u2502 \u2514\u2500\u2500 Microsoft.PowerShell_profile.ps1 # PowerShell\u914d\u7f6e\n\u251c\u2500\u2500 AppData/\n\u2502 \u251c\u2500\u2500 Roaming/\n\u2502 \u2502 \u2514\u2500\u2500 Code/\n\u2502 \u2502 \u2514\u2500\u2500 User/\n\u2502 \u2502 \u2514\u2500\u2500 settings.json # VSCode\u914d\u7f6e\n\u2502 \u2514\u2500\u2500 Local/\n\u2514\u2500\u2500 .config/\n \u2514\u2500\u2500 scoop/\n \u2514\u2500\u2500 config.json # Scoop\u914d\u7f6e\n
Ubuntu \u5e38\u7528\u914d\u7f6e\u6587\u4ef6:
Text Only~/\n\u251c\u2500\u2500 .bashrc # Bash\u914d\u7f6e\n\u251c\u2500\u2500 .zshrc # Zsh\u914d\u7f6e\n\u251c\u2500\u2500 .gitconfig # Git\u914d\u7f6e\n\u251c\u2500\u2500 .ssh/ # SSH\u914d\u7f6e\n\u2514\u2500\u2500 .config/\n \u251c\u2500\u2500 Code/\n \u2502 \u2514\u2500\u2500 User/\n \u2502 \u2514\u2500\u2500 settings.json # VSCode\u914d\u7f6e\n \u2514\u2500\u2500 tabby/\n \u2514\u2500\u2500 config.yaml # Tabby\u7ec8\u7aef\u914d\u7f6e\n
"},{"location":"Tools/Others/Chezmoi/#github","title":"GitHub \u8bbe\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1-github","title":"1. \u521b\u5efa GitHub \u4ed3\u5e93","text":"dotfiles
# \u751f\u6210SSH\u5bc6\u94a5\nssh-keygen -t ed25519 -C \"your_email@example.com\"\n\n# \u5c06\u516c\u94a5\u6dfb\u52a0\u5230GitHub\n# 1. \u590d\u5236\u516c\u94a5\u5185\u5bb9\ncat ~/.ssh/id_ed25519.pub\n# 2. \u8bbf\u95ee GitHub \u2192 Settings \u2192 SSH and GPG keys \u2192 New SSH key\n# 3. \u7c98\u8d34\u516c\u94a5\u5185\u5bb9\u5e76\u4fdd\u5b58\n
"},{"location":"Tools/Others/Chezmoi/#windows","title":"Windows \u914d\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1_1","title":"1. \u5b89\u88c5\u5fc5\u8981\u5de5\u5177","text":"\u4f7f\u7528 PowerShell\uff08\u4ee5\u7ba1\u7406\u5458\u8eab\u4efd\u8fd0\u884c\uff09\uff1a
PowerShell# \u5b89\u88c5Scoop\nSet-ExecutionPolicy RemoteSigned -Scope CurrentUser\nirm get.scoop.sh | iex\n\n# \u5b89\u88c5Git\uff08\u5982\u679c\u8fd8\u6ca1\u6709\uff09\nscoop install git\n\n# \u5b89\u88c5chezmoi\nscoop install chezmoi\n
"},{"location":"Tools/Others/Chezmoi/#2-chezmoi","title":"2. \u521d\u59cb\u5316 chezmoi","text":"PowerShell# \u521d\u59cb\u5316chezmoi\u5e76\u514b\u9686\u4f60\u7684\u4ed3\u5e93\nchezmoi init --apply https://github.com/yourusername/dotfiles.git\n# \u7528 ssh \u4e5f\u53ef\u4ee5\n\n# \u67e5\u770bchezmoi\u5c06\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5c06\u73b0\u6709\u914d\u7f6e\u6587\u4ef6\u6dfb\u52a0\u5230chezmoi\nchezmoi add $HOME/.gitconfig\nchezmoi add $HOME/.ssh/config\nchezmoi add $HOME/Documents/PowerShell/Microsoft.PowerShell_profile.ps1\nchezmoi add $HOME/AppData/Roaming/Code/User/settings.json\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Initial Windows config\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#3","title":"3. \u5bfc\u51fa\u8f6f\u4ef6\u5305\u5217\u8868","text":"PowerShell# \u5bfc\u51faScoop\u5305\u5217\u8868\nscoop export > packages/scoop-packages.txt\n\n# \u63d0\u4ea4\u5305\u5217\u8868\nchezmoi cd\ngit add packages/scoop-packages.txt\ngit commit -m \"Add Windows package list\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#ubuntu","title":"Ubuntu \u914d\u7f6e","text":""},{"location":"Tools/Others/Chezmoi/#1_2","title":"1. \u5b89\u88c5\u5fc5\u8981\u5de5\u5177","text":"Bash# \u5b89\u88c5Git\uff08\u5982\u679c\u8fd8\u6ca1\u6709\uff09\nsudo apt update\nsudo apt install git\n\n# \u5b89\u88c5chezmoi\nsh -c \"$(curl -fsLS get.chezmoi.io)\"\n
\u53c2\u8003\u8fd9\u4e2a\u7f51\u7ad9 Install - chezmoi \u8fdb\u884c\u4e0b\u8f7d\uff0c\u6211\u547d\u4ee4\u884c\u4e00\u76f4\u4e0d\u6210\u529f\uff0c\u76f4\u63a5\u9009\u62e9\u5bf9\u5e94\u7684\u5305\u5c31\u884c\u4e86\u3002
Text Onlysudo dpkg -i chezmoi_2.54.0_linux_amd64.deb\nchezmoi --version\n
"},{"location":"Tools/Others/Chezmoi/#2-chezmoi_1","title":"2. \u521d\u59cb\u5316 chezmoi","text":"Bash# \u521d\u59cb\u5316chezmoi\u5e76\u514b\u9686\u4f60\u7684\u4ed3\u5e93\nchezmoi init --apply https://github.com/yourusername/dotfiles.git\n\n# \u67e5\u770bchezmoi\u5c06\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5c06\u73b0\u6709\u914d\u7f6e\u6587\u4ef6\u6dfb\u52a0\u5230chezmoi\nchezmoi add ~/.bashrc\nchezmoi add ~/.zshrc\nchezmoi add ~/.gitconfig\nchezmoi add ~/.ssh/config\nchezmoi add ~/.config/Code/User/settings.json\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Initial Ubuntu config\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#3_1","title":"3. \u5bfc\u51fa\u8f6f\u4ef6\u5305\u5217\u8868","text":"Bashchezmoi cd\nmkdir packages\n# \u5bfc\u51faapt\u5305\u5217\u8868\ndpkg --get-selections | grep -v deinstall | awk '{print $1}' > packages/apt-packages.txt\n\n# \u5bfc\u51fasnap\u5305\u5217\u8868\nsnap list | awk '{if (NR>1) print $1}' > packages/snap-packages.txt\n\n# \u63d0\u4ea4\u5305\u5217\u8868\ngit add packages/apt-packages.txt packages/snap-packages.txt\ngit commit -m \"Add Ubuntu package lists\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#_2","title":"\u65e5\u5e38\u4f7f\u7528","text":""},{"location":"Tools/Others/Chezmoi/#1_3","title":"1. \u66f4\u65b0\u914d\u7f6e","text":"\u5f53\u4f60\u4fee\u6539\u4e86\u914d\u7f6e\u6587\u4ef6\u540e\uff1a
Bash# \u5c06\u66f4\u6539\u6dfb\u52a0\u5230chezmoi\nchezmoi add ~/.bashrc # \u6216\u5176\u4ed6\u4fee\u6539\u7684\u914d\u7f6e\u6587\u4ef6\n\n# \u67e5\u770b\u66f4\u6539\nchezmoi diff\n\n# \u63d0\u4ea4\u5e76\u63a8\u9001\u66f4\u6539\nchezmoi cd\ngit add .\ngit commit -m \"Update bashrc\"\ngit push\n
"},{"location":"Tools/Others/Chezmoi/#2_1","title":"2. \u5728\u5176\u4ed6\u673a\u5668\u4e0a\u540c\u6b65","text":"Bash# \u62c9\u53d6\u5e76\u5e94\u7528\u6700\u65b0\u66f4\u6539\nchezmoi update\n
"},{"location":"Tools/Others/Chezmoi/#3_2","title":"3. \u66f4\u65b0\u8f6f\u4ef6\u5305\u5217\u8868","text":"Windows:
PowerShell# \u66f4\u65b0Scoop\u5305\u5217\u8868\nscoop export > packages/scoop-packages.txt\n
Ubuntu:
Bash# \u66f4\u65b0apt\u5305\u5217\u8868\ndpkg --get-selections | grep -v deinstall | awk '{print $1}' > packages/apt-packages.txt\n\n# \u66f4\u65b0snap\u5305\u5217\u8868\nsnap list | awk '{if (NR>1) print $1}' > packages/snap-packages.txt\n
"},{"location":"Tools/Others/Chezmoi/#4","title":"4. \u5728\u65b0\u673a\u5668\u4e0a\u8bbe\u7f6e","text":"Windows:
PowerShell# \u5b89\u88c5chezmoi\nscoop install chezmoi\n\n# \u521d\u59cb\u5316\u5e76\u5e94\u7528\u914d\u7f6e\nchezmoi init https://github.com/yourusername/dotfiles.git\nchezmoi apply\n
Ubuntu:
Bash# \u5b89\u88c5chezmoi\nsh -c \"$(curl -fsLS get.chezmoi.io)\"\n\n# \u521d\u59cb\u5316\u5e76\u5e94\u7528\u914d\u7f6e\nchezmoi init https://github.com/yourusername/dotfiles.git\nchezmoi apply\n
"},{"location":"Tools/Others/Chezmoi/#_3","title":"\u5e38\u89c1\u95ee\u9898","text":""},{"location":"Tools/Others/Chezmoi/#1_4","title":"1. \u5982\u4f55\u5904\u7406\u4e0d\u540c\u673a\u5668\u7684\u7279\u5b9a\u914d\u7f6e\uff1f","text":"\u4f7f\u7528\u6a21\u677f\u548c\u6761\u4ef6\u8bed\u53e5\u3002\u5728 .chezmoi.toml.tmpl
\u4e2d\uff1a
{{- $osid := .chezmoi.os -}}\n[data]\n name = \"Your Name\"\n email = \"your@email.com\"\n {{- if eq .chezmoi.os \"windows\" }}\n is_windows = true\n {{- else if eq .chezmoi.os \"linux\" }}\n is_linux = true\n {{- end }}\n
"},{"location":"Tools/Others/Chezmoi/#2_2","title":"2. \u5982\u4f55\u5904\u7406\u654f\u611f\u4fe1\u606f\uff1f","text":"\u5bf9\u4e8e\u654f\u611f\u4fe1\u606f\uff0c\u53ef\u4ee5\uff1a
# \u67e5\u770b\u5c06\u8981\u8fdb\u884c\u7684\u66f4\u6539\nchezmoi diff\n\n# \u5982\u679c\u4e0d\u6ee1\u610f\uff0c\u53ef\u4ee5\u64a4\u9500\nchezmoi forget ~/.bashrc # \u79fb\u9664\u6587\u4ef6\u7684\u7ba1\u7406\n\n# \u6216\u8005\u91cd\u7f6e\u4e3a\u539f\u59cb\u72b6\u6001\nchezmoi apply --force\n
"},{"location":"Tools/Others/Chezmoi/#4_1","title":"4. \u914d\u7f6e\u6587\u4ef6\u6743\u9650\u95ee\u9898\uff1f","text":"chezmoi \u4f1a\u81ea\u52a8\u5904\u7406\u6587\u4ef6\u6743\u9650\u3002\u5bf9\u4e8e\u7279\u6b8a\u6743\u9650\u9700\u6c42\uff0c\u53ef\u4ee5\u5728\u6e90\u6587\u4ef6\u540d\u4e2d\u4f7f\u7528\u7279\u6b8a\u524d\u7f00\uff1a
private_
: \u521b\u5efa\u79c1\u6709\u6587\u4ef6 (chmod 600)executable_
: \u521b\u5efa\u53ef\u6267\u884c\u6587\u4ef6 (chmod 700)readonly_
: \u521b\u5efa\u53ea\u8bfb\u6587\u4ef6 (chmod 400)# \u5217\u51fa\u6240\u6709\u7ba1\u7406\u7684\u6587\u4ef6\nchezmoi managed\n\n# \u67e5\u770b\u6e90\u6587\u4ef6\nchezmoi cd\nls -la\n
"},{"location":"Tools/Others/Chezmoi/#6","title":"6. \u66f4\u65b0\u51fa\u9519\u600e\u4e48\u529e\uff1f","text":"Bash# \u5907\u4efd\u5f53\u524d\u72b6\u6001\nchezmoi archive --output=backup.tar.gz\n\n# \u91cd\u7f6e\u66f4\u6539\nchezmoi init --force\n\n# \u91cd\u65b0\u5e94\u7528\u914d\u7f6e\nchezmoi apply\n
"},{"location":"Tools/Others/SSH/","title":"SSH\u914d\u7f6e\u6307\u5357","text":""},{"location":"Tools/Others/SSH/#ssh","title":"SSH\u914d\u7f6e\u6307\u5357","text":"\u7ea6 641 \u4e2a\u5b57 195 \u884c\u4ee3\u7801 1 \u5f20\u56fe\u7247 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 6 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Others/SSH/#ssh_1","title":"\u4e00\u3001SSH\u57fa\u7840\u6982\u5ff5","text":""},{"location":"Tools/Others/SSH/#1-ssh","title":"1. SSH\u5de5\u4f5c\u539f\u7406","text":"SSH(Secure Shell)\u662f\u4e00\u79cd\u52a0\u5bc6\u7684\u7f51\u7edc\u534f\u8bae\uff0c\u901a\u8fc7\u5728\u4e0d\u5b89\u5168\u7684\u7f51\u7edc\u4e0a\u4e3a\u7f51\u7edc\u670d\u52a1\u63d0\u4f9b\u5b89\u5168\u7684\u4f20\u8f93\u73af\u5883\u3002SSH\u901a\u8fc7\u4f7f\u7528\u52a0\u5bc6\u6280\u672f\uff0c\u80fd\u591f\u6709\u6548\u9632\u6b62\u4e2d\u95f4\u4eba\u653b\u51fb\uff0c\u4fdd\u62a4\u6570\u636e\u4f20\u8f93\u7684\u5b89\u5168\u3002
SSH\u5de5\u4f5c\u6d41\u7a0b\uff1a 1. TCP\u8fde\u63a5\u5efa\u7acb\uff1a\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u5efa\u7acbTCP\u8fde\u63a5\uff08\u9ed8\u8ba4\u7aef\u53e322\uff09 2. \u7248\u672c\u534f\u5546\uff1a\u53cc\u65b9\u4ea4\u6362\u7248\u672c\u4fe1\u606f\uff0c\u786e\u5b9a\u4f7f\u7528\u7684SSH\u534f\u8bae\u7248\u672c 3. \u5bc6\u94a5\u4ea4\u6362\uff1a\u4f7f\u7528Diffie-Hellman\u7b97\u6cd5\u4ea4\u6362\u4f1a\u8bdd\u5bc6\u94a5 4. \u8ba4\u8bc1\uff1a\u4f7f\u7528\u516c\u94a5\u6216\u5bc6\u7801\u8fdb\u884c\u8eab\u4efd\u9a8c\u8bc1 5. \u4f1a\u8bdd\uff1a\u5efa\u7acb\u52a0\u5bc6\u901a\u4fe1\u901a\u9053
"},{"location":"Tools/Others/SSH/#2","title":"2. \u8ba4\u8bc1\u65b9\u5f0f\u8be6\u89e3","text":""},{"location":"Tools/Others/SSH/#21","title":"2.1 \u5bc6\u7801\u8ba4\u8bc1","text":"\u8ba4\u8bc1\u6d41\u7a0b 1. \u5ba2\u6237\u7aef\u53d1\u9001\u516c\u94a5\u4fe1\u606f\u7ed9\u670d\u52a1\u5668 2. \u670d\u52a1\u5668\u68c0\u67e5authorized_keys\u6587\u4ef6 3. \u670d\u52a1\u5668\u751f\u6210\u968f\u673a\u5b57\u7b26\u4e32\uff0c\u7528\u516c\u94a5\u52a0\u5bc6\u540e\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef 4. \u5ba2\u6237\u7aef\u7528\u79c1\u94a5\u89e3\u5bc6\uff0c\u5c06\u7ed3\u679c\u8fd4\u56de\u670d\u52a1\u5668 5. \u670d\u52a1\u5668\u9a8c\u8bc1\u7ed3\u679c\uff0c\u5b8c\u6210\u8ba4\u8bc1
"},{"location":"Tools/Others/SSH/#3","title":"3. \u5b89\u5168\u5efa\u8bae","text":""},{"location":"Tools/Others/SSH/#31","title":"3.1 \u57fa\u672c\u5b89\u5168\u8bbe\u7f6e","text":"Bash# /etc/ssh/sshd_config \u5b89\u5168\u914d\u7f6e\nPermitRootLogin no # \u7981\u6b62root\u76f4\u63a5\u767b\u5f55\nPasswordAuthentication no # \u7981\u7528\u5bc6\u7801\u8ba4\u8bc1\nPubkeyAuthentication yes # \u542f\u7528\u516c\u94a5\u8ba4\u8bc1\nPermitEmptyPasswords no # \u7981\u6b62\u7a7a\u5bc6\u7801\nProtocol 2 # \u53ea\u4f7f\u7528SSH2\u534f\u8bae\nMaxAuthTries 3 # \u6700\u5927\u8ba4\u8bc1\u5c1d\u8bd5\u6b21\u6570\nLoginGraceTime 30 # \u767b\u5f55\u8d85\u65f6\u65f6\u95f4\nX11Forwarding no # \u7981\u7528X11\u8f6c\u53d1\uff08\u9664\u975e\u9700\u8981\uff09\nAllowUsers user1 user2 # \u9650\u5236\u5141\u8bb8\u767b\u5f55\u7684\u7528\u6237\n
"},{"location":"Tools/Others/SSH/#32","title":"3.2 \u5bc6\u94a5\u7ba1\u7406","text":"Bash# \u751f\u6210\u5f3a\u5bc6\u94a5\nssh-keygen -t ed25519 -C \"your_email@example.com\" -a 100\n\n# \u5bc6\u94a5\u6743\u9650\u8bbe\u7f6e\nchmod 700 ~/.ssh\nchmod 600 ~/.ssh/id_ed25519\nchmod 644 ~/.ssh/id_ed25519.pub\nchmod 600 ~/.ssh/authorized_keys\nchmod 600 ~/.ssh/known_hosts\n
"},{"location":"Tools/Others/SSH/#ssh_2","title":"\u5e38\u7528\u7684 SSH \u547d\u4ee4","text":"SSH \u6559\u7a0b \u83dc\u9e1f\u6559\u7a0b
"},{"location":"Tools/Others/SSH/#_1","title":"\u4e8c\u3001\u5b8c\u6574\u914d\u7f6e\u6307\u5357","text":""},{"location":"Tools/Others/SSH/#1-linux","title":"1. Linux\u670d\u52a1\u5668\u914d\u7f6e","text":"Bash# 1. \u5b89\u88c5SSH\u670d\u52a1\u5668\nsudo apt update\nsudo apt install openssh-server\n\n# 2. \u914d\u7f6eSSH\u670d\u52a1\nsudo nano /etc/ssh/sshd_config\n\n# 3. \u57fa\u672c\u5b89\u5168\u914d\u7f6e\nPort 22 # \u53ef\u4ee5\u4fee\u6539\u4e3a\u975e\u6807\u51c6\u7aef\u53e3\nListenAddress 0.0.0.0 # \u76d1\u542c\u5730\u5740\nProtocol 2\nPermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nAuthorizedKeysFile .ssh/authorized_keys\nUsePAM yes\nX11Forwarding no\nPrintMotd no\nAcceptEnv LANG LC_*\nSubsystem sftp /usr/lib/openssh/sftp-server\n\n# 4. \u91cd\u542fSSH\u670d\u52a1\nsudo systemctl restart sshd\n\n# 5. \u68c0\u67e5\u670d\u52a1\u72b6\u6001\nsudo systemctl status sshd\n
"},{"location":"Tools/Others/SSH/#2-windows-ssh","title":"2. Windows SSH\u914d\u7f6e","text":""},{"location":"Tools/Others/SSH/#21-openssh","title":"2.1 \u5b89\u88c5OpenSSH","text":"PowerShell# \u4f7f\u7528PowerShell\u5b89\u88c5OpenSSH\n# \u68c0\u67e5OpenSSH\u72b6\u6001\nGet-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'\n\n# \u5b89\u88c5\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\nAdd-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0\nAdd-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0\n\n# \u542f\u52a8SSH\u670d\u52a1\nStart-Service sshd\nSet-Service -Name sshd -StartupType 'Automatic'\n
\u5982\u679c\u6709\u7f51\u7edc\u95ee\u9898\u53ef\u4ee5\u4e0b\u8f7d\u5e76\u5b89\u88c5 OpenSSH \u7684\u79bb\u7ebf\u5b89\u88c5\u5305\uff1a powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
\u00a0\u6765\u5b89\u88c5 OpenSSH \u670d\u52a1\u3002 # \u7f16\u8f91SSH\u914d\u7f6e\u6587\u4ef6\nnotepad \"$env:ProgramData\\ssh\\sshd_config\"\n\n# \u57fa\u672c\u914d\u7f6e\u5185\u5bb9\u4e0eLinux\u7c7b\u4f3c\uff0c\u4f46\u8def\u5f84\u9700\u8981\u8c03\u6574\nPubkeyAuthentication yes\nPasswordAuthentication no\nSubsystem sftp sftp-server.exe\n
"},{"location":"Tools/Others/SSH/#3-ssh","title":"3. SSH\u5ba2\u6237\u7aef\u914d\u7f6e","text":""},{"location":"Tools/Others/SSH/#31-ssh","title":"3.1 \u521b\u5efaSSH\u914d\u7f6e\u6587\u4ef6","text":"Bash# ~/.ssh/config\n# \u5168\u5c40\u8bbe\u7f6e\nHost *\n ServerAliveInterval 60\n ServerAliveCountMax 3\n HashKnownHosts yes\n GSSAPIAuthentication no\n\n# GitHub\nHost github.com\n HostName github.com\n User git\n IdentityFile ~/.ssh/github_ed25519\n AddKeysToAgent yes\n\n# \u5f00\u53d1\u670d\u52a1\u5668\nHost dev\n HostName dev.example.com\n User developer\n Port 22\n IdentityFile ~/.ssh/dev_ed25519\n ForwardAgent yes\n\n# \u751f\u4ea7\u670d\u52a1\u5668\nHost prod\n HostName prod.example.com\n User deployer\n Port 22\n IdentityFile ~/.ssh/prod_ed25519\n ForwardAgent no\n
"},{"location":"Tools/Others/SSH/#_2","title":"\u4e09\u3001\u5177\u4f53\u5b9e\u8df5\uff0c\u7528\u7b14\u8bb0\u672c\u8fde\u53f0\u5f0f\u673a","text":""},{"location":"Tools/Others/SSH/#_3","title":"\u53f0\u5f0f\u7535\u8111\uff08\u670d\u52a1\u7aef\uff09\u914d\u7f6e\uff1a","text":"# Ubuntu/Debian\u7cfb\u7edf\nsudo apt install openssh-server\nsudo systemctl enable ssh\nsudo systemctl start ssh\n\n# \u68c0\u67e5SSH\u670d\u52a1\u72b6\u6001\nsudo systemctl status ssh\n
# \u7f16\u8f91SSH\u670d\u52a1\u5668\u914d\u7f6e\nsudo nano /etc/ssh/sshd_config\n\n# \u6dfb\u52a0\u6216\u4fee\u6539\u4ee5\u4e0b\u914d\u7f6e\nPermitRootLogin no\nPasswordAuthentication no\nPubkeyAuthentication yes\nAllowUsers your_username # \u66ff\u6362\u4e3a\u60a8\u7684\u7528\u6237\u540d\n
# \u67e5\u770b\u5f53\u524dIP\nip addr show\n\n# \u5982\u679c\u662f\u52a8\u6001IP\uff0c\u5efa\u8bae\u8bbe\u7f6e\u9759\u6001IP\u6216\u4f7f\u7528\u52a8\u6001DNS\u670d\u52a1\n
"},{"location":"Tools/Others/SSH/#_4","title":"\u7b14\u8bb0\u672c\uff08\u5ba2\u6237\u7aef\uff09\u914d\u7f6e\uff1a","text":"ssh-keygen -t ed25519 -C \"your_laptop\"\n
# \u65b9\u6cd51\uff1a\u4f7f\u7528ssh-copy-id\nssh-copy-id -i ~/.ssh/id_ed25519.pub username@desktop_ip\n\n# \u65b9\u6cd52\uff1a\u624b\u52a8\u590d\u5236\ncat ~/.ssh/id_ed25519.pub | ssh username@desktop_ip \"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys\"\n
# \u7f16\u8f91 ~/.ssh/config\nnano ~/.ssh/config\n\n# \u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\nHost desktop\n HostName 192.168.1.xxx # \u66ff\u6362\u4e3a\u53f0\u5f0f\u673a\u7684IP\n User your_username # \u66ff\u6362\u4e3a\u60a8\u7684\u7528\u6237\u540d\n Port 22\n IdentityFile ~/.ssh/id_ed25519\n ForwardX11 yes # \u5982\u679c\u9700\u8981\u56fe\u5f62\u754c\u9762\u8f6c\u53d1\n ForwardAgent yes\n Compression yes\n ServerAliveInterval 60\n
"},{"location":"Tools/Others/SSH/#_5","title":"\u5e38\u7528\u8fde\u63a5\u547d\u4ee4\uff1a","text":"# \u4ece\u7b14\u8bb0\u672c\u8fde\u63a5\u5230\u53f0\u5f0f\u673a\nssh desktop\n\n# \u4f7f\u7528\u56fe\u5f62\u754c\u9762\u8f6c\u53d1\nssh -X desktop\n
# \u4ece\u7b14\u8bb0\u672c\u590d\u5236\u6587\u4ef6\u5230\u53f0\u5f0f\u673a\nscp /path/to/local/file desktop:/path/to/remote/\n\n# \u4ece\u53f0\u5f0f\u673a\u590d\u5236\u6587\u4ef6\u5230\u7b14\u8bb0\u672c\nscp desktop:/path/to/remote/file /path/to/local/\n
# \u672c\u5730\u7aef\u53e3\u8f6c\u53d1\nssh -L 8080:localhost:80 desktop\n\n# \u8fdc\u7a0b\u7aef\u53e3\u8f6c\u53d1\nssh -R 8080:localhost:80 desktop\n
"},{"location":"Tools/Others/SSH/#_6","title":"\u56db\u3001\u9ad8\u7ea7\u64cd\u4f5c","text":""},{"location":"Tools/Others/SSH/#1-ssh_1","title":"1. SSH\u7aef\u53e3\u8f6c\u53d1","text":""},{"location":"Tools/Others/SSH/#11","title":"1.1 \u672c\u5730\u7aef\u53e3\u8f6c\u53d1","text":"Bash# \u5c06\u672c\u57308080\u7aef\u53e3\u8f6c\u53d1\u5230\u8fdc\u7a0b80\u7aef\u53e3\nssh -L 8080:localhost:80 user@remote\n\n# \u4f7f\u7528\u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost tunnel\n HostName remote.example.com\n LocalForward 8080 localhost:80\n
"},{"location":"Tools/Others/SSH/#12","title":"1.2 \u8fdc\u7a0b\u7aef\u53e3\u8f6c\u53d1","text":"Bash# \u5c06\u8fdc\u7a0b3000\u7aef\u53e3\u8f6c\u53d1\u5230\u672c\u57303000\u7aef\u53e3\nssh -R 3000:localhost:3000 user@remote\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost remote-tunnel\n HostName remote.example.com\n RemoteForward 3000 localhost:3000\n
"},{"location":"Tools/Others/SSH/#2-ssh","title":"2. SSH\u4ee3\u7406\u8f6c\u53d1","text":"Bash# \u542f\u7528\u4ee3\u7406\u8f6c\u53d1\nssh -A user@remote\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost *\n ForwardAgent yes\n AddKeysToAgent yes\n
"},{"location":"Tools/Others/SSH/#3_1","title":"3. \u8df3\u677f\u673a\u914d\u7f6e","text":"Bash# \u901a\u8fc7\u8df3\u677f\u673a\u8fde\u63a5\nssh -J jumphost user@target\n\n# \u914d\u7f6e\u6587\u4ef6\u8bbe\u7f6e\nHost target\n HostName target.example.com\n ProxyJump jumphost\n
"},{"location":"Tools/Others/SSH/#_7","title":"\u4e94\u3001\u6545\u969c\u6392\u67e5","text":""},{"location":"Tools/Others/SSH/#1","title":"1. \u6700\u4f73\u5b9e\u8df5","text":"Bash# 1. \u4f7f\u7528SSH\u914d\u7f6e\u6587\u4ef6\u7ba1\u7406\u8fde\u63a5\n# 2. \u4e3a\u4e0d\u540c\u7528\u9014\u4f7f\u7528\u4e0d\u540c\u7684\u5bc6\u94a5\n# 3. \u5b9a\u671f\u8f6e\u6362\u5bc6\u94a5\n# 4. \u4f7f\u7528ssh-agent\u7ba1\u7406\u5bc6\u94a5\n# 5. \u5907\u4efdSSH\u914d\u7f6e\u548c\u5bc6\u94a5\n
"},{"location":"Tools/Others/SSH/#2_1","title":"2. \u5e38\u89c1\u95ee\u9898\u89e3\u51b3","text":"Bash# \u8fde\u63a5\u88ab\u62d2\u7edd\nssh -v user@host # \u67e5\u770b\u8be6\u7ec6\u8fde\u63a5\u4fe1\u606f\n\n# \u6743\u9650\u95ee\u9898\nls -la ~/.ssh # \u68c0\u67e5\u6743\u9650\nchmod 600 ~/.ssh/id_ed25519\n\n# \u5bc6\u94a5\u95ee\u9898\nssh-add -l # \u67e5\u770b\u5df2\u52a0\u8f7d\u7684\u5bc6\u94a5\nssh-add ~/.ssh/id_ed25519 # \u6dfb\u52a0\u5bc6\u94a5\u5230agent\n
"},{"location":"Tools/Others/SSH/#3_2","title":"3. \u65e5\u5fd7\u67e5\u770b","text":"Bash# \u670d\u52a1\u5668\u7aef\nsudo tail -f /var/log/auth.log # Debian/Ubuntu\nsudo tail -f /var/log/secure # CentOS/RHEL\n\n# \u5ba2\u6237\u7aef\u8c03\u8bd5\nssh -vvv user@host # \u6700\u8be6\u7ec6\u7684\u8c03\u8bd5\u4fe1\u606f\n
"},{"location":"Tools/Others/zotero_%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/","title":"zotero_\u4f7f\u7528\u6307\u5357","text":"\u7ea6 156 \u4e2a\u5b57 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 1 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
#Zotero
#Tools
","tags":["Zotero","Tools"]},{"location":"Tools/Others/zotero_%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#zotero","title":"zotero \u4f7f\u7528\u6307\u5357","text":"\u7ea6 236 \u4e2a\u5b57 789 \u884c\u4ee3\u7801 \u9884\u8ba1\u9605\u8bfb\u65f6\u95f4 11 \u5206\u949f \u5171\u88ab\u8bfb\u8fc7 \u6b21
"},{"location":"Tools/Terminal/Tabby_Zsh/#_1","title":"\u524d\u7f6e\u51c6\u5907","text":"\u7cfb\u7edf\u8981\u6c42
Bash# Ubuntu/Debian\nsudo apt update\nsudo apt install -y \\\n git \\\n curl \\\n wget \\\n build-essential \\\n cmake \\\n python3-pip \\\n pkg-config \\\n libssl-dev\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#zsh","title":"ZSH \u57fa\u7840\u914d\u7f6e","text":"ZSH \u5b89\u88c5
Bash# \u5b89\u88c5zsh\nsudo apt install zsh\n\n# \u8bbe\u7f6e\u4e3a\u9ed8\u8ba4shell\nchsh -s $(which zsh)\n\n# \u786e\u8ba4\u8bbe\u7f6e\necho $SHELL\n# \u5e94\u8be5\u8f93\u51fa: /usr/bin/zsh\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#1-oh-my-zsh","title":"1. Oh My Zsh \u5b89\u88c5","text":"Bash# \u5b89\u88c5Oh My Zsh\nsh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n\n# \u5907\u4efd\u9ed8\u8ba4\u914d\u7f6e\ncp ~/.zshrc ~/.zshrc.backup\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2","title":"2. \u63d2\u4ef6\u7ba1\u7406\u5668\u5b89\u88c5","text":"Bash# \u5b89\u88c5zinit\nbash -c \"$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/install.sh)\"\n\n# \u7b49\u5f85\u5b89\u88c5\u5b8c\u6210\u540e\u91cd\u542f\u7ec8\u7aef\nexec zsh\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3","title":"3. \u57fa\u7840\u914d\u7f6e\u6587\u4ef6","text":"Bash# \u521b\u5efa\u65b0\u7684\u914d\u7f6e\u6587\u4ef6\ncat << 'EOF' > ~/.zshrc\n# \u57fa\u7840\u8bbe\u7f6e\nexport ZSH=\"$HOME/.oh-my-zsh\"\nexport LANG=en_US.UTF-8\nexport EDITOR='nvim'\nexport VISUAL='nvim'\n\n# zinit\u914d\u7f6e\nsource \"$HOME/.local/share/zinit/zinit.git/zinit.zsh\"\nautoload -Uz _zinit\n(( ${+_comps} )) && _comps[zinit]=_zinit\n\n# \u52a0\u8f7d\u6838\u5fc3\u63d2\u4ef6\nzinit ice depth=1; zinit light romkatv/powerlevel10k # \u4e3b\u9898\nzinit light zsh-users/zsh-autosuggestions # \u547d\u4ee4\u5efa\u8bae\nzinit light zsh-users/zsh-syntax-highlighting # \u8bed\u6cd5\u9ad8\u4eae\nzinit light zsh-users/zsh-completions # \u8865\u5168\u589e\u5f3a\nzinit light agkozak/zsh-z # \u76ee\u5f55\u8df3\u8f6c\n\n# \u5386\u53f2\u8bb0\u5f55\u8bbe\u7f6e\nHISTFILE=\"$HOME/.zsh_history\"\nHISTSIZE=50000\nSAVEHIST=50000\nsetopt EXTENDED_HISTORY # \u8bb0\u5f55\u547d\u4ee4\u65f6\u95f4\u6233\nsetopt HIST_EXPIRE_DUPS_FIRST # \u4f18\u5148\u5220\u9664\u91cd\u590d\u547d\u4ee4\nsetopt HIST_IGNORE_DUPS # \u5ffd\u7565\u8fde\u7eed\u91cd\u590d\u547d\u4ee4\nsetopt HIST_IGNORE_SPACE # \u5ffd\u7565\u4ee5\u7a7a\u683c\u5f00\u5934\u7684\u547d\u4ee4\nsetopt HIST_VERIFY # \u6267\u884c\u5386\u53f2\u547d\u4ee4\u524d\u5c55\u793a\nsetopt INC_APPEND_HISTORY # \u5b9e\u65f6\u6dfb\u52a0\u5386\u53f2\u8bb0\u5f55\nsetopt SHARE_HISTORY # \u5171\u4eab\u5386\u53f2\u8bb0\u5f55\n\n# \u76ee\u5f55\u8bbe\u7f6e\nsetopt AUTO_CD \nsetopt AUTO_PUSHD \nsetopt PUSHD_IGNORE_DUPS \nsetopt PUSHD_MINUS \nDIRSTACKSIZE=20\n\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4","title":"4. \u5b9e\u7528\u522b\u540d\u8bbe\u7f6e","text":"Bash# \u6dfb\u52a0\u5230~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u57fa\u7840\u547d\u4ee4\u589e\u5f3a\nalias ls='ls --color=auto'\nalias ll='ls -lah'\nalias la='ls -A'\nalias l='ls -CF'\nalias grep='grep --color=auto'\nalias rm='rm -i'\nalias cp='cp -i'\nalias mv='mv -i'\nalias mkdir='mkdir -p'\nalias df='df -h'\nalias free='free -m'\nalias duf='du -sh *'\nalias ps='ps auxf'\nalias ping='ping -c 5'\nalias root='sudo -i'\nalias reboot='sudo reboot'\nalias poweroff='sudo poweroff'\n\n# Git\u5feb\u6377\u547d\u4ee4\nalias gs='git status'\nalias ga='git add'\nalias gaa='git add --all'\nalias gc='git commit -m'\nalias gp='git push'\nalias gl='git pull'\nalias gd='git diff'\nalias gco='git checkout'\nalias gb='git branch'\nalias gm='git merge'\nalias glog='git log --oneline --decorate --graph'\n\n# Docker\u5feb\u6377\u547d\u4ee4\nalias dk='docker'\nalias dkc='docker-compose'\nalias dkps='docker ps'\nalias dkst='docker stats'\nalias dktop='docker top'\nalias dkimg='docker images'\nalias dkpull='docker pull'\nalias dkex='docker exec -it'\n\n# \u5feb\u901f\u7f16\u8f91\nalias zshconfig=\"$EDITOR ~/.zshrc\"\nalias zshreload=\"source ~/.zshrc\"\nalias vimconfig=\"$EDITOR ~/.vimrc\"\nalias tmuxconfig=\"$EDITOR ~/.tmux.conf\"\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#5","title":"5. \u5b9e\u7528\u51fd\u6570","text":"Bash# \u6dfb\u52a0\u5230~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u521b\u5efa\u5e76\u8fdb\u5165\u76ee\u5f55\nmkcd() {\n mkdir -p \"$1\" && cd \"$1\"\n}\n\n# \u63d0\u53d6\u538b\u7f29\u6587\u4ef6\nextract() {\n if [ -f $1 ]; then\n case $1 in\n *.tar.bz2) tar xjf $1 ;;\n *.tar.gz) tar xzf $1 ;;\n *.bz2) bunzip2 $1 ;;\n *.rar) unrar e $1 ;;\n *.gz) gunzip $1 ;;\n *.tar) tar xf $1 ;;\n *.tbz2) tar xjf $1 ;;\n *.tgz) tar xzf $1 ;;\n *.zip) unzip $1 ;;\n *.Z) uncompress $1 ;;\n *.7z) 7z x $1 ;;\n *) echo \"'$1' cannot be extracted\" ;;\n esac\n else\n echo \"'$1' is not a valid file\"\n fi\n}\n\n# \u5feb\u901f\u67e5\u627e\u6587\u4ef6\nff() { find . -type f -iname \"*$1*\" ; }\nfd() { find . -type d -iname \"*$1*\" ; }\n\n# \u5feb\u901f\u67e5\u770b\u8fdb\u7a0b\npsg() { ps aux | grep -v grep | grep -i -e VSZ -e \"$1\"; }\n\n# \u7f51\u7edc\u5de5\u5177\nmyip() {\n curl -s http://ipecho.net/plain\n echo\n}\n\n# \u5feb\u901fHTTP\u670d\u52a1\u5668\nserve() {\n local port=\"${1:-8000}\"\n python3 -m http.server \"$port\"\n}\n\n# Git\u65e5\u5fd7\u7f8e\u5316\ngll() {\n git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit\n}\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_2","title":"\u4e3b\u9898\u7f8e\u5316\u4e0e\u63d2\u4ef6\u589e\u5f3a","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#powerlevel10k","title":"\u4e00\u3001Powerlevel10k \u4e3b\u9898\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1","title":"1. \u5b89\u88c5\u5fc5\u8981\u5b57\u4f53","text":"Bash# \u521b\u5efa\u5b57\u4f53\u76ee\u5f55\nmkdir -p ~/.local/share/fonts\n\n# \u4e0b\u8f7d\u63a8\u8350\u5b57\u4f53\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Italic.ttf\nwget -P /tmp https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold%20Italic.ttf\n\n# \u79fb\u52a8\u5b57\u4f53\u6587\u4ef6\nmv /tmp/MesloLGS*.ttf ~/.local/share/fonts/\n\n# \u66f4\u65b0\u5b57\u4f53\u7f13\u5b58\nfc-cache -f -v\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_1","title":"2. \u4e3b\u9898\u914d\u7f6e","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# Powerlevel10k \u914d\u7f6e\n# \u542f\u7528 Powerlevel10k \u5373\u65f6\u63d0\u793a\nif [[ -r \"${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh\" ]]; then\n source \"${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh\"\nfi\n\n# \u52a0\u8f7d\u4e3b\u9898\nsource ~/.oh-my-zsh/custom/themes/powerlevel10k/powerlevel10k.zsh-theme\n\n# \u4e3b\u9898\u4e2a\u6027\u5316\u8bbe\u7f6e\nPOWERLEVEL9K_MODE='nerdfont-complete'\nPOWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(\n os_icon # \u64cd\u4f5c\u7cfb\u7edf\u56fe\u6807\n dir # \u5f53\u524d\u76ee\u5f55\n vcs # git\u72b6\u6001\n newline # \u6362\u884c\n prompt_char # \u63d0\u793a\u7b26\n)\nPOWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(\n status # \u4e0a\u4e00\u4e2a\u547d\u4ee4\u7684\u72b6\u6001\n background_jobs # \u540e\u53f0\u4efb\u52a1\n load # \u7cfb\u7edf\u8d1f\u8f7d\n ram # \u5185\u5b58\u4f7f\u7528\n time # \u65f6\u95f4\n)\n\n# \u76ee\u5f55\u663e\u793a\u8bbe\u7f6e\nPOWERLEVEL9K_DIR_BACKGROUND='blue'\nPOWERLEVEL9K_DIR_FOREGROUND='black'\nPOWERLEVEL9K_SHORTEN_DIR_LENGTH=2\nPOWERLEVEL9K_SHORTEN_STRATEGY=\"truncate_middle\"\n\n# Git\u72b6\u6001\u8bbe\u7f6e\nPOWERLEVEL9K_VCS_CLEAN_BACKGROUND='green'\nPOWERLEVEL9K_VCS_UNTRACKED_BACKGROUND='yellow'\nPOWERLEVEL9K_VCS_MODIFIED_BACKGROUND='red'\nEOF\n\n# \u8fd0\u884c\u914d\u7f6e\u5411\u5bfc\uff08\u9996\u6b21\u4f7f\u7528\uff09\np10k configure\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_3","title":"\u4e8c\u3001\u9ad8\u7ea7\u63d2\u4ef6\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_1","title":"1. \u9ad8\u7ea7\u8865\u5168\u7cfb\u7edf","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u8865\u5168\u7cfb\u7edf\u914d\u7f6e\nautoload -Uz compinit\ncompinit\n\n# \u8865\u5168\u83dc\u5355\u8bbe\u7f6e\nzstyle ':completion:*' menu select\nzstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # \u5ffd\u7565\u5927\u5c0f\u5199\nzstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} # \u8865\u5168\u83dc\u5355\u7740\u8272\nzstyle ':completion:*' verbose yes # \u8be6\u7ec6\u8865\u5168\u83dc\u5355\nzstyle ':completion:*:descriptions' format '%U%B%d%b%u' # \u8865\u5168\u83dc\u5355\u683c\u5f0f\nzstyle ':completion:*:warnings' format '%BSorry, no matches for: %d%b'\nzstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'\nzstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'\n\n# \u4f7f\u7528\u7f13\u5b58\u52a0\u901f\u8865\u5168\nzstyle ':completion:*' use-cache on\nzstyle ':completion:*' cache-path ~/.zsh/cache\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-fzf","title":"2. FZF \u96c6\u6210\u914d\u7f6e","text":"Bash# \u5b89\u88c5FZF\ngit clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf\n~/.fzf/install\n\n# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# FZF \u914d\u7f6e\nexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'\nexport FZF_DEFAULT_OPTS='--height 40% --layout=reverse --border --preview \"bat --style=numbers --color=always --line-range :500 {}\"'\n\n# FZF \u5feb\u6377\u952e\nbindkey '^T' fzf-file-widget\nbindkey '^R' fzf-history-widget\nbindkey '^[c' fzf-cd-widget\n\n# FZF \u51fd\u6570\n# \u5feb\u901f\u6253\u5f00\u6587\u4ef6\nfe() {\n local file\n file=$(fzf --query=\"$1\" --select-1 --exit-0)\n [ -n \"$file\" ] && ${EDITOR:-vim} \"$file\"\n}\n\n# \u5feb\u901f\u5207\u6362\u76ee\u5f55\nfd() {\n local dir\n dir=$(find ${1:-.} -path '*/\\.*' -prune -o -type d -print 2> /dev/null | fzf +m)\n [ -n \"$dir\" ] && cd \"$dir\"\n}\n\n# \u641c\u7d22\u5386\u53f2\u547d\u4ee4\nfh() {\n print -z $( ([ -n \"$ZSH_NAME\" ] && fc -l 1 || history) | fzf +s --tac | sed -E 's/ *[0-9]*\\*? *//' | sed -E 's/\\\\/\\\\\\\\/g')\n}\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3_1","title":"3. \u589e\u5f3a\u76ee\u5f55\u5bfc\u822a","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u76ee\u5f55\u4e66\u7b7e\nhash -d proj=~/projects\nhash -d docs=~/Documents\nhash -d dl=~/Downloads\nhash -d pics=~/Pictures\n\n# z \u63d2\u4ef6\u914d\u7f6e\nZSHZ_DATA=~/.local/share/z/data\nZSHZ_MAX_SCORE=5000\nZSHZ_CASE=smart\n\n# \u76ee\u5f55\u5806\u6808\u5bfc\u822a\nsetopt AUTO_PUSHD # \u81ea\u52a8\u5c06\u76ee\u5f55\u52a0\u5165\u5806\u6808\nsetopt PUSHD_IGNORE_DUPS # \u5ffd\u7565\u91cd\u590d\u76ee\u5f55\nsetopt PUSHD_SILENT # \u9759\u9ed8\u6a21\u5f0f\nsetopt PUSHD_TO_HOME # pushd \u4e0d\u5e26\u53c2\u6570\u65f6\u7b49\u540c\u4e8e pushd $HOME\n\n# \u76ee\u5f55\u522b\u540d\nalias -g ...='../..'\nalias -g ....='../../..'\nalias -g .....='../../../..'\nalias d='dirs -v'\nfor index ({1..9}) alias \"$index\"=\"cd +${index}\"; unset index\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4_1","title":"4. \u589e\u5f3a\u5386\u53f2\u8bb0\u5f55\u641c\u7d22","text":"Bash# \u6dfb\u52a0\u5230 ~/.zshrc\ncat << 'EOF' >> ~/.zshrc\n# \u5386\u53f2\u8bb0\u5f55\u641c\u7d22\u914d\u7f6e\nbindkey '^[[A' history-substring-search-up\nbindkey '^[[B' history-substring-search-down\nbindkey '^P' history-substring-search-up\nbindkey '^N' history-substring-search-down\n\n# \u5386\u53f2\u8bb0\u5f55\u683c\u5f0f\u5316\nHIST_STAMPS=\"yyyy-mm-dd\"\nHISTORY_IGNORE=\"(ls|ls *|cd|cd *|pwd|exit|date|* --help)\"\n\n# \u547d\u4ee4\u6267\u884c\u65f6\u95f4\u663e\u793a\nREPORTTIME=10\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#tabby","title":"Tabby \u7ec8\u7aef\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#_4","title":"\u4e00\u3001\u5b89\u88c5\u548c\u521d\u59cb\u5316","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1-tabby","title":"1. \u5b89\u88c5 Tabby","text":"Bash# Ubuntu/Debian\nwget https://github.com/Eugeny/tabby/releases/latest/download/tabby-1.0.0-linux-x64.deb\nsudo dpkg -i tabby-*.deb\nsudo apt-get install -f\n\n# \u786e\u4fdd\u5b57\u4f53\u652f\u6301\nfc-cache -fv\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_2","title":"2. \u521d\u59cb\u914d\u7f6e","text":"YAML# ~/.config/tabby/config.yaml\nconfig:\n version: 3\n\nterminal:\n shell: zsh # \u4f7f\u7528\u524d\u9762\u914d\u7f6e\u7684zsh\n fontSize: 14\n lineHeight: 1.2\n bell: 'off'\n copyOnSelect: true\n rightClick: menu\n\n # \u57fa\u7840\u73af\u5883\u53d8\u91cf\n environment:\n TERM: xterm-256color\n COLORTERM: truecolor\n\n # \u6027\u80fd\u8bbe\u7f6e\n performanceMode: true\n gpuAcceleration: true\n webGL: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_5","title":"\u4e8c\u3001\u5916\u89c2\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_2","title":"1. \u5b57\u4f53\u8bbe\u7f6e","text":"YAMLterminal:\n font: JetBrainsMono Nerd Font # \u786e\u4fdd\u5df2\u5b89\u88c5\n fontSize: 14\n lineHeight: 1.2\n ligatures: true # \u8fde\u5b57\u652f\u6301\n\n # \u5b57\u4f53\u56de\u9000\n fallbackFont: 'Sarasa Mono SC' # \u4e2d\u6587\u652f\u6301\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-dracula","title":"2. Dracula \u4e3b\u9898\u914d\u7f6e","text":"YAMLprofiles:\n - name: Default\n theme:\n name: 'Dracula'\n\n colors:\n background: '#282a36'\n foreground: '#f8f8f2'\n cursor: '#f8f8f2'\n\n selection:\n background: '#44475a'\n foreground: '#f8f8f2'\n\n # ANSI Colors\n black: '#21222c'\n red: '#ff5555'\n green: '#50fa7b'\n yellow: '#f1fa8c'\n blue: '#bd93f9'\n magenta: '#ff79c6'\n cyan: '#8be9fd'\n white: '#f8f8f2'\n\n # Bright Colors\n brightBlack: '#6272a4'\n brightRed: '#ff6e6e'\n brightGreen: '#69ff94'\n brightYellow: '#ffffa5'\n brightBlue: '#d6acff'\n brightMagenta: '#ff92df'\n brightCyan: '#a4ffff'\n brightWhite: '#ffffff'\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3_2","title":"3. \u900f\u660e\u80cc\u666f\u914d\u7f6e","text":"YAMLterminal:\n background:\n type: 'image' # \u6216 'color'\n image: '~/.config/tabby/backgrounds/bg.jpg' # \u81ea\u5b9a\u4e49\u80cc\u666f\u56fe\u7247\n opacity: 0.85 # \u900f\u660e\u5ea6\n\n # \u4e9a\u514b\u529b\u6548\u679c\uff08Windows\uff09\n experimental:\n vibrancy: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_6","title":"\u4e09\u3001\u5feb\u6377\u952e\u914d\u7f6e","text":"YAMLhotkeys:\n # \u6807\u7b7e\u7ba1\u7406\n new-tab: ['Ctrl+T']\n close-tab: ['Ctrl+W']\n previous-tab: ['Ctrl+Shift+Tab']\n next-tab: ['Ctrl+Tab']\n\n # \u5206\u5c4f\u64cd\u4f5c\n split-right: ['Ctrl+Shift+E']\n split-bottom: ['Ctrl+Shift+O']\n split-nav-left: ['Alt+Left']\n split-nav-right: ['Alt+Right']\n split-nav-up: ['Alt+Up']\n split-nav-down: ['Alt+Down']\n\n # \u7ec8\u7aef\u64cd\u4f5c\n clear: ['Ctrl+L']\n copy: ['Ctrl+C']\n paste: ['Ctrl+V']\n search: ['Ctrl+Shift+F']\n\n # \u89c6\u56fe\u63a7\u5236\n zoom-in: ['Ctrl+Plus']\n zoom-out: ['Ctrl+Minus']\n reset-zoom: ['Ctrl+0']\n toggle-fullscreen: ['F11']\n\n # \u5feb\u901f\u547d\u4ee4\n command-palette: ['Ctrl+Shift+P']\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#ssh","title":"\u56db\u3001SSH \u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1-ssh","title":"1. \u57fa\u7840 SSH \u914d\u7f6e","text":"YAMLssh:\n auth:\n agent: true\n privateKeys:\n - ~/.ssh/id_ed25519\n - ~/.ssh/id_rsa\n\n # \u8fde\u63a5\u4fdd\u6301\n keepaliveInterval: 30\n keepaliveCountMax: 3\n\n # \u8f6c\u53d1\u8bbe\u7f6e\n forwardAgent: true\n x11: false\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-ssh","title":"2. SSH \u8fde\u63a5\u914d\u7f6e","text":"YAMLssh:\n profiles:\n - name: \"\u5f00\u53d1\u670d\u52a1\u5668\"\n group: \"\u5f00\u53d1\u73af\u5883\"\n host: dev.example.com\n port: 22\n user: username\n auth: publicKey\n privateKey: ~/.ssh/id_ed25519\n\n - name: \"\u751f\u4ea7\u670d\u52a1\u5668\"\n group: \"\u751f\u4ea7\u73af\u5883\"\n host: prod.example.com\n port: 22\n user: username\n auth: agent\n\n - name: \"\u8df3\u677f\u673a\"\n host: jump.example.com\n forwardAgent: true\n jumpHost: true # \u6807\u8bb0\u4e3a\u8df3\u677f\u673a\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_7","title":"\u4e94\u3001\u63d2\u4ef6\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_3","title":"1. \u6838\u5fc3\u63d2\u4ef6","text":"YAMLplugins:\n # SSH\u7ba1\u7406\n ssh:\n enabled: true\n\n # \u7ec8\u7aef\u5f55\u5236\n record:\n enabled: true\n directory: ~/terminal-records\n\n # \u547d\u4ee4\u9762\u677f\n commander:\n enabled: true\n\n # \u4e3b\u9898\u63d2\u4ef6\n community-color-schemes:\n enabled: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2_3","title":"2. \u6269\u5c55\u529f\u80fd","text":"YAML# \u641c\u7d22\u589e\u5f3a\nsearch:\n enabled: true\n searchOptions:\n regex: true\n wholeWord: false\n caseSensitive: false\n\n# \u7ec8\u7aef\u5206\u5272\nsplit:\n autoRemove: true # \u81ea\u52a8\u5173\u95ed\u7a7a\u7ec8\u7aef\n copyOnSelect: true\n pasteOnMiddleClick: true\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_8","title":"\u516d\u3001\u6027\u80fd\u4f18\u5316","text":"YAML# \u6027\u80fd\u76f8\u5173\u914d\u7f6e\nterminal:\n # \u57fa\u7840\u4f18\u5316\n performanceMode: true\n gpuAcceleration: true\n webGL: true\n\n # \u5386\u53f2\u8bb0\u5f55\n scrollback: 5000\n\n # \u8fdb\u7a0b\u7ba1\u7406\n autoClose: true\n closeOnExit: true\n\n # \u6e32\u67d3\u4f18\u5316\n smoothScroll: false\n experimentalFontRendering: false\n\n # \u8d44\u6e90\u9650\u5236\n environment:\n LIMIT_MEMORY: 512 # MB\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#_9","title":"\u5f00\u53d1\u5de5\u5177\u4e0e\u7ec8\u7aef\u5de5\u5177\u914d\u7f6e","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#_10","title":"\u4e00\u3001\u73b0\u4ee3\u547d\u4ee4\u884c\u5de5\u5177","text":""},{"location":"Tools/Terminal/Tabby_Zsh/#1_4","title":"1. \u57fa\u7840\u5de5\u5177\u5b89\u88c5","text":"Bash# \u5b89\u88c5\u57fa\u7840\u5de5\u5177\nsudo apt install -y \\\n exa `# \u73b0\u4ee3ls\u66ff\u4ee3\u54c1` \\\n bat `# \u73b0\u4ee3cat\u66ff\u4ee3\u54c1` \\\n ripgrep `# \u73b0\u4ee3grep\u66ff\u4ee3\u54c1` \\\n fd-find `# \u73b0\u4ee3find\u66ff\u4ee3\u54c1` \\\n duf `# \u73b0\u4ee3df\u66ff\u4ee3\u54c1` \\\n ncdu `# \u78c1\u76d8\u4f7f\u7528\u5206\u6790` \\\n tldr `# \u547d\u4ee4\u7b80\u5316\u8bf4\u660e` \\\n jq `# JSON\u5904\u7406` \\\n fzf `# \u6a21\u7cca\u641c\u7d22`\n\n# \u521b\u5efa\u522b\u540d\ncat << 'EOF' >> ~/.zshrc\n# \u73b0\u4ee3\u547d\u4ee4\u884c\u5de5\u5177\u522b\u540d\nalias ls='exa --icons'\nalias ll='exa -l --icons --git'\nalias la='exa -la --icons --git'\nalias lt='exa -T --icons --git-ignore'\nalias cat='batcat'\nalias find='fd'\nalias du='ncdu'\nalias df='duf'\nalias help='tldr'\n\n# fzf \u914d\u7f6e\nexport FZF_DEFAULT_OPTS=\"--height 40% --layout=reverse --border \\\n --preview 'batcat --style=numbers --color=always --line-range :500 {}'\"\nexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'\nexport FZF_CTRL_T_COMMAND=\"$FZF_DEFAULT_COMMAND\"\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#2-ranger","title":"2. \u6587\u4ef6\u7ba1\u7406\u5668 - Ranger","text":"Bash# \u5b89\u88c5ranger\u548c\u4f9d\u8d56\nsudo apt install ranger python3-pillow ueberzug\n\n# \u751f\u6210\u914d\u7f6e\u6587\u4ef6\nranger --copy-config=all\n\n# \u914d\u7f6eRanger\ncat << 'EOF' > ~/.config/ranger/rc.conf\n# \u57fa\u7840\u8bbe\u7f6e\nset preview_images true\nset preview_images_method ueberzug\nset show_hidden true\nset hostname_in_titlebar false\nset tilde_in_titlebar true\nset line_numbers relative\nset mouse_enabled true\n\n# \u914d\u8272\u65b9\u6848\nset colorscheme solarized\n\n# \u6587\u4ef6\u9884\u89c8\nset use_preview_script true\nset preview_files true\nset preview_directories true\nset collapse_preview true\n\n# \u5feb\u6377\u952e\nmap <C-f> fzf_select\nmap <C-p> shell -w echo %d/%f | xsel -b\nmap <C-g> shell lazygit\nEOF\n\n# \u6dfb\u52a0FZF\u96c6\u6210\ncat << 'EOF' > ~/.config/ranger/commands.py\nfrom ranger.api.commands import Command\nclass fzf_select(Command):\n def execute(self):\n import subprocess\n import os.path\n command=\"find -L . \\( -path '*/\\.*' -o -fstype 'dev' -o -fstype 'proc' \\) -prune \\\n -o -print 2> /dev/null | sed 1d | cut -b3- | fzf +m\"\n fzf = self.fm.execute_command(command, universal_newlines=True, stdout=subprocess.PIPE)\n stdout, stderr = fzf.communicate()\n if fzf.returncode == 0:\n fzf_file = os.path.abspath(stdout.rstrip('\\n'))\n if os.path.isdir(fzf_file):\n self.fm.cd(fzf_file)\n else:\n self.fm.select_file(fzf_file)\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#3-htopglances","title":"3. \u7cfb\u7edf\u76d1\u63a7 - htop/glances","text":"Bash# \u5b89\u88c5\u5de5\u5177\nsudo apt install htop glances\n\n# htop\u914d\u7f6e\nmkdir -p ~/.config/htop\ncat << 'EOF' > ~/.config/htop/htoprc\n# \u57fa\u7840\u663e\u793a\u8bbe\u7f6e\nshow_cpu_frequency=1\nshow_cpu_temperature=1\nshow_program_path=0\nhighlight_base_name=1\nhighlight_megabytes=1\nhighlight_threads=1\n\n# \u663e\u793a\u8bbe\u7f6e\nfields=0 48 17 18 38 39 40 2 46 47 49 1\nsort_key=46\nsort_direction=-1\ntree_view=1\ntree_view_always_by_pid=0\n\n# \u989c\u8272\u8bbe\u7f6e\ncolor_scheme=0\nEOF\n\n# glances\u914d\u7f6e\nmkdir -p ~/.config/glances\ncat << 'EOF' > ~/.config/glances/glances.conf\n[global]\n# \u5237\u65b0\u95f4\u9694\nrefresh=2\n# \u5386\u53f2\u5927\u5c0f\nhistory_size=1200\n\n[cpu]\n# CPU \u8b66\u544a\u9608\u503c\ncareful=50\nwarning=70\ncritical=90\n\n[memory]\n# \u5185\u5b58\u8b66\u544a\u9608\u503c\ncareful=50\nwarning=70\ncritical=90\n\n[network]\n# \u7f51\u7edc\u5e26\u5bbd\u663e\u793a\u5355\u4f4d (bit/sec)\nunit=bit\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#4-git-lazygit","title":"4. Git \u5de5\u5177 - Lazygit","text":"Bash# \u5b89\u88c5Lazygit\nLAZYGIT_VERSION=$(curl -s \"https://api.github.com/repos/jesseduffield/lazygit/releases/latest\" | grep -Po '\"tag_name\": \"v\\K[^\"]*')\ncurl -Lo lazygit.tar.gz \"https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz\"\nsudo tar xf lazygit.tar.gz -C /usr/local/bin lazygit\n\n# \u914d\u7f6eLazygit\nmkdir -p ~/.config/lazygit\ncat << 'EOF' > ~/.config/lazygit/config.yml\ngui:\n # UI\u4e3b\u9898\n theme:\n lightTheme: false\n activeBorderColor:\n - green\n - bold\n inactiveBorderColor:\n - white\n selectedLineBgColor:\n - reverse\n # \u5e38\u7528\u8bbe\u7f6e \n showFileTree: true\n showRandomTip: false\n showCommandLog: false\n\ngit:\n # git\u8bbe\u7f6e\n paging:\n colorArg: always\n useConfig: true\n # commit\u8bbe\u7f6e\n commits:\n showGraph: always\n showWholeGraph: true\n # \u81ea\u52a8\u83b7\u53d6\n autoFetch: true\n # \u5206\u652f\u663e\u793a\n branchLogCmd: \"git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --\"\n\nkeybinding:\n # \u81ea\u5b9a\u4e49\u5feb\u6377\u952e\n universal:\n return: '<c-c>'\n quit: 'q'\n quit-alt1: '<esc>'\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#5_1","title":"5. \u4ee3\u7801\u641c\u7d22\u5de5\u5177","text":"Bash# ripgrep\u914d\u7f6e\ncat << 'EOF' >> ~/.zshrc\n# ripgrep \u914d\u7f6e\nexport RIPGREP_CONFIG_PATH=\"$HOME/.ripgreprc\"\n\n# ripgrep \u522b\u540d\nalias rg='rg --smart-case'\nalias rgf='rg --files | rg'\nalias rgh='rg --hidden'\nalias rgc='rg --count'\n\n# fzf + ripgrep \u96c6\u6210\nfif() {\n if [ ! \"$#\" -gt 0 ]; then echo \"Need a string to search for!\"; return 1; fi\n rg --files-with-matches --no-messages \"$1\" | fzf --preview \"highlight -O ansi -l {} 2> /dev/null | rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' || rg --ignore-case --pretty --context 10 '$1' {}\"\n}\nEOF\n\n# \u521b\u5efaripgrep\u914d\u7f6e\u6587\u4ef6\ncat << 'EOF' > ~/.ripgreprc\n# \u9ed8\u8ba4\u914d\u7f6e\n--smart-case\n--hidden\n--follow\n--glob=!.git/*\n\n# \u641c\u7d22\u914d\u7f6e\n--max-columns=150\n--max-columns-preview\n\n# \u989c\u8272\u914d\u7f6e\n--colors=line:fg:yellow\n--colors=line:style:bold\n--colors=path:fg:green\n--colors=path:style:bold\n--colors=match:fg:black\n--colors=match:bg:yellow\n--colors=match:style:nobold\nEOF\n
"},{"location":"Tools/Terminal/Tabby_Zsh/#6","title":"6. \u5b9e\u7528\u5f00\u53d1\u5de5\u5177","text":"Bash# \u5b89\u88c5\u5f00\u53d1\u8f85\u52a9\u5de5\u5177\nsudo apt install -y \\\n shellcheck `# shell\u811a\u672c\u68c0\u67e5` \\\n python3-pip `# Python\u5305\u7ba1\u7406` \\\n nodejs npm `# Node.js\u73af\u5883` \\\n golang `# Go\u8bed\u8a00\u73af\u5883` \\\n docker.io `# Docker\u652f\u6301` \\\n postgresql-client `# \u6570\u636e\u5e93\u5ba2\u6237\u7aef` \\\n redis-tools `# Redis\u5ba2\u6237\u7aef` \\\n mycli `# MySQL\u5ba2\u6237\u7aef` \\\n httpie `# HTTP\u5ba2\u6237\u7aef`\n\n# \u6dfb\u52a0\u5b9e\u7528\u522b\u540d\u548c\u51fd\u6570\ncat << 'EOF' >> ~/.zshrc\n# Docker\u522b\u540d\nalias dk='docker'\nalias dkc='docker-compose'\nalias dkps='docker ps'\nalias dkst='docker stats'\nalias dkimg='docker images'\nalias dkpull='docker pull'\nalias dkexec='docker exec -it'\n\n# \u5f00\u53d1\u8f85\u52a9\u51fd\u6570\n# \u5feb\u901fHTTP\u670d\u52a1\u5668\nserve() {\n local port=\"${1:-8000}\"\n python3 -m http.server \"$port\"\n}\n\n# JSON\u683c\u5f0f\u5316\njson() {\n if [ -t 0 ]; then # \u53c2\u6570\u8f93\u5165\n python -m json.tool <<< \"$*\" | pygmentize -l json\n else # \u7ba1\u9053\u8f93\u5165\n python -m json.tool | pygmentize -l json\n fi\n}\n\n# Git\u5206\u652f\u6e05\u7406\ngit-clean() {\n git branch --merged | egrep -v \"(^\\*|master|main|dev)\" | xargs git branch -d\n}\n\n# \u73af\u5883\u53d8\u91cf\u7ba1\u7406\nenvfile() {\n if [[ -f \"$1\" ]]; then\n set -a\n source \"$1\"\n set +a\n else\n echo \"Error: File $1 not found\"\n return 1\n fi\n}\nEOF\n
"}]}
\ No newline at end of file