├── .gitignore ├── Chapter-04 ├── 4-4 多层感知机代码实现.ipynb ├── 4-6 线性回归代码实现.ipynb └── 4-8 多分类问题代码实现.ipynb ├── Chapter-05 ├── 5-3 过拟合和欠拟合示例.ipynb ├── 5-6 Dropout代码实现.ipynb └── 5-8 模型文件的读写.ipynb ├── Chapter-06 ├── 6-11 梯度下降代码实现.ipynb ├── 6-12 学习率调节器.ipynb ├── 6-6 小批量梯度下降法.ipynb └── 6-8 AdaGrad算法.ipynb ├── Chapter-07 └── 7.6 卷积神经网络代码实现.ipynb ├── Chapter-08 ├── 8.1 AlexNet.ipynb ├── 8.2 VGGNet.ipynb ├── 8.3 批量标准化.ipynb ├── 8.4 GoogLeNet.ipynb ├── 8.5 ResNet.ipynb └── 8.6 DenseNet.ipynb ├── Chapter-09 ├── 9.5 RNN时间序列数据预测.ipynb └── images │ ├── image1.png │ └── image2.png ├── Chapter-10 ├── 10.5 复杂循环神经网络代码实现.ipynb ├── 10.7 序列到序列模型代码实现.ipynb ├── 10.9 机器翻译代码实现-精简版.ipynb ├── 10.9 机器翻译代码实现.ipynb └── data │ └── 有英语-中文普通话对应句 - 2023-02-18.tsv ├── Chapter-11 ├── 11.5 注意力池化.ipynb └── 11.7 Transformer代码实现.ipynb ├── Chapter-12 └── 12.6 GPT模型代码实现.ipynb ├── Chapter-13 └── 13.6 图像生成.ipynb ├── Chapter-14 ├── 14.1 自定义数据加载.ipynb ├── 14.2 图像数据增强.ipynb ├── 14.3 迁移学习.ipynb ├── 14.5 猫狗大战.ipynb └── dataset │ └── url.txt ├── Chapter-15 ├── 15.1 词嵌入和word2vec.ipynb ├── 15.2 词义搜索和句意表示.ipynb ├── 15.4 Huggingface库介绍.ipynb ├── 15.6 项目实战:电影评论情感分类.ipynb └── data │ ├── fairytales.txt │ └── 越女剑.txt ├── README.md └── assets └── catalog.png /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python ### 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # Jupyter Notebook 8 | .ipynb_checkpoints 9 | -------------------------------------------------------------------------------- /Chapter-04/4-4 多层感知机代码实现.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "0b766fe0", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "# 导包\n", 11 | "import torch\n", 12 | "from torchvision import datasets\n", 13 | "from torchvision import transforms\n", 14 | "import torch.nn as nn \n", 15 | "import torch.optim as optim" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "id": "f32c4d1b", 21 | "metadata": {}, 22 | "source": [ 23 | "## data" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 2, 29 | "id": "507db569", 30 | "metadata": { 31 | "scrolled": false 32 | }, 33 | "outputs": [ 34 | { 35 | "name": "stdout", 36 | "output_type": "stream", 37 | "text": [ 38 | "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n", 39 | "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to data/mnist/MNIST/raw/train-images-idx3-ubyte.gz\n" 40 | ] 41 | }, 42 | { 43 | "data": { 44 | "application/vnd.jupyter.widget-view+json": { 45 | "model_id": "a1d2c56523614f5195807d150fa17419", 46 | "version_major": 2, 47 | "version_minor": 0 48 | }, 49 | "text/plain": [ 50 | " 0%| | 0/9912422 [00:00" 190 | ] 191 | }, 192 | "metadata": { 193 | "needs_background": "light" 194 | }, 195 | "output_type": "display_data" 196 | } 197 | ], 198 | "source": [ 199 | "import matplotlib.pyplot as plt\n", 200 | "\n", 201 | "plt.plot(x, y, 'o')\n", 202 | "plt.plot(x_tensor.numpy(), y_pred.detach().numpy())\n", 203 | "plt.show()" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "id": "a6673f9a", 209 | "metadata": {}, 210 | "source": [ 211 | "### 完整代码" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 6, 217 | "id": "b0d2ed6a", 218 | "metadata": {}, 219 | "outputs": [ 220 | { 221 | "name": "stdout", 222 | "output_type": "stream", 223 | "text": [ 224 | "w: tensor([1.9540], requires_grad=True)\n", 225 | "b: tensor([1.0215], requires_grad=True)\n" 226 | ] 227 | } 228 | ], 229 | "source": [ 230 | "import numpy as np\n", 231 | "import torch\n", 232 | "\n", 233 | "# 设置随机数种子,使得每次运行代码生成的数据相同\n", 234 | "np.random.seed(42)\n", 235 | "\n", 236 | "# 生成随机数据,w为2,b为1\n", 237 | "x = np.random.rand(100, 1)\n", 238 | "y = 1 + 2 * x + 0.1 * np.random.randn(100, 1)\n", 239 | "\n", 240 | "# 将数据转换为 pytorch tensor\n", 241 | "x_tensor = torch.from_numpy(x).float()\n", 242 | "y_tensor = torch.from_numpy(y).float()\n", 243 | "\n", 244 | "# 设置超参数\n", 245 | "learning_rate = 0.1\n", 246 | "num_epochs = 1000\n", 247 | "\n", 248 | "# 初始化参数,可以使用常数、随机数或预训练等\n", 249 | "w = torch.randn(1, requires_grad=True)\n", 250 | "b = torch.zeros(1, requires_grad=True)\n", 251 | "\n", 252 | "# 开始训练\n", 253 | "for epoch in range(num_epochs):\n", 254 | " # 计算预测值\n", 255 | " y_pred = x_tensor * w + b\n", 256 | "\n", 257 | " # 计算损失\n", 258 | " loss = ((y_pred - y_tensor) ** 2).mean()\n", 259 | "\n", 260 | " # 反向传播\n", 261 | " loss.backward()\n", 262 | "\n", 263 | " # 更新参数\n", 264 | " with torch.no_grad():\n", 265 | " w -= learning_rate * w.grad\n", 266 | " b -= learning_rate * b.grad\n", 267 | "\n", 268 | " # 清空梯度\n", 269 | " w.grad.zero_()\n", 270 | " b.grad.zero_()\n", 271 | "\n", 272 | "# 输出训练后的参数,与数据生成时设置的常数基本一致\n", 273 | "print('w:', w)\n", 274 | "print('b:', b)" 275 | ] 276 | }, 277 | { 278 | "cell_type": "markdown", 279 | "id": "7b633db9", 280 | "metadata": {}, 281 | "source": [ 282 | "### Pytorch模型实现" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 7, 288 | "id": "85684228", 289 | "metadata": {}, 290 | "outputs": [ 291 | { 292 | "name": "stdout", 293 | "output_type": "stream", 294 | "text": [ 295 | "w: tensor([[1.9540]])\n", 296 | "b: tensor([1.0215])\n" 297 | ] 298 | } 299 | ], 300 | "source": [ 301 | "import numpy as np\n", 302 | "import torch\n", 303 | "import torch.nn as nn\n", 304 | "\n", 305 | "# 设置随机数种子,使得每次运行代码生成的数据相同\n", 306 | "np.random.seed(42)\n", 307 | "\n", 308 | "# 生成随机数据\n", 309 | "x = np.random.rand(100, 1)\n", 310 | "y = 1 + 2 * x + 0.1 * np.random.randn(100, 1)\n", 311 | "\n", 312 | "# 将数据转换为 pytorch tensor\n", 313 | "x_tensor = torch.from_numpy(x).float()\n", 314 | "y_tensor = torch.from_numpy(y).float()\n", 315 | "\n", 316 | "# 设置超参数\n", 317 | "learning_rate = 0.1\n", 318 | "num_epochs = 1000\n", 319 | "\n", 320 | "# 定义输入数据的维度和输出数据的维度\n", 321 | "input_dim = 1\n", 322 | "output_dim = 1\n", 323 | "\n", 324 | "# 定义模型,就是一个神经元\n", 325 | "model = nn.Linear(input_dim, output_dim)\n", 326 | "\n", 327 | "# 定义损失函数和优化器\n", 328 | "criterion = nn.MSELoss()\n", 329 | "optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)\n", 330 | "\n", 331 | "# 开始训练\n", 332 | "for epoch in range(num_epochs):\n", 333 | " # 将输入数据喂给模型\n", 334 | " y_pred = model(x_tensor)\n", 335 | "\n", 336 | " # 计算损失\n", 337 | " loss = criterion(y_pred, y_tensor)\n", 338 | " \n", 339 | " # 清空梯度\n", 340 | " optimizer.zero_grad()\n", 341 | "\n", 342 | " # 反向传播\n", 343 | " loss.backward()\n", 344 | "\n", 345 | " # 更新参数\n", 346 | " optimizer.step()\n", 347 | "\n", 348 | "# 输出训练后的参数\n", 349 | "print('w:', model.weight.data)\n", 350 | "print('b:', model.bias.data)" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": null, 356 | "id": "37131c58", 357 | "metadata": {}, 358 | "outputs": [], 359 | "source": [] 360 | } 361 | ], 362 | "metadata": { 363 | "kernelspec": { 364 | "display_name": "Python 3 (ipykernel)", 365 | "language": "python", 366 | "name": "python3" 367 | }, 368 | "language_info": { 369 | "codemirror_mode": { 370 | "name": "ipython", 371 | "version": 3 372 | }, 373 | "file_extension": ".py", 374 | "mimetype": "text/x-python", 375 | "name": "python", 376 | "nbconvert_exporter": "python", 377 | "pygments_lexer": "ipython3", 378 | "version": "3.8.10" 379 | }, 380 | "toc": { 381 | "base_numbering": 1, 382 | "nav_menu": { 383 | "height": "68px", 384 | "width": "172px" 385 | }, 386 | "number_sections": true, 387 | "sideBar": true, 388 | "skip_h1_title": false, 389 | "title_cell": "Table of Contents", 390 | "title_sidebar": "Contents", 391 | "toc_cell": false, 392 | "toc_position": { 393 | "height": "calc(100% - 180px)", 394 | "left": "10px", 395 | "top": "150px", 396 | "width": "180.6px" 397 | }, 398 | "toc_section_display": true, 399 | "toc_window_display": true 400 | } 401 | }, 402 | "nbformat": 4, 403 | "nbformat_minor": 5 404 | } 405 | -------------------------------------------------------------------------------- /Chapter-05/5-6 Dropout代码实现.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "10eef938", 6 | "metadata": {}, 7 | "source": [ 8 | "### 代码实现" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "142a326f", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# 导入必要的库\n", 19 | "import torch\n", 20 | "import torch.nn as nn\n", 21 | "import matplotlib.pyplot as plt\n", 22 | "\n", 23 | "# 随机数种子\n", 24 | "torch.manual_seed(2333)\n", 25 | "\n", 26 | "# 定义超参数\n", 27 | "num_samples = 20 # 样本数\n", 28 | "hidden_size = 200 # 隐藏层大小\n", 29 | "num_epochs = 500 # 训练轮数" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "id": "cc854ac5", 35 | "metadata": {}, 36 | "source": [ 37 | "### 数据生成" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "id": "c4ebe862", 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8+yak3AAAACXBIWXMAAAsTAAALEwEAmpwYAAAdUklEQVR4nO3df5AV5Z3v8fcXRAaUwBGIAuMIJrhqJSPqFOI1leiqEawt0FljMOWNRlITc/Xe7N4LG4xJLknVvZddqWxCGTVUlo3ZbEW9Oq6kJFcwQqkViQ4UjiAIg+vCABGCw0SiEJHv/aN75ADnMD+6T/c53Z9X1dTp0/2cfr7TZ+Z7nvP000+buyMiItk3KO0AREQkGUr4IiI5oYQvIpITSvgiIjmhhC8ikhNK+CIiORE54ZvZ2Wa2ysxeN7ONZvaNEmXMzBabWYeZtZvZJVHrFRGR/jklhn0cBv6Hu68zsxHAWjNb6e6vF5WZAUwOfy4DHgwfRUQkIZFb+O6+293XhcvvApuACccVmwX83ANrgFFmNi5q3SIi0ndxtPA/YmYTgYuB3x23aQKwo+h5Z7hud4l9tAAtAKeddtql559/fpwhiohk2tq1a//g7mNLbYst4ZvZ6cATwN+4+x8Huh93XwIsAWhqavK2traYIhQRyT4z+49y22IZpWNmQwiS/b+6e2uJIjuBs4ue14frREQkIXGM0jHgn4BN7v6DMsWWAV8OR+tMA7rd/YTuHBERqZw4unSuAP4z8JqZrQ/XfQtoAHD3h4DlwPVAB/Ae8JUY6hURkX6InPDd/UXAeinjwF1R6wL44IMP6Ozs5ODBg3HsrmrV1dVRX1/PkCFD0g5FRDIi1lE6Sejs7GTEiBFMnDiRoDcpe9ydffv20dnZyaRJk9IOR0QyouamVjh48CCjR4/ObLIHMDNGjx6d+W8xIpKsmkv4QKaTfY88/I4ikqyaTPgiItJ/Svj9tH//fh544IF+v+76669n//798QckItJHSvj9VC7hHz58+KSvW758OaNGjapQVCIivau5UTr91t4Ora2wfTs0NEBzMzQ2Dnh38+fPZ9u2bUyZMoUhQ4ZQV1dHoVBg8+bNbNmyhRtuuIEdO3Zw8OBBvvGNb9DS0gLAxIkTaWtr48CBA8yYMYPPfOYz/Pa3v2XChAk89dRTDBs2LK7fWESkpGy38NvbYdEi6OqC+vrgcdGiYP0ALVy4kE984hOsX7+e++67j3Xr1vGjH/2ILVu2ALB06VLWrl1LW1sbixcvZt++fSfsY+vWrdx1111s3LiRUaNG8cQTTww4HhGRvsp2wm9thUIh+Bk06Ohya6npfgZm6tSpx4yVX7x4MRdddBHTpk1jx44dbN269YTXTJo0iSlTpgBw6aWX8tZbb8UWj4hIOdnu0tm+PWjZFxs5Mlgfk9NOO+2j5dWrV/Pss8/y0ksvMXz4cK688sqSY+mHDh360fLgwYN5//33Y4tHRKScbLfwGxqgu/vYdd3dwfoBGjFiBO+++27Jbd3d3RQKBYYPH87mzZtZs2bNgOsREYlbthN+c3PQb9/VBUeOHF1ubh7wLkePHs0VV1zBpz71KebNm3fMtunTp3P48GEuuOAC5s+fz7Rp06L+BiIisbFgXrPqVOoGKJs2beKCCy7o+05iHqWTpH7/riKSe2a21t2bSm3Ldh8+BMm9RhK8iEglZbtLR0REPqKELyKSE0r4IiI5oYQvIpITsSR8M1tqZnvMbEOZ7VeaWbeZrQ9/vhtHvSIi0ndxtfB/BkzvpcwL7j4l/Pl+TPUmbqDTIwP88Ic/5L333os5IhGRvokl4bv788A7ceyr2inhi0itSnIc/uVm9iqwC5jr7huTqDTu666Kp0e+9tpr+fjHP85jjz3GoUOHuPHGG/ne977Hn/70J26++WY6Ozv58MMP+c53vsPbb7/Nrl27uOqqqxgzZgyrVq2K75cUEemDpBL+OuAcdz9gZtcD/wZMLlXQzFqAFoCGCHPewNHZkQuFY2dHnjt34El/4cKFbNiwgfXr17NixQoef/xxXn75ZdydmTNn8vzzz7N3717Gjx/P008/DQRz7IwcOZIf/OAHrFq1ijFjxkT6vUREBiKRUTru/kd3PxAuLweGmFnJrOfuS9y9yd2bxo4dG6neSs+OvGLFClasWMHFF1/MJZdcwubNm9m6dSuf/vSnWblyJd/85jd54YUXGDlyZDwViohEkEgL38zOAt52dzezqQQfNCfeGSRmlZ4d2d255557+NrXvnbCtnXr1rF8+XK+/e1vc/XVV/Pd72pgkoikK65hmb8EXgL+wsw6zWyOmd1pZneGRW4CNoR9+IuB2Z7ArG0VmB35mOmRr7vuOpYuXcqBAwcA2LlzJ3v27GHXrl0MHz6cW2+9lXnz5rFu3boTXisikrRYWvjufksv2+8H7o+jrv5obg767CFo2Xd3B/34c+YMfJ/F0yPPmDGDL33pS1x++eUAnH766fziF7+go6ODefPmMWjQIIYMGcKDDz4IQEtLC9OnT2f8+PE6aSsiicv89Mg1PDuypkcWkX7L9fTImh1ZpHbUcgOtFmguHRGpCj3DqLu6jh1G3d6edmTZUZMJv5q7oeKSh99RpFilh1FLDSb8uro69u3bl+mE6O7s27ePurq6tEMRScz27cHgimJxDqOWGuzDr6+vp7Ozk71796YdSkXV1dVRf/xFBCIZ1tAQdOMUCkfXRR1GLcequYQ/ZMgQJk2alHYYIhKzSgyjlmPVXJeOiGRTY2Mwz1WhAJ2dwWOUea/kRDXXwheR7NIw6spSC19EJCeU8EVEckJdOiIiMan2K4XVwhcRiUEtXCmshC8iEoNauFJYXToiIqEoXTKx3HCpwn1CauGLiBC9SybyDZcS6BNSwhcRIXqXTHNzkKO7uuDIkaPLzc0JBdAHSvgiIkSfvC3ylcIJzB6nPnwREeKZvC3SlcIJzB4X103Ml5rZHjPbUGa7mdliM+sws3YzuySOekVE4hK5S6YGAoirS+dnwPSTbJ8BTA5/WoAHY6pXRCQWqU/elkAAsXTpuPvzZjbxJEVmAT/34K4la8xslJmNc/fdcdQvIhKH1Cdvq3AASfXhTwB2FD3vDNedkPDNrIXgWwANuvOBiNSSKp9boepG6bj7EndvcvemsWPHph2OiEjf1MDcCkm18HcCZxc9rw/XiUg1qfIWalUrHkcPRx9bW6vmGCbVwl8GfDkcrTMN6Fb/vUiVqYEWalWrgbuwx9LCN7NfAlcCY8ysE/ifwBAAd38IWA5cD3QA7wFfiaNeEYlRDbRQq1oN3IU9rlE6t/Sy3YG74qhLRCokltm/ciyGu7BXuket6k7aikhKIs/+VQXa22HBArjjjuAxye6oiOPok+hR09QKIhKIoYWaqp6MWSgcmzGTvHoqwjj6JHrU1MIXkUDql5pGVAt3IDmJJM75qoUvIkdFvdIzzWGdNX4OIolzvmrhi0g80h7WWePnIJKYvE0JX0TikXaXSurTXUaTRI+aunREJB5pd6k0NtI+89u03r+T7TtPoWHCYZrvnkBj43nJ1B+DSk/epoQvIvGIoxM6wjmA9nZYtOw8ChedR/1noasbFi2DuefVznnnSlOXjojEI2qXSsRzAGn3KNUCJXwRiUfUTuiIGbsGprJJnbp0RCQ+UTqhI54DqIGpbFKnFr6IVIeIwyprfJBOIpTwRaQ6RMzYsQxrTHMungRYMJFldWpqavK2tra0wxCRpKR5pW7xXDzFcwnV0vQSgJmtdfemUtvUhy8i1SPNu4jn4H4A6tIREYFcDPNRwhcRgZqfi6cvlPBFRCAXw3xiSfhmNt3M3jCzDjObX2L77Wa218zWhz9fjaNeEZHY1Pr9APog8klbMxsM/Bi4FugEXjGzZe7++nFFH3X3u6PWJyJSMWmeNE5AHC38qUCHu7/p7n8GHgFmxbBfERGJURzDMicAO4qedwKXlSj312b2WWAL8LfuvqNEGcysBWgBaMjQyRKRPEhzGL30LqmTtr8CJrp7I7ASeLhcQXdf4u5N7t40duzYhMITkajSvuGV9C6OhL8TOLvoeX247iPuvs/dD4VPfwpcGkO9IlJFND1x9Ysj4b8CTDazSWZ2KjAbWFZcwMzGFT2dCWyKoV4RqSI5uG6p5kXuw3f3w2Z2N/AMMBhY6u4bzez7QJu7LwP+m5nNBA4D7wC3R61XREpIsRNd0xNXP02eJpIVMUz+FeXzIiNzj9W8k02epittRbIiYid61JOuObhuqeZptkyRrIh4x6g4JovM+HVLNU8JXzIl9XHgaQYQsRM94ueF1AB16UhmpD4OPO0AIk7+lYPJInNPCV8yI/Vx4GkHELETPQeTReaeunQkM1Lvkkg9ACJ1ovd8XhT3SM2Zoz75LFHCl8xIfRx46gFEp5Ou2aYuHcmM1LskUg9A5OSU8CUzUh8HnnoAIienLh3JlNS7JFIPQKQ8JXzJltQH4qcr57++9EJdOpIdMYyDb2+HBQvgjjuCx1qayz3tywCk+inhS3akPJdMHKJ84KR9GYBUPyV8yY6IE7KnnTCjfuBoPnrpjRK+ZEfEuQHSTphRP3A0NYL0RglfsqPG55KJ+oGjywCkN0r4kh01PpdM1A8cXQYgvdEdr0SKpDmsUXeMkjic7I5XsSR8M5sO/IjgnrY/dfeFx20fCvwcuBTYB3zR3d/qbb9K+JI3GkcvUZ0s4Ue+8MrMBgM/Bq4FOoFXzGyZu79eVGwO0OXunzSz2cDfA1+MWrdI1uhCXamkOPrwpwId7v6mu/8ZeASYdVyZWcDD4fLjwNVmZjHULSIifRRHwp8A7Ch63hmuK1nG3Q8D3cDoUjszsxYzazOztr1798YQnoiIQBWO0nH3Je7e5O5NY8eOTTscEZHMiCPh7wTOLnpeH64rWcbMTgFGEpy8FRGRhMSR8F8BJpvZJDM7FZgNLDuuzDLgtnD5JuA5r+bxoCIiGRR5lI67Hzazu4FnCIZlLnX3jWb2faDN3ZcB/wT8i5l1AO8QfCiIiEiCYpkP392XA8uPW/fdouWDwBfiqEtERAam6k7aiohIZSjhi4jkhBK+iEhOKOGLiOSEEr6ISE4o4YuI5IQSvohITijhi4jkRCwXXolIQDcwkWqmFr5ITHpuUdjVBfX1weOiRcF6kWqghC8Sk9bW4H60hQIMGnR0ubU17chEAkr4IjHZvj24+XixkSOD9SLVQAlfJCYNDdDdfey67u5gvUg1UMIXiUlzc9Bv39UFR44cXW5uTjsykYBG6RxHoyxkoBobYe7cY/9+5szR349UDyX8Ij2jLAqFY0dZzJ2rf9qk1PoHbmNjbcUr+aKEX6R4lAUcfWxt1T9xX0VJ2PrApfY/8aSqqQ+/iEZZRBN1HHprKxQ+3Evh1dUM+tVTFF5dTeHDvfkZ1qiB/FJhkVr4ZnYG8CgwEXgLuNndu0qU+xB4LXy63d1nRqm3Uhoagv+xnpY9JD/KopYbeFG/IW1f/w71b74Iw+rgYx+D999n5Gsvsv1PnwPOqFjcx0jzDdBXTKmwqC38+cBv3H0y8JvweSnvu/uU8Kcqkz2kP8qi1ht4Ub8hNex/le5BBRg2DMxg2DC6BxVo2P9q/MGWkvYboK+YUmFRE/4s4OFw+WHghoj7S1XPKItCATo7g8ck+49r/UrNqOPQm0c9R9eRkXS9X8cRh6736+g6MpLmUc/FH2wpab8BGsgvFRb1pO2Z7r47XP49cGaZcnVm1gYcBha6+7+V26GZtQAtAA0p/KGnOcpi+/agYVmslhp4zc1BgxiCuLu7g0bynDl9e33jlMHMHf4MrbsuY3v3KBpG7mfOJ1bTeN7gisV8jLTfgKgHUKQXvSZ8M3sWOKvEpnuLn7i7m5mX2c057r7TzM4FnjOz19x9W6mC7r4EWALQ1NRUbn+ZVA3nEKKIPA69uZnGRYtovGj3sQmveW5F4/5I2m+ABvJLhfWa8N39mnLbzOxtMxvn7rvNbBywp8w+doaPb5rZauBioGTCT12KJ+2y0MCL9A0p7YRXDW+ABvJLBZn7wBvRZnYfsM/dF5rZfOAMd/+748oUgPfc/ZCZjQFeAma5++u97b+pqcnb2toGHF+/FQ8EL/6HT7Ajv5ZH6WSC3gCpcWa21t2bSm2L2oe/EHjMzOYA/wHcHFbYBNzp7l8FLgB+YmZHCE4SL+xLsk9FHMPiIiaMmm/g1XrCrPk3QKS8SC38Sku8hX/HHcFJu0FFg5eOHAmG7Cxd2vvr8/4NoQp+f5G8O1kLX1faFos6LC7lYX1pDyNP+/cXkZPLXsJvb4cFC4LW+oIF/ct2Ua+8SvnCmdTzrS4cEqlq2Ur4UZu4Ua+8SvnCmdTzrS4cEqlq2ZotM46TrlFO2jU30/6tR2jdexnbD51Jw9C3aR77Ao3/O5m5GWIZRh7lJEA1DGsUkbKy1cJPuYnbTiOLbB5dFKhnB10UWGTzaCe5cfyR5gJqb6f9W4+w4NeXcce6u1nw68to/9YjyX1DEpGKylYLP+UrJVtboXBugcKl0wAoAHQlN9lh1OuW2h94kUXbbqDwsSPUj/wjXQcLLNp2A3MfeJHGhxL4hiQiFZWthJ9yl0LaU7FAtHzbumY8hREfUhh2CIDCsIPgQ2ldMz6h7ygiUknZSvgpX5qfeh96RNvtHOr5PTDso3Uj2c92OyeR+kWksrKV8CHVLoXIXzBSvsdfw7RxdK3eQ8Heh7o6OHiQ7ncH0XDluIrXLSKVl62TtkQbhh9V5HOWKQ+kb/76WXR9cipdFDjS/Ue6KND1yak0f73UZKkiUmsyNbVCzV/ZH3VqhxjU+lQ4InlXycnTqkrN3xI07fnY0SAbkSzLVJdO6leaRpX2TXVFJNMylfBr/sp+XbgkIhWUqS6dTFzZrz4VEamQTLXw1UAWESkvUy18UANZRKScTLXwRUSkvEgJ38y+YGYbzexIeB/bcuWmm9kbZtYR3uxcREQSFrWFvwFoBp4vV8DMBgM/BmYAFwK3mNmFEesVEZF+itSH7+6bAMzsZMWmAh3u/mZY9hFgFvB6lLqlDF0qKyJlJNGHPwHYUfS8M1xXkpm1mFmbmbXt3bu34sFlSup3MReRatZrwjezZ81sQ4mfWZUIyN2XuHuTuzeNHTu2ElVkV+p3MReRatZrl467XxOxjp3A2UXP68N1ErdquAOLiFStJLp0XgEmm9kkMzsVmA0sS6De/Kn5uSVEpJKiDsu80cw6gcuBp83smXD9eDNbDuDuh4G7gWeATcBj7r4xWthSkiZfE5GTyNR8+IJG6YjkXG7mwxc0t4SIlKWpFUREckIJX0QkJ5TwRURyQglfRCQnlPBFRHJCCV9EJCeU8EVEckIJX0QkJ5TwRURyQglfRCQnlPBFRHJCCV9EJCeU8EVEckIJX0QkJ5TwRURyQglfRCQnlPBFRHIi6j1tv2BmG83siJmVvKVWWO4tM3vNzNabme5ZKCKSgqi3ONwANAM/6UPZq9z9DxHrExGRAYqU8N19E4CZxRONiIhUTFJ9+A6sMLO1ZtaSUJ0iIlKk1xa+mT0LnFVi073u/lQf6/mMu+80s48DK81ss7s/X6a+FqAFoKGhoY+7FxGR3vSa8N39mqiVuPvO8HGPmT0JTAVKJnx3XwIsAWhqavKodYuISKDiXTpmdpqZjehZBj5PcLJXREQSFHVY5o1m1glcDjxtZs+E68eb2fKw2JnAi2b2KvAy8LS7/78o9YqISP9FHaXzJPBkifW7gOvD5TeBi6LUIyIi0elKWxGRnFDCFxHJCSV8EZGcUMIXEckJJXwRkZxQwhcRyQklfBGRnFDCFxHJCSV8EZGcUMIXEckJJXwRkZxQwhcRyQklfBGRnFDCFxHJCSV8EZGcUMIXEckJJXwRkZxQwhcRyQklfBGRnIh6E/P7zGyzmbWb2ZNmNqpMuelm9oaZdZjZ/Ch1iojIwERt4a8EPuXujcAW4J7jC5jZYODHwAzgQuAWM7swYr0iItJPkRK+u69w98Ph0zVAfYliU4EOd3/T3f8MPALMilKviIj03ykx7usO4NES6ycAO4qedwKXlduJmbUALeHTA2b2xgDjGQP8YYCvrSTF1T+Kq38UV/9kMa5zym3oNeGb2bPAWSU23evuT4Vl7gUOA/86wAA/4u5LgCVR92Nmbe7eFHU/cVNc/aO4+kdx9U/e4uo14bv7NSfbbma3A38FXO3uXqLITuDsouf14ToREUlQ1FE604G/A2a6+3tlir0CTDazSWZ2KjAbWBalXhER6b+oo3TuB0YAK81svZk9BGBm481sOUB4Uvdu4BlgE/CYu2+MWG9fRO4WqhDF1T+Kq38UV//kKi4r3QsjIiJZoyttRURyQglfRCQnajrhm9kXzGyjmR0xs7JDmMpN7RCeSP5duP7R8KRyHHGdYWYrzWxr+FgoUeaq8LxHz89BM7sh3PYzM/v3om1TkoorLPdhUd3LitanebymmNlL4fvdbmZfLNoW6/HqbSoQMxsa/v4d4fGYWLTtnnD9G2Z2XZQ4BhDXfzez18Pj8xszO6doW8n3NKG4bjezvUX1f7Vo223h+77VzG5LOK5/LIppi5ntL9pWkeNlZkvNbI+ZbSiz3cxscRhzu5ldUrQt+rFy95r9AS4A/gJYDTSVKTMY2AacC5wKvApcGG57DJgdLj8EfD2muP4BmB8uzwf+vpfyZwDvAMPD5z8DbqrA8epTXMCBMutTO17AecDkcHk8sBsYFffxOtnfS1GZ/wI8FC7PBh4Nly8Myw8FJoX7GZxgXFcV/Q19vSeuk72nCcV1O3B/ideeAbwZPhbC5UJScR1X/r8CSxM4Xp8FLgE2lNl+PfBrwIBpwO/iPFY13cJ3903u3tuVuCWndjAzA/4SeDws9zBwQ0yhzQr319f93gT82ssPbY1Lf+P6SNrHy923uPvWcHkXsAcYG1P9xfoyFUhxvI8DV4fHZxbwiLsfcvd/BzrC/SUSl7uvKvobKjfVSdyiTJ1yHbDS3d9x9y6CubmmpxTXLcAvY6q7LHd/nqBxV84s4OceWAOMMrNxxHSsajrh91GpqR0mAKOB/X50LqCe9XE40913h8u/B87spfxsTvxj+1/hV7p/NLOhCcdVZ2ZtZramp5uJKjpeZjaVoNW2rWh1XMer3N9LyTLh8egmOD59eW0l4yo2h6Cl2KPUe5pkXH8dvj+Pm1nPhZhVcbzCrq9JwHNFqyt1vHpTLu5YjlWcc+lUhPVhaoc0nCyu4ifu7mZWduxr+On9aYLrFHrcQ5D4TiUYj/tN4PsJxnWOu+80s3OB58zsNYKkNmAxH69/AW5z9yPh6gEfrywys1uBJuBzRatPeE/dfVvpPcTuV8Av3f2QmX2N4NvRXyZUd1/MBh539w+L1qV5vCqm6hO+9zK1Qx+Um9phH8HXpVPCVlq/pnw4WVxm9raZjXP33WGC2nOSXd0MPOnuHxTtu6e1e8jM/hmYm2Rc7r4zfHzTzFYDFwNPkPLxMrOPAU8TfNivKdr3gI9XCX2ZCqSnTKeZnQKMJPh7quQ0In3at5ldQ/Ah+jl3P9Szvsx7GkcC6zUud99X9PSnBOdsel575XGvXR1DTH2Kq8hs4K7iFRU8Xr0pF3csxyoPXTolp3bw4EzIKoL+c4DbgLi+MSwL99eX/Z7QdxgmvZ5+8xuAkmf0KxGXmRV6ukTMbAxwBfB62scrfO+eJOjffPy4bXEer75MBVIc703Ac+HxWQbMtmAUzyRgMvByhFj6FZeZXQz8hGCqkz1F60u+pwnGNa7o6UyCK+4h+Fb7+TC+AvB5jv2mW9G4wtjOJzgJ+lLRukoer94sA74cjtaZBnSHDZp4jlUlzkQn9QPcSNCXdQh4G3gmXD8eWF5U7nqCG7RsI2gd9qw/l+AfsgP4v8DQmOIaDfwG2Ao8C5wRrm8CflpUbiLBJ/eg417/HPAaQeL6BXB6UnEB/yms+9XwcU41HC/gVuADYH3Rz5RKHK9Sfy8EXUQzw+W68PfvCI/HuUWvvTd83RvAjJj/3nuL69nw/6Dn+Czr7T1NKK7/A2wM618FnF/02jvC49gBfCXJuMLnC4CFx72uYseLoHG3O/xb7iQ413IncGe43QhuGLUtrLup6LWRj5WmVhARyYk8dOmIiAhK+CIiuaGELyKSE0r4IiI5oYQvIpITSvgiIjmhhC8ikhP/H0ONPCmRnWJKAAAAAElFTkSuQmCC\n", 49 | "text/plain": [ 50 | "
" 51 | ] 52 | }, 53 | "metadata": { 54 | "needs_background": "light" 55 | }, 56 | "output_type": "display_data" 57 | } 58 | ], 59 | "source": [ 60 | "# 生成训练集\n", 61 | "x_train = torch.unsqueeze(torch.linspace(-1, 1, num_samples), 1)\n", 62 | "y_train = x_train + 0.3 * torch.randn(num_samples, 1)\n", 63 | "\n", 64 | "# 测试集\n", 65 | "x_test = torch.unsqueeze(torch.linspace(-1, 1, num_samples), 1)\n", 66 | "y_test = x_test + 0.3 * torch.randn(num_samples, 1)\n", 67 | "\n", 68 | "# 绘制训练集和测试集\n", 69 | "plt.scatter(x_train, y_train, c='r', alpha=0.5, label='train')\n", 70 | "plt.scatter(x_test, y_test, c='b', alpha=0.5, label='test')\n", 71 | "plt.legend(loc='upper left')\n", 72 | "plt.ylim((-2, 2))\n", 73 | "plt.show()" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "id": "112f71f2", 79 | "metadata": {}, 80 | "source": [ 81 | "### 模型定义" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 3, 87 | "id": "6e4f5e40", 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "# 定义一个可能会过拟合的网络\n", 92 | "net_overfitting = torch.nn.Sequential(\n", 93 | " torch.nn.Linear(1, hidden_size),\n", 94 | " torch.nn.ReLU(),\n", 95 | " torch.nn.Linear(hidden_size, hidden_size),\n", 96 | " torch.nn.ReLU(),\n", 97 | " torch.nn.Linear(hidden_size, 1),\n", 98 | ")\n", 99 | "\n", 100 | "# 定义一个包含 Dropout 的网络\n", 101 | "net_dropout = torch.nn.Sequential(\n", 102 | " torch.nn.Linear(1, hidden_size),\n", 103 | " torch.nn.Dropout(0.5), # p=0.5\n", 104 | " torch.nn.ReLU(),\n", 105 | " torch.nn.Linear(hidden_size, hidden_size),\n", 106 | " torch.nn.Dropout(0.5), # p=0.5\n", 107 | " torch.nn.ReLU(),\n", 108 | " torch.nn.Linear(hidden_size, 1),\n", 109 | ")" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "id": "729631eb", 115 | "metadata": {}, 116 | "source": [ 117 | "### 模型训练" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 4, 123 | "id": "489c6ba6", 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "# 定义优化器和损失函数\n", 128 | "optimizer_overfitting = torch.optim.Adam(net_overfitting.parameters(), lr=0.01)\n", 129 | "optimizer_dropout = torch.optim.Adam(net_dropout.parameters(), lr=0.01)\n", 130 | "\n", 131 | "# 损失函数\n", 132 | "criterion = nn.MSELoss()\n", 133 | "\n", 134 | "# 分别进行训练\n", 135 | "for i in range(num_epochs):\n", 136 | " # overfitting的网络:预测、损失函数、反向传播\n", 137 | " pred_overfitting = net_overfitting(x_train)\n", 138 | " loss_overfitting = criterion(pred_overfitting, y_train)\n", 139 | " optimizer_overfitting.zero_grad()\n", 140 | " loss_overfitting.backward()\n", 141 | " optimizer_overfitting.step()\n", 142 | " \n", 143 | " # 包含dropout的网络:预测、损失函数、反向传播\n", 144 | " pred_dropout = net_dropout(x_train)\n", 145 | " loss_dropout = criterion(pred_dropout, y_train)\n", 146 | " optimizer_dropout.zero_grad()\n", 147 | " loss_dropout.backward()\n", 148 | " optimizer_dropout.step()" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "447bcd89", 154 | "metadata": {}, 155 | "source": [ 156 | "### 预测和可视化" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 5, 162 | "id": "42c10551", 163 | "metadata": {}, 164 | "outputs": [ 165 | { 166 | "data": { 167 | "image/png": "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\n", 168 | "text/plain": [ 169 | "
" 170 | ] 171 | }, 172 | "metadata": { 173 | "needs_background": "light" 174 | }, 175 | "output_type": "display_data" 176 | } 177 | ], 178 | "source": [ 179 | "# 在测试过程中不使用 Dropout\n", 180 | "net_overfitting.eval()\n", 181 | "net_dropout.eval()\n", 182 | "\n", 183 | "# 预测\n", 184 | "test_pred_overfitting = net_overfitting(x_test)\n", 185 | "test_pred_dropout = net_dropout(x_test)\n", 186 | "\n", 187 | "# 绘制拟合效果\n", 188 | "plt.scatter(x_train, y_train, c='r', alpha=0.3, label='train')\n", 189 | "plt.scatter(x_test, y_test, c='b', alpha=0.3, label='test')\n", 190 | "plt.plot(x_test, test_pred_overfitting.data.numpy(), 'r-', lw=2, label='overfitting')\n", 191 | "plt.plot(x_test, test_pred_dropout.data.numpy(), 'b--', lw=2, label='dropout')\n", 192 | "plt.legend(loc='upper left')\n", 193 | "plt.ylim((-2, 2))\n", 194 | "plt.show()" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "id": "f4d4fe39", 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [] 204 | } 205 | ], 206 | "metadata": { 207 | "kernelspec": { 208 | "display_name": "Python 3 (ipykernel)", 209 | "language": "python", 210 | "name": "python3" 211 | }, 212 | "language_info": { 213 | "codemirror_mode": { 214 | "name": "ipython", 215 | "version": 3 216 | }, 217 | "file_extension": ".py", 218 | "mimetype": "text/x-python", 219 | "name": "python", 220 | "nbconvert_exporter": "python", 221 | "pygments_lexer": "ipython3", 222 | "version": "3.8.10" 223 | } 224 | }, 225 | "nbformat": 4, 226 | "nbformat_minor": 5 227 | } 228 | -------------------------------------------------------------------------------- /Chapter-05/5-8 模型文件的读写.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "29c26766", 6 | "metadata": {}, 7 | "source": [ 8 | "# 张量的保存和加载" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "d709ab87", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "id": "588159e8", 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "data": { 29 | "text/plain": [ 30 | "tensor([0.8608, 0.6997, 0.4133, 0.6113, 0.5393, 0.8223])" 31 | ] 32 | }, 33 | "execution_count": 2, 34 | "metadata": {}, 35 | "output_type": "execute_result" 36 | } 37 | ], 38 | "source": [ 39 | "a = torch.rand(6)\n", 40 | "a" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 3, 46 | "id": "43aa15a3", 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "torch.save(a,\"model/tensor_a\")" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 4, 56 | "id": "3589ec6b", 57 | "metadata": {}, 58 | "outputs": [ 59 | { 60 | "data": { 61 | "text/plain": [ 62 | "tensor([0.8608, 0.6997, 0.4133, 0.6113, 0.5393, 0.8223])" 63 | ] 64 | }, 65 | "execution_count": 4, 66 | "metadata": {}, 67 | "output_type": "execute_result" 68 | } 69 | ], 70 | "source": [ 71 | "torch.load(\"model/tensor_a\")" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 5, 77 | "id": "05bf71bf", 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "data": { 82 | "text/plain": [ 83 | "[tensor([0.6443, 0.6780, 0.9844, 0.3475, 0.3763, 0.9680]),\n", 84 | " tensor([0.0351, 0.3652, 0.9474, 0.5658, 0.5001, 0.7580]),\n", 85 | " tensor([0.5543, 0.2713, 0.3125, 0.0378, 0.0676, 0.2208])]" 86 | ] 87 | }, 88 | "execution_count": 5, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "a = torch.rand(6)\n", 95 | "b = torch.rand(6)\n", 96 | "c = torch.rand(6)\n", 97 | "[a,b,c]" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 6, 103 | "id": "6d5eb6ed", 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "torch.save([a,b,c],\"model/tensor_abc\")" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 7, 113 | "id": "5bac7f09", 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/plain": [ 119 | "[tensor([0.6443, 0.6780, 0.9844, 0.3475, 0.3763, 0.9680]),\n", 120 | " tensor([0.0351, 0.3652, 0.9474, 0.5658, 0.5001, 0.7580]),\n", 121 | " tensor([0.5543, 0.2713, 0.3125, 0.0378, 0.0676, 0.2208])]" 122 | ] 123 | }, 124 | "execution_count": 7, 125 | "metadata": {}, 126 | "output_type": "execute_result" 127 | } 128 | ], 129 | "source": [ 130 | "torch.load(\"model/tensor_abc\")" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 8, 136 | "id": "1391dbc8", 137 | "metadata": {}, 138 | "outputs": [ 139 | { 140 | "data": { 141 | "text/plain": [ 142 | "{'a': tensor([0.6443, 0.6780, 0.9844, 0.3475, 0.3763, 0.9680]),\n", 143 | " 'b': tensor([0.0351, 0.3652, 0.9474, 0.5658, 0.5001, 0.7580]),\n", 144 | " 'c': tensor([0.5543, 0.2713, 0.3125, 0.0378, 0.0676, 0.2208])}" 145 | ] 146 | }, 147 | "execution_count": 8, 148 | "metadata": {}, 149 | "output_type": "execute_result" 150 | } 151 | ], 152 | "source": [ 153 | "tensor_dict= {'a':a,'b':b,'c':c}\n", 154 | "tensor_dict" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 9, 160 | "id": "4a87f7ae", 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "torch.save(tensor_dict,\"model/tensor_dict_abc\")" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 13, 170 | "id": "c374d5e6", 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "data": { 175 | "text/plain": [ 176 | "{'a': tensor([0.6443, 0.6780, 0.9844, 0.3475, 0.3763, 0.9680]),\n", 177 | " 'b': tensor([0.0351, 0.3652, 0.9474, 0.5658, 0.5001, 0.7580]),\n", 178 | " 'c': tensor([0.5543, 0.2713, 0.3125, 0.0378, 0.0676, 0.2208])}" 179 | ] 180 | }, 181 | "execution_count": 13, 182 | "metadata": {}, 183 | "output_type": "execute_result" 184 | } 185 | ], 186 | "source": [ 187 | "torch.load(\"model/tensor_dict_abc\")" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "id": "f5c3641a", 193 | "metadata": {}, 194 | "source": [ 195 | "# 模型的保存与加载" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 15, 201 | "id": "592d73a7", 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "from torchvision import datasets\n", 206 | "from torchvision import transforms\n", 207 | "import torch.nn as nn \n", 208 | "import torch.optim as optim\n", 209 | "\n", 210 | "# 定义 MLP 网络 继承nn.Module\n", 211 | "class MLP(nn.Module):\n", 212 | " \n", 213 | " # 初始化方法\n", 214 | " # input_size输入数据的维度 \n", 215 | " # hidden_size 隐藏层的大小\n", 216 | " # num_classes 输出分类的数量\n", 217 | " def __init__(self, input_size, hidden_size, num_classes):\n", 218 | " # 调用父类的初始化方法\n", 219 | " super(MLP, self).__init__()\n", 220 | " # 定义第1个全连接层 \n", 221 | " self.fc1 = nn.Linear(input_size, hidden_size)\n", 222 | " # 定义激活函数\n", 223 | " self.relu = nn.ReLU()\n", 224 | " # 定义第2个全连接层\n", 225 | " self.fc2 = nn.Linear(hidden_size, hidden_size)\n", 226 | " # 定义第3个全连接层\n", 227 | " self.fc3 = nn.Linear(hidden_size, num_classes)\n", 228 | " \n", 229 | " # 定义forward函数\n", 230 | " # x 输入的数据\n", 231 | " def forward(self, x):\n", 232 | " # 第一层运算\n", 233 | " out = self.fc1(x)\n", 234 | " # 将上一步结果送给激活函数\n", 235 | " out = self.relu(out)\n", 236 | " # 将上一步结果送给fc2\n", 237 | " out = self.fc2(out)\n", 238 | " # 同样将结果送给激活函数\n", 239 | " out = self.relu(out)\n", 240 | " # 将上一步结果传递给fc3\n", 241 | " out = self.fc3(out)\n", 242 | " # 返回结果\n", 243 | " return out\n", 244 | " \n", 245 | "# 定义参数 \n", 246 | "input_size = 28 * 28 # 输入大小\n", 247 | "hidden_size = 512 # 隐藏层大小\n", 248 | "num_classes = 10 # 输出大小(类别数) \n", 249 | "\n", 250 | "# 初始化MLP \n", 251 | "model = MLP(input_size, hidden_size, num_classes)" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "id": "0c1fbe9d", 257 | "metadata": {}, 258 | "source": [ 259 | "### 方式1" 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": 16, 265 | "id": "851bcb3e", 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [ 269 | "# 保存模型参数\n", 270 | "torch.save(model.state_dict(),\"model/mlp_state_dict.pth\")" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": 17, 276 | "id": "d555cb3e", 277 | "metadata": {}, 278 | "outputs": [ 279 | { 280 | "data": { 281 | "text/plain": [ 282 | "" 283 | ] 284 | }, 285 | "execution_count": 17, 286 | "metadata": {}, 287 | "output_type": "execute_result" 288 | } 289 | ], 290 | "source": [ 291 | "# 读取保存的模型参数\n", 292 | "mlp_state_dict = torch.load(\"model/mlp_state_dict.pth\")\n", 293 | "\n", 294 | "# 新实例化一个MLP模型\n", 295 | "model_load = MLP(input_size,hidden_size,num_classes)\n", 296 | "\n", 297 | "# 调用load_state_dict方法 传入读取的参数\n", 298 | "model_load.load_state_dict(mlp_state_dict)" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "id": "ff83264f", 304 | "metadata": {}, 305 | "source": [ 306 | "### 方式2" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": 25, 312 | "id": "f10908c0", 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "# 保存整个模型\n", 317 | "torch.save(model,\"model/mlp_model.pth\")" 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": 26, 323 | "id": "8de54658", 324 | "metadata": {}, 325 | "outputs": [], 326 | "source": [ 327 | "# 加载整个模型\n", 328 | "mlp_load = torch.load(\"model/mlp_model.pth\")" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "id": "1ef9f302", 334 | "metadata": {}, 335 | "source": [ 336 | "### 方式3 : checkpoint" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": null, 342 | "id": "05ddf837", 343 | "metadata": {}, 344 | "outputs": [], 345 | "source": [ 346 | "# 保存参数\n", 347 | "torch.save({\n", 348 | " 'epoch': epoch,\n", 349 | " 'model_state_dict': model.state_dict(),\n", 350 | " 'optimizer_state_dict': optimizer.state_dict(),\n", 351 | " 'loss': loss,\n", 352 | " ...\n", 353 | " }, PATH)" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": null, 359 | "id": "098aa0b0", 360 | "metadata": {}, 361 | "outputs": [], 362 | "source": [ 363 | "# 加载参数\n", 364 | "model = TheModelClass(*args, **kwargs)\n", 365 | "optimizer = TheOptimizerClass(*args, **kwargs)\n", 366 | "\n", 367 | "checkpoint = torch.load(PATH)\n", 368 | "model.load_state_dict(checkpoint['model_state_dict'])\n", 369 | "optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n", 370 | "epoch = checkpoint['epoch']\n", 371 | "loss = checkpoint['loss']\n", 372 | "\n", 373 | "model.eval()" 374 | ] 375 | } 376 | ], 377 | "metadata": { 378 | "kernelspec": { 379 | "display_name": "Python 3 (ipykernel)", 380 | "language": "python", 381 | "name": "python3" 382 | }, 383 | "language_info": { 384 | "codemirror_mode": { 385 | "name": "ipython", 386 | "version": 3 387 | }, 388 | "file_extension": ".py", 389 | "mimetype": "text/x-python", 390 | "name": "python", 391 | "nbconvert_exporter": "python", 392 | "pygments_lexer": "ipython3", 393 | "version": "3.8.10" 394 | } 395 | }, 396 | "nbformat": 4, 397 | "nbformat_minor": 5 398 | } 399 | -------------------------------------------------------------------------------- /Chapter-06/6-8 AdaGrad算法.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 代码实现" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 2, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "data": { 17 | "image/png": "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\n", 18 | "text/plain": [ 19 | "
" 20 | ] 21 | }, 22 | "metadata": { 23 | "needs_background": "light" 24 | }, 25 | "output_type": "display_data" 26 | } 27 | ], 28 | "source": [ 29 | "import torch\n", 30 | "import matplotlib.pyplot as plt\n", 31 | "\n", 32 | "# 假设我们有一个简单的线性回归模型\n", 33 | "# y = w * x + b\n", 34 | "# 其中 w 和 b 是需要学习的参数\n", 35 | "\n", 36 | "# 定义超参数\n", 37 | "learning_rate = 0.01\n", 38 | "num_epochs = 100\n", 39 | "\n", 40 | "# 随机生成训练数据\n", 41 | "X = torch.randn(100, 1)\n", 42 | "y = 2 * X + 3 + torch.randn(100, 1)\n", 43 | "\n", 44 | "# 初始化参数\n", 45 | "w = torch.zeros(1, requires_grad=True)\n", 46 | "b = torch.zeros(1, requires_grad=True)\n", 47 | "\n", 48 | "# 创建 Adagrad optimizer\n", 49 | "optimizer = torch.optim.Adagrad([w, b], lr=learning_rate)\n", 50 | "\n", 51 | "# 记录每次迭代的 loss\n", 52 | "losses = []\n", 53 | "\n", 54 | "# 训练模型\n", 55 | "for epoch in range(num_epochs):\n", 56 | " # 计算预测值\n", 57 | " y_pred = w * X + b\n", 58 | "\n", 59 | " # 计算 loss\n", 60 | " loss = torch.mean((y_pred - y) ** 2)\n", 61 | "\n", 62 | " # 记录 loss\n", 63 | " losses.append(loss.item())\n", 64 | "\n", 65 | " # 清空上一步的梯度\n", 66 | " optimizer.zero_grad()\n", 67 | "\n", 68 | " # 计算梯度\n", 69 | " loss.backward()\n", 70 | "\n", 71 | " # 更新参数\n", 72 | " optimizer.step()\n", 73 | "\n", 74 | "# 可视化训练过程\n", 75 | "plt.plot(losses)\n", 76 | "plt.xlabel('Epoch')\n", 77 | "plt.ylabel('Loss')\n", 78 | "plt.show()" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": "Python 3 (ipykernel)", 92 | "language": "python", 93 | "name": "python3" 94 | }, 95 | "language_info": { 96 | "codemirror_mode": { 97 | "name": "ipython", 98 | "version": 3 99 | }, 100 | "file_extension": ".py", 101 | "mimetype": "text/x-python", 102 | "name": "python", 103 | "nbconvert_exporter": "python", 104 | "pygments_lexer": "ipython3", 105 | "version": "3.8.10" 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 4 110 | } 111 | -------------------------------------------------------------------------------- /Chapter-07/7.6 卷积神经网络代码实现.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b72b1d2b", 6 | "metadata": {}, 7 | "source": [ 8 | "### 代码实现" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "6ba3f730", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# 导入必要的库,torchinfo用于查看模型结构\n", 19 | "import torch\n", 20 | "import torch.nn as nn\n", 21 | "from torchinfo import summary" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "257bddce", 27 | "metadata": {}, 28 | "source": [ 29 | "### 模型定义" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "id": "d87c584f", 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "# 定义LeNet的网络结构\n", 40 | "class LeNet(nn.Module):\n", 41 | " def __init__(self, num_classes=10):\n", 42 | " super(LeNet, self).__init__()\n", 43 | " # 卷积层1:输入1个通道,输出6个通道,卷积核大小为5x5\n", 44 | " self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n", 45 | " # 卷积层2:输入6个通道,输出16个通道,卷积核大小为5x5\n", 46 | " self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)\n", 47 | " # 全连接层1:输入16x4x4=256个节点,输出120个节点,由于输入数据略有差异,修改为16x4x4\n", 48 | " self.fc1 = nn.Linear(in_features=16 * 4 * 4, out_features=120)\n", 49 | " # 全连接层2:输入120个节点,输出84个节点\n", 50 | " self.fc2 = nn.Linear(in_features=120, out_features=84)\n", 51 | " # 输出层:输入84个节点,输出10个节点\n", 52 | " self.fc3 = nn.Linear(in_features=84, out_features=num_classes)\n", 53 | "\n", 54 | " def forward(self, x):\n", 55 | " # 使用ReLU激活函数,并进行最大池化\n", 56 | " x = torch.relu(self.conv1(x))\n", 57 | " x = nn.functional.max_pool2d(x, kernel_size=2)\n", 58 | " # 使用ReLU激活函数,并进行最大池化\n", 59 | " x = torch.relu(self.conv2(x))\n", 60 | " x = nn.functional.max_pool2d(x, kernel_size=2)\n", 61 | " # 将多维张量展平为一维张量\n", 62 | " x = x.view(-1, 16 * 4 * 4)\n", 63 | " # 全连接层\n", 64 | " x = torch.relu(self.fc1(x))\n", 65 | " # 全连接层\n", 66 | " x = torch.relu(self.fc2(x))\n", 67 | " # 全连接层\n", 68 | " x = self.fc3(x)\n", 69 | " return x" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "id": "c0a6dbeb", 75 | "metadata": {}, 76 | "source": [ 77 | "### 网络结构" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 3, 83 | "id": "42692239", 84 | "metadata": { 85 | "scrolled": true 86 | }, 87 | "outputs": [ 88 | { 89 | "data": { 90 | "text/plain": [ 91 | "==========================================================================================\n", 92 | "Layer (type:depth-idx) Output Shape Param #\n", 93 | "==========================================================================================\n", 94 | "LeNet [1, 10] --\n", 95 | "├─Conv2d: 1-1 [1, 6, 24, 24] 156\n", 96 | "├─Conv2d: 1-2 [1, 16, 8, 8] 2,416\n", 97 | "├─Linear: 1-3 [1, 120] 30,840\n", 98 | "├─Linear: 1-4 [1, 84] 10,164\n", 99 | "├─Linear: 1-5 [1, 10] 850\n", 100 | "==========================================================================================\n", 101 | "Total params: 44,426\n", 102 | "Trainable params: 44,426\n", 103 | "Non-trainable params: 0\n", 104 | "Total mult-adds (M): 0.29\n", 105 | "==========================================================================================\n", 106 | "Input size (MB): 0.00\n", 107 | "Forward/backward pass size (MB): 0.04\n", 108 | "Params size (MB): 0.18\n", 109 | "Estimated Total Size (MB): 0.22\n", 110 | "==========================================================================================" 111 | ] 112 | }, 113 | "execution_count": 3, 114 | "metadata": {}, 115 | "output_type": "execute_result" 116 | } 117 | ], 118 | "source": [ 119 | "# 查看模型结构及参数量,input_size表示示例输入数据的维度信息\n", 120 | "summary(LeNet(), input_size=(1, 1, 28, 28))" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "id": "25bbfb1c", 126 | "metadata": {}, 127 | "source": [ 128 | "### 模型训练" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 4, 134 | "id": "04cbc625", 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "name": "stdout", 139 | "output_type": "stream", 140 | "text": [ 141 | "Epoch: 0 Loss: 2.7325645021239664 Acc: 0.2633\n", 142 | "Epoch: 2 Loss: 2.630008887238046 Acc: 0.6901 \n", 143 | "Epoch: 4 Loss: 1.9096679044736495 Acc: 0.9047 \n", 144 | "Epoch: 6 Loss: 1.7179356540642037 Acc: 0.9424 \n", 145 | "Epoch: 8 Loss: 1.5851480201856594 Acc: 0.9413 \n", 146 | "100%|██████████| 10/10 [01:46<00:00, 10.65s/it]\n" 147 | ] 148 | }, 149 | { 150 | "data": { 151 | "image/png": "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\n", 152 | "text/plain": [ 153 | "
" 154 | ] 155 | }, 156 | "metadata": { 157 | "needs_background": "light" 158 | }, 159 | "output_type": "display_data" 160 | }, 161 | { 162 | "name": "stdout", 163 | "output_type": "stream", 164 | "text": [ 165 | "Accuracy: 0.9628\n" 166 | ] 167 | } 168 | ], 169 | "source": [ 170 | "# 导入必要的库\n", 171 | "import torch\n", 172 | "import torch.nn as nn\n", 173 | "import torch.optim as optim\n", 174 | "from torch.utils.data import DataLoader\n", 175 | "from torchvision import datasets, transforms\n", 176 | "from tqdm import * # tqdm用于显示进度条并评估任务时间开销\n", 177 | "import numpy as np\n", 178 | "import sys\n", 179 | "\n", 180 | "# 设置随机种子\n", 181 | "torch.manual_seed(0)\n", 182 | "\n", 183 | "# 定义模型、优化器、损失函数\n", 184 | "model = LeNet()\n", 185 | "optimizer = optim.SGD(model.parameters(), lr=0.02)\n", 186 | "criterion = nn.CrossEntropyLoss()\n", 187 | "\n", 188 | "# 设置数据变换和数据加载器\n", 189 | "transform = transforms.Compose([\n", 190 | " transforms.ToTensor(), # 将数据转换为张量\n", 191 | "])\n", 192 | "\n", 193 | "# 加载训练数据\n", 194 | "train_dataset = datasets.MNIST(root='../data/mnist/', train=True, download=True, transform=transform)\n", 195 | "# 实例化训练数据加载器\n", 196 | "train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True)\n", 197 | "# 加载测试数据\n", 198 | "test_dataset = datasets.MNIST(root='../data/mnist/', train=False, download=True, transform=transform)\n", 199 | "# 实例化测试数据加载器\n", 200 | "test_loader = DataLoader(test_dataset, batch_size=256, shuffle=False)\n", 201 | "\n", 202 | "# 设置epoch数并开始训练\n", 203 | "num_epochs = 10 # 设置epoch数\n", 204 | "loss_history = [] # 创建损失历史记录列表\n", 205 | "acc_history = [] # 创建准确率历史记录列表\n", 206 | "\n", 207 | "# tqdm用于显示进度条并评估任务时间开销\n", 208 | "for epoch in tqdm(range(num_epochs), file=sys.stdout):\n", 209 | " # 记录损失和预测正确数\n", 210 | " total_loss = 0\n", 211 | " total_correct = 0\n", 212 | " \n", 213 | " # 批量训练\n", 214 | " model.train()\n", 215 | " for inputs, labels in train_loader:\n", 216 | "\n", 217 | " # 预测、损失函数、反向传播\n", 218 | " optimizer.zero_grad()\n", 219 | " outputs = model(inputs)\n", 220 | " loss = criterion(outputs, labels)\n", 221 | " loss.backward()\n", 222 | " optimizer.step()\n", 223 | " \n", 224 | " # 记录训练集loss\n", 225 | " total_loss += loss.item()\n", 226 | " \n", 227 | " # 测试模型,不计算梯度\n", 228 | " model.eval()\n", 229 | " with torch.no_grad():\n", 230 | " for inputs, labels in test_loader:\n", 231 | "\n", 232 | " # 预测\n", 233 | " outputs = model(inputs)\n", 234 | " # 记录测试集预测正确数\n", 235 | " total_correct += (outputs.argmax(1) == labels).sum().item()\n", 236 | " \n", 237 | " # 记录训练集损失和测试集准确率\n", 238 | " loss_history.append(np.log10(total_loss)) # 将损失加入损失历史记录列表,由于数值有时较大,这里取对数\n", 239 | " acc_history.append(total_correct / len(test_dataset))# 将准确率加入准确率历史记录列表\n", 240 | " \n", 241 | " # 打印中间值\n", 242 | " if epoch % 2 == 0:\n", 243 | " tqdm.write(\"Epoch: {0} Loss: {1} Acc: {2}\".format(epoch, loss_history[-1], acc_history[-1]))\n", 244 | "\n", 245 | "# 使用Matplotlib绘制损失和准确率的曲线图\n", 246 | "import matplotlib.pyplot as plt\n", 247 | "plt.plot(loss_history, label='loss')\n", 248 | "plt.plot(acc_history, label='accuracy')\n", 249 | "plt.legend()\n", 250 | "plt.show()\n", 251 | "\n", 252 | "# 输出准确率\n", 253 | "print(\"Accuracy:\", acc_history[-1])" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "id": "af348896", 260 | "metadata": {}, 261 | "outputs": [], 262 | "source": [] 263 | } 264 | ], 265 | "metadata": { 266 | "kernelspec": { 267 | "display_name": "Python 3 (ipykernel)", 268 | "language": "python", 269 | "name": "python3" 270 | }, 271 | "language_info": { 272 | "codemirror_mode": { 273 | "name": "ipython", 274 | "version": 3 275 | }, 276 | "file_extension": ".py", 277 | "mimetype": "text/x-python", 278 | "name": "python", 279 | "nbconvert_exporter": "python", 280 | "pygments_lexer": "ipython3", 281 | "version": "3.8.10" 282 | } 283 | }, 284 | "nbformat": 4, 285 | "nbformat_minor": 5 286 | } 287 | -------------------------------------------------------------------------------- /Chapter-08/8.3 批量标准化.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "03c6be7c", 6 | "metadata": {}, 7 | "source": [ 8 | "### 代码实现" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "3ecb9916", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# 导入必要的库,torchinfo用于查看模型结构\n", 19 | "import torch\n", 20 | "import torch.nn as nn\n", 21 | "from torchinfo import summary" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "2a980a08", 27 | "metadata": {}, 28 | "source": [ 29 | "### 结构定义" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "id": "72e3dcde", 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "# 定义LeNet的网络结构\n", 40 | "class LeNet(nn.Module):\n", 41 | " def __init__(self):\n", 42 | " super(LeNet, self).__init__()\n", 43 | " # 卷积层1:输入1个通道,输出6个通道,卷积核大小为5x5,后接BN\n", 44 | " self.conv1 = nn.Sequential(\n", 45 | " nn.Conv2d(1, 6, 5),\n", 46 | " nn.BatchNorm2d(6)\n", 47 | " )\n", 48 | " # 卷积层2:输入6个通道,输出16个通道,卷积核大小为5x5,后接BN\n", 49 | " self.conv2 = nn.Sequential(\n", 50 | " nn.Conv2d(6, 16, 5),\n", 51 | " nn.BatchNorm2d(16)\n", 52 | " )\n", 53 | " # 全连接层1:输入16x4x4=256个节点,输出120个节点,由于输入数据略有差异,修改为16x4x4\n", 54 | " self.fc1 = nn.Sequential(\n", 55 | " nn.Linear(16 * 4 * 4, 120),\n", 56 | " nn.BatchNorm1d(120)\n", 57 | " )\n", 58 | " # 全连接层2:输入120个节点,输出84个节点\n", 59 | " self.fc2 = nn.Sequential(\n", 60 | " nn.Linear(120, 84),\n", 61 | " nn.BatchNorm1d(84)\n", 62 | " )\n", 63 | " # 输出层:输入84个节点,输出10个节点\n", 64 | " self.fc3 = nn.Linear(84, 10)\n", 65 | "\n", 66 | " def forward(self, x):\n", 67 | " # 使用ReLU激活函数,并进行最大池化\n", 68 | " x = torch.relu(self.conv1(x))\n", 69 | " x = nn.functional.max_pool2d(x, 2)\n", 70 | " # 使用ReLU激活函数,并进行最大池化\n", 71 | " x = torch.relu(self.conv2(x))\n", 72 | " x = nn.functional.max_pool2d(x, 2)\n", 73 | " # 将多维张量展平为一维张量\n", 74 | " x = x.view(-1, 16 * 4 * 4)\n", 75 | " # 全连接层\n", 76 | " x = torch.relu(self.fc1(x))\n", 77 | " # 全连接层\n", 78 | " x = torch.relu(self.fc2(x))\n", 79 | " # 全连接层\n", 80 | " x = self.fc3(x)\n", 81 | " return x" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "id": "05abf6fa", 87 | "metadata": {}, 88 | "source": [ 89 | "### 网络结构" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 3, 95 | "id": "e1529d62", 96 | "metadata": { 97 | "scrolled": false 98 | }, 99 | "outputs": [ 100 | { 101 | "data": { 102 | "text/plain": [ 103 | "==========================================================================================\n", 104 | "Layer (type:depth-idx) Output Shape Param #\n", 105 | "==========================================================================================\n", 106 | "LeNet [1, 10] --\n", 107 | "├─Sequential: 1-1 [1, 6, 24, 24] --\n", 108 | "│ └─Conv2d: 2-1 [1, 6, 24, 24] 156\n", 109 | "│ └─BatchNorm2d: 2-2 [1, 6, 24, 24] 12\n", 110 | "├─Sequential: 1-2 [1, 16, 8, 8] --\n", 111 | "│ └─Conv2d: 2-3 [1, 16, 8, 8] 2,416\n", 112 | "│ └─BatchNorm2d: 2-4 [1, 16, 8, 8] 32\n", 113 | "├─Sequential: 1-3 [1, 120] --\n", 114 | "│ └─Linear: 2-5 [1, 120] 30,840\n", 115 | "│ └─BatchNorm1d: 2-6 [1, 120] 240\n", 116 | "├─Sequential: 1-4 [1, 84] --\n", 117 | "│ └─Linear: 2-7 [1, 84] 10,164\n", 118 | "│ └─BatchNorm1d: 2-8 [1, 84] 168\n", 119 | "├─Linear: 1-5 [1, 10] 850\n", 120 | "==========================================================================================\n", 121 | "Total params: 44,878\n", 122 | "Trainable params: 44,878\n", 123 | "Non-trainable params: 0\n", 124 | "Total mult-adds (M): 0.29\n", 125 | "==========================================================================================\n", 126 | "Input size (MB): 0.00\n", 127 | "Forward/backward pass size (MB): 0.08\n", 128 | "Params size (MB): 0.18\n", 129 | "Estimated Total Size (MB): 0.26\n", 130 | "==========================================================================================" 131 | ] 132 | }, 133 | "execution_count": 3, 134 | "metadata": {}, 135 | "output_type": "execute_result" 136 | } 137 | ], 138 | "source": [ 139 | "# 查看模型结构及参数量,input_size表示示例输入数据的维度信息\n", 140 | "summary(LeNet(), input_size=(1, 1, 28, 28))" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "id": "9ad16a80", 146 | "metadata": {}, 147 | "source": [ 148 | "### 模型训练" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 4, 154 | "id": "96bf0385", 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "Epoch: 0 Loss: 2.2088656986293165 Acc: 0.9578\n", 162 | "Epoch: 2 Loss: 1.4376559603001913 Acc: 0.979 \n", 163 | "Epoch: 4 Loss: 1.228520721191793 Acc: 0.9803 \n", 164 | "Epoch: 6 Loss: 1.106042682456222 Acc: 0.9859 \n", 165 | "Epoch: 8 Loss: 1.0158490855052476 Acc: 0.9883 \n", 166 | "100%|██████████| 10/10 [01:56<00:00, 11.62s/it]\n" 167 | ] 168 | }, 169 | { 170 | "data": { 171 | "image/png": "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999/P5///OdP7v0ginroEJiT3tzqeHp5ldeliEiY+NWvfkVxcTFTpkxh69atzJs3j+nTpzNyZOCzFDIyMgBYsGABt99+e8f3paend3vsa665Bp/PB0B9fT3XXHMNRUVFfPWrX2XNmjUdx73tttvw+/0d5zMzrr/+eh5++GHq6upYvHgxl1xyyUn/WaOmhw4wblgKRXkpPLGskpvO1gdfiISNHvSk+8Jrr73GggULWLx4MYmJicyYMYOSkhLWr1/f42MElwQHoKmp6Yh9gwcP7nj+H//xH5x33nk89dRTbN68mRkzZhz3uLNnz+ayyy4jISGBa665piPwT0ZU9dABrj4jn9VVDazbrjnpIgNdfX096enpJCYmsn79epYsWUJTUxMLFy7kww8/BOgYcrngggv47W9/2/G97UMu2dnZrFu3jra2Np566qnjnisvLw+ABx54oGP7BRdcwB/+8IeOC6ft58vNzSU3N5e77rqL2bNnh+TPG3WBPrMkLzAnXQt2iQx4F198MS0tLYwbN45vf/vbTJkyhaysLObNm8dVV11FcXExn/70pwH47ne/S21tLUVFRRQXF/Pqq68CcPfdd3PppZcybdo0hg0b1uW57rjjDu68805KS0uPmPVyyy23MHz4cCZOnEhxcTGPPPJIx77rrruOgoKCkK1KGdHL53bltj+Xs7SijsV3fpxYX9T9nyUSEbR8bve++MUvUlpays0333zM/QNq+dyuzJpUwO69B1n4nuaki0h4mjRpEitXruRzn/tcyI4ZVRdF280Yk8WQwXE8sbSS88dle12OiMhHLF26NOTHjMoeeqwvhitK81iwrprafYe8LkdkwPJqSDca9Oa9i8pAh8Bsl+ZWx9MrtE66iBcSEhKoqalRqPeCc46amhoSEhJO6PuicsgFYHxuCuOHpTB/WSU3Tiv0uhyRASc/P5/Kykp27dK1rN5ISEggPz//hL4nagMdAgt2/dcza9mwo5ExOclelyMyoMTGxnbcjSn9o9shFzMrMLNXzWytma0xsy8fo42Z2a/MbKOZrTSzM/qm3BMzsyQXf4zWSReRgaEnY+gtwNedc+OBKcDtZjb+qDaXAKODjznA70NaZS8NSYrn42OH8uSyKlq0TrqIRLluA905t905tyz4vBFYB+Qd1Wwm8JALWAKkmVnXt1T1o6sn5QfmpL+vcTwRiW4n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\n", 172 | "text/plain": [ 173 | "
" 174 | ] 175 | }, 176 | "metadata": { 177 | "needs_background": "light" 178 | }, 179 | "output_type": "display_data" 180 | }, 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "Accuracy: 0.9886\n" 186 | ] 187 | } 188 | ], 189 | "source": [ 190 | "# 导入必要的库\n", 191 | "import torch\n", 192 | "import torch.nn as nn\n", 193 | "import torch.optim as optim\n", 194 | "from torch.utils.data import DataLoader\n", 195 | "from torchvision import datasets, transforms\n", 196 | "from tqdm import * # tqdm用于显示进度条并评估任务时间开销\n", 197 | "import numpy as np\n", 198 | "import sys\n", 199 | "\n", 200 | "# 设置随机种子\n", 201 | "torch.manual_seed(0)\n", 202 | "\n", 203 | "# 定义模型、优化器、损失函数\n", 204 | "model = LeNet()\n", 205 | "optimizer = optim.SGD(model.parameters(), lr=0.02)\n", 206 | "criterion = nn.CrossEntropyLoss()\n", 207 | "\n", 208 | "# 设置数据变换和数据加载器\n", 209 | "transform = transforms.Compose([\n", 210 | " transforms.ToTensor(), # 将数据转换为张量\n", 211 | "])\n", 212 | "\n", 213 | "# 加载训练数据\n", 214 | "train_dataset = datasets.MNIST(root='../data/mnist/', train=True, download=True, transform=transform)\n", 215 | "# 实例化训练数据加载器\n", 216 | "train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True)\n", 217 | "# 加载测试数据\n", 218 | "test_dataset = datasets.MNIST(root='../data/mnist/', train=False, download=True, transform=transform)\n", 219 | "# 实例化测试数据加载器\n", 220 | "test_loader = DataLoader(test_dataset, batch_size=256, shuffle=False)\n", 221 | "\n", 222 | "# 设置epoch数并开始训练\n", 223 | "num_epochs = 10 # 设置epoch数\n", 224 | "loss_history = [] # 创建损失历史记录列表\n", 225 | "acc_history = [] # 创建准确率历史记录列表\n", 226 | "\n", 227 | "# tqdm用于显示进度条并评估任务时间开销\n", 228 | "for epoch in tqdm(range(num_epochs), file=sys.stdout):\n", 229 | " # 记录损失和预测正确数\n", 230 | " total_loss = 0\n", 231 | " total_correct = 0\n", 232 | " \n", 233 | " # 批量训练\n", 234 | " model.train()\n", 235 | " for inputs, labels in train_loader:\n", 236 | "\n", 237 | " # 预测、损失函数、反向传播\n", 238 | " optimizer.zero_grad()\n", 239 | " outputs = model(inputs)\n", 240 | " loss = criterion(outputs, labels)\n", 241 | " loss.backward()\n", 242 | " optimizer.step()\n", 243 | " \n", 244 | " # 记录训练集loss\n", 245 | " total_loss += loss.item()\n", 246 | " \n", 247 | " # 测试模型,不计算梯度\n", 248 | " model.eval()\n", 249 | " with torch.no_grad():\n", 250 | " for inputs, labels in test_loader:\n", 251 | "\n", 252 | " # 预测\n", 253 | " outputs = model(inputs)\n", 254 | " # 记录测试集预测正确数\n", 255 | " total_correct += (outputs.argmax(1) == labels).sum().item()\n", 256 | " \n", 257 | " # 记录训练集损失和测试集准确率\n", 258 | " loss_history.append(np.log10(total_loss)) # 将损失加入损失历史记录列表,由于数值有时较大,这里取对数\n", 259 | " acc_history.append(total_correct / len(test_dataset))# 将准确率加入准确率历史记录列表\n", 260 | " \n", 261 | " # 打印中间值\n", 262 | " if epoch % 2 == 0:\n", 263 | " tqdm.write(\"Epoch: {0} Loss: {1} Acc: {2}\".format(epoch, loss_history[-1], acc_history[-1]))\n", 264 | "\n", 265 | "# 使用Matplotlib绘制损失和准确率的曲线图\n", 266 | "import matplotlib.pyplot as plt\n", 267 | "plt.plot(loss_history, label='loss')\n", 268 | "plt.plot(acc_history, label='accuracy')\n", 269 | "plt.legend()\n", 270 | "plt.show()\n", 271 | "\n", 272 | "# 输出准确率\n", 273 | "print(\"Accuracy:\", acc_history[-1])" 274 | ] 275 | } 276 | ], 277 | "metadata": { 278 | "kernelspec": { 279 | "display_name": "Python 3 (ipykernel)", 280 | "language": "python", 281 | "name": "python3" 282 | }, 283 | "language_info": { 284 | "codemirror_mode": { 285 | "name": "ipython", 286 | "version": 3 287 | }, 288 | "file_extension": ".py", 289 | "mimetype": "text/x-python", 290 | "name": "python", 291 | "nbconvert_exporter": "python", 292 | "pygments_lexer": "ipython3", 293 | "version": "3.8.10" 294 | } 295 | }, 296 | "nbformat": 4, 297 | "nbformat_minor": 5 298 | } 299 | -------------------------------------------------------------------------------- /Chapter-09/images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gengzhige/Deep-Learning-Code/7897466284437bafb53fdf688281aa160fb2c06d/Chapter-09/images/image1.png -------------------------------------------------------------------------------- /Chapter-09/images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gengzhige/Deep-Learning-Code/7897466284437bafb53fdf688281aa160fb2c06d/Chapter-09/images/image2.png -------------------------------------------------------------------------------- /Chapter-14/dataset/url.txt: -------------------------------------------------------------------------------- 1 | https://www.kaggle.com/datasets/araraltawil/fruit-101-dataset 2 | https://www.kaggle.com/datasets/olgabelitskaya/flower-color-images 3 | -------------------------------------------------------------------------------- /Chapter-15/15.1 词嵌入和word2vec.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "46360dcf", 6 | "metadata": {}, 7 | "source": [ 8 | "## 1. word2vec模型" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "029f6b08", 14 | "metadata": {}, 15 | "source": [ 16 | "### 1.1 代码包引入" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "id": "830bfd74", 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "from gensim.models.word2vec import Word2Vec\n", 27 | "import gensim.downloader" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "id": "56b47102", 33 | "metadata": {}, 34 | "source": [ 35 | "### 1.2 引入Word2vec模型" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "id": "31412a6f", 42 | "metadata": {}, 43 | "outputs": [ 44 | { 45 | "data": { 46 | "text/plain": [ 47 | "['fasttext-wiki-news-subwords-300',\n", 48 | " 'conceptnet-numberbatch-17-06-300',\n", 49 | " 'word2vec-ruscorpora-300',\n", 50 | " 'word2vec-google-news-300',\n", 51 | " 'glove-wiki-gigaword-50',\n", 52 | " 'glove-wiki-gigaword-100',\n", 53 | " 'glove-wiki-gigaword-200',\n", 54 | " 'glove-wiki-gigaword-300',\n", 55 | " 'glove-twitter-25',\n", 56 | " 'glove-twitter-50',\n", 57 | " 'glove-twitter-100',\n", 58 | " 'glove-twitter-200',\n", 59 | " '__testing_word2vec-matrix-synopsis']" 60 | ] 61 | }, 62 | "execution_count": 2, 63 | "metadata": {}, 64 | "output_type": "execute_result" 65 | } 66 | ], 67 | "source": [ 68 | "list(gensim.downloader.info()['models'].keys())" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "id": "8cd2ea1f", 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "word_vectors = gensim.downloader.load('word2vec-google-news-300')" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "id": "c8d126a5", 84 | "metadata": {}, 85 | "source": [ 86 | "### 1.3 训练word2vec模型" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 3, 92 | "id": "3afabe2c", 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "sentences = [['猫','吃','鱼'],['狗','吃','肉']] # 构造数据集\n", 97 | "model = Word2Vec(sentences, min_count=1, sg=1) #训练模型\n", 98 | "model_path = 'model/demo.model'\n", 99 | "model.save(model_path) # 保存模型" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "id": "51b453d5", 105 | "metadata": {}, 106 | "source": [ 107 | "### 1.4 词向量" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 4, 113 | "id": "37152b9e", 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/plain": [ 119 | "array([-0.00713902, 0.00124103, -0.00717672, -0.00224462, 0.0037193 ,\n", 120 | " 0.00583312, 0.00119818, 0.00210273, -0.00411039, 0.00722533,\n", 121 | " -0.00630704, 0.00464722, -0.00821997, 0.00203647, -0.00497705,\n", 122 | " -0.00424769, -0.00310898, 0.00565521, 0.0057984 , -0.00497465,\n", 123 | " 0.00077333, -0.00849578, 0.00780981, 0.00925729, -0.00274233,\n", 124 | " 0.00080022, 0.00074665, 0.00547788, -0.00860608, 0.00058446,\n", 125 | " 0.00686942, 0.00223159, 0.00112468, -0.00932216, 0.00848237,\n", 126 | " -0.00626413, -0.00299237, 0.00349379, -0.00077263, 0.00141129,\n", 127 | " 0.00178199, -0.0068289 , -0.00972481, 0.00904058, 0.00619805,\n", 128 | " -0.00691293, 0.00340348, 0.00020606, 0.00475375, -0.00711994,\n", 129 | " 0.00402695, 0.00434743, 0.00995737, -0.00447374, -0.00138926,\n", 130 | " -0.00731732, -0.00969783, -0.00908026, -0.00102275, -0.00650329,\n", 131 | " 0.00484973, -0.00616403, 0.00251919, 0.00073944, -0.00339215,\n", 132 | " -0.00097922, 0.00997913, 0.00914589, -0.00446183, 0.00908303,\n", 133 | " -0.00564176, 0.00593092, -0.00309722, 0.00343175, 0.00301723,\n", 134 | " 0.00690046, -0.00237388, 0.00877504, 0.00758943, -0.00954765,\n", 135 | " -0.00800821, -0.0076379 , 0.00292326, -0.00279472, -0.00692952,\n", 136 | " -0.00812826, 0.00830918, 0.00199049, -0.00932802, -0.00479272,\n", 137 | " 0.00313674, -0.00471321, 0.00528084, -0.00423344, 0.0026418 ,\n", 138 | " -0.00804569, 0.00620989, 0.00481889, 0.00078719, 0.00301345],\n", 139 | " dtype=float32)" 140 | ] 141 | }, 142 | "execution_count": 4, 143 | "metadata": {}, 144 | "output_type": "execute_result" 145 | } 146 | ], 147 | "source": [ 148 | "model = Word2Vec.load(model_path) # 加载模型\n", 149 | "model.wv['猫'] # 输出词向量" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "id": "3c1ce806", 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [] 159 | } 160 | ], 161 | "metadata": { 162 | "kernelspec": { 163 | "display_name": "Python 3 (ipykernel)", 164 | "language": "python", 165 | "name": "python3" 166 | }, 167 | "language_info": { 168 | "codemirror_mode": { 169 | "name": "ipython", 170 | "version": 3 171 | }, 172 | "file_extension": ".py", 173 | "mimetype": "text/x-python", 174 | "name": "python", 175 | "nbconvert_exporter": "python", 176 | "pygments_lexer": "ipython3", 177 | "version": "3.8.10" 178 | } 179 | }, 180 | "nbformat": 4, 181 | "nbformat_minor": 5 182 | } 183 | -------------------------------------------------------------------------------- /Chapter-15/15.4 Huggingface库介绍.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "ee6483b8", 6 | "metadata": {}, 7 | "source": [ 8 | "## 1. 加载预训练模型" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 10, 14 | "id": "5b6a09e3", 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "name": "stderr", 19 | "output_type": "stream", 20 | "text": [ 21 | "Some weights of the model checkpoint at bert-base-chinese were not used when initializing BertForMaskedLM: ['cls.seq_relationship.weight', 'cls.seq_relationship.bias']\n", 22 | "- This IS expected if you are initializing BertForMaskedLM from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", 23 | "- This IS NOT expected if you are initializing BertForMaskedLM from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n" 24 | ] 25 | } 26 | ], 27 | "source": [ 28 | "from transformers import AutoModelForMaskedLM\n", 29 | "# 加载中文bert模型\n", 30 | "model = AutoModelForMaskedLM.from_pretrained(\"bert-base-chinese\")" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 2, 36 | "id": "110d9e69", 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "data": { 41 | "text/plain": [ 42 | "BertConfig {\n", 43 | " \"_name_or_path\": \"bert-base-chinese\",\n", 44 | " \"architectures\": [\n", 45 | " \"BertForMaskedLM\"\n", 46 | " ],\n", 47 | " \"attention_probs_dropout_prob\": 0.1,\n", 48 | " \"classifier_dropout\": null,\n", 49 | " \"directionality\": \"bidi\",\n", 50 | " \"hidden_act\": \"gelu\",\n", 51 | " \"hidden_dropout_prob\": 0.1,\n", 52 | " \"hidden_size\": 768,\n", 53 | " \"initializer_range\": 0.02,\n", 54 | " \"intermediate_size\": 3072,\n", 55 | " \"layer_norm_eps\": 1e-12,\n", 56 | " \"max_position_embeddings\": 512,\n", 57 | " \"model_type\": \"bert\",\n", 58 | " \"num_attention_heads\": 12,\n", 59 | " \"num_hidden_layers\": 12,\n", 60 | " \"pad_token_id\": 0,\n", 61 | " \"pooler_fc_size\": 768,\n", 62 | " \"pooler_num_attention_heads\": 12,\n", 63 | " \"pooler_num_fc_layers\": 3,\n", 64 | " \"pooler_size_per_head\": 128,\n", 65 | " \"pooler_type\": \"first_token_transform\",\n", 66 | " \"position_embedding_type\": \"absolute\",\n", 67 | " \"transformers_version\": \"4.19.2\",\n", 68 | " \"type_vocab_size\": 2,\n", 69 | " \"use_cache\": true,\n", 70 | " \"vocab_size\": 21128\n", 71 | "}" 72 | ] 73 | }, 74 | "execution_count": 2, 75 | "metadata": {}, 76 | "output_type": "execute_result" 77 | } 78 | ], 79 | "source": [ 80 | "# 显示模型配置信息\n", 81 | "model.config" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 3, 87 | "id": "8ba69c07", 88 | "metadata": {}, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/plain": [ 93 | "" 406 | ] 407 | }, 408 | "execution_count": 3, 409 | "metadata": {}, 410 | "output_type": "execute_result" 411 | } 412 | ], 413 | "source": [ 414 | "# 显示模型结构\n", 415 | "model.parameters" 416 | ] 417 | }, 418 | { 419 | "cell_type": "markdown", 420 | "id": "3bcdab34", 421 | "metadata": {}, 422 | "source": [ 423 | "## 2 加载词元化工具" 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": 4, 429 | "id": "c56aabb2", 430 | "metadata": {}, 431 | "outputs": [ 432 | { 433 | "data": { 434 | "text/plain": [ 435 | "PreTrainedTokenizerFast(name_or_path='bert-base-chinese', vocab_size=21128, model_max_len=512, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'})" 436 | ] 437 | }, 438 | "execution_count": 4, 439 | "metadata": {}, 440 | "output_type": "execute_result" 441 | } 442 | ], 443 | "source": [ 444 | "from transformers import AutoTokenizer\n", 445 | "tokenizer = AutoTokenizer.from_pretrained(\"bert-base-chinese\")\n", 446 | "tokenizer" 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "execution_count": 5, 452 | "id": "66d84b63", 453 | "metadata": {}, 454 | "outputs": [ 455 | { 456 | "name": "stdout", 457 | "output_type": "stream", 458 | "text": [ 459 | "[101, 2769, 4263, 3322, 1690, 2110, 739, 102, 2769, 3291, 4263, 3918, 2428, 2110, 102]\n" 460 | ] 461 | } 462 | ], 463 | "source": [ 464 | "sent1 = '我爱机器学习'\n", 465 | "sent2 = '我更爱深度学习'\n", 466 | "#编码两个句子\n", 467 | "encode_result = tokenizer.encode(\n", 468 | " text=sent1,\n", 469 | " text_pair=sent2,\n", 470 | "\n", 471 | " #当句子长度大于max_length时,截断\n", 472 | " truncation=True,\n", 473 | "\n", 474 | " #一律补pad到max_length长度\n", 475 | " padding='max_length',\n", 476 | " add_special_tokens=True,\n", 477 | " max_length=15,\n", 478 | " return_tensors=None,\n", 479 | ")\n", 480 | "print(encode_result)" 481 | ] 482 | }, 483 | { 484 | "cell_type": "code", 485 | "execution_count": 6, 486 | "id": "823eef61", 487 | "metadata": {}, 488 | "outputs": [ 489 | { 490 | "data": { 491 | "text/plain": [ 492 | "'[CLS] 我 爱 机 器 学 习 [SEP] 我 更 爱 深 度 学 [SEP]'" 493 | ] 494 | }, 495 | "execution_count": 6, 496 | "metadata": {}, 497 | "output_type": "execute_result" 498 | } 499 | ], 500 | "source": [ 501 | "tokenizer.decode(encode_result)" 502 | ] 503 | }, 504 | { 505 | "cell_type": "code", 506 | "execution_count": 7, 507 | "id": "50029869", 508 | "metadata": {}, 509 | "outputs": [ 510 | { 511 | "data": { 512 | "text/plain": [ 513 | "(dict, 21128, False)" 514 | ] 515 | }, 516 | "execution_count": 7, 517 | "metadata": {}, 518 | "output_type": "execute_result" 519 | } 520 | ], 521 | "source": [ 522 | "#获取字典\n", 523 | "mydict = tokenizer.get_vocab()\n", 524 | "\n", 525 | "type(mydict), len(mydict), '强化' in mydict," 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": 8, 531 | "id": "bf3098de", 532 | "metadata": {}, 533 | "outputs": [ 534 | { 535 | "data": { 536 | "text/plain": [ 537 | "(dict, 21131, 21128, 21130)" 538 | ] 539 | }, 540 | "execution_count": 8, 541 | "metadata": {}, 542 | "output_type": "execute_result" 543 | } 544 | ], 545 | "source": [ 546 | "#添加新词\n", 547 | "tokenizer.add_tokens(new_tokens=['强化', '学习'])\n", 548 | "\n", 549 | "#添加新符号\n", 550 | "tokenizer.add_special_tokens({'eos_token': '[EOS]'})\n", 551 | "\n", 552 | "mydict = tokenizer.get_vocab()\n", 553 | "\n", 554 | "type(mydict), len(mydict), mydict['强化'], mydict['[EOS]']" 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 9, 560 | "id": "388f0e54", 561 | "metadata": {}, 562 | "outputs": [ 563 | { 564 | "name": "stdout", 565 | "output_type": "stream", 566 | "text": [ 567 | "[101, 21129, 21128, 21129, 21130, 102, 0, 0]\n" 568 | ] 569 | }, 570 | { 571 | "data": { 572 | "text/plain": [ 573 | "'[CLS] 学习 强化 学习 [EOS] [SEP] [PAD] [PAD]'" 574 | ] 575 | }, 576 | "execution_count": 9, 577 | "metadata": {}, 578 | "output_type": "execute_result" 579 | } 580 | ], 581 | "source": [ 582 | "#编码新添加的词\n", 583 | "encode_result = tokenizer.encode(\n", 584 | " text='学习强化学习[EOS]',\n", 585 | " text_pair=None,\n", 586 | "\n", 587 | " #当句子长度大于max_length时,截断\n", 588 | " truncation=True,\n", 589 | "\n", 590 | " #一律补pad到max_length长度\n", 591 | " padding='max_length',\n", 592 | " add_special_tokens=True,\n", 593 | " max_length=10,\n", 594 | " return_tensors=None,\n", 595 | ")\n", 596 | "\n", 597 | "print(encode_result)\n", 598 | "\n", 599 | "tokenizer.decode(encode_result)" 600 | ] 601 | } 602 | ], 603 | "metadata": { 604 | "kernelspec": { 605 | "display_name": "Python 3 (ipykernel)", 606 | "language": "python", 607 | "name": "python3" 608 | }, 609 | "language_info": { 610 | "codemirror_mode": { 611 | "name": "ipython", 612 | "version": 3 613 | }, 614 | "file_extension": ".py", 615 | "mimetype": "text/x-python", 616 | "name": "python", 617 | "nbconvert_exporter": "python", 618 | "pygments_lexer": "ipython3", 619 | "version": "3.8.10" 620 | } 621 | }, 622 | "nbformat": 4, 623 | "nbformat_minor": 5 624 | } 625 | -------------------------------------------------------------------------------- /Chapter-15/data/越女剑.txt: -------------------------------------------------------------------------------- 1 | 越女剑 2 | “请!”“请!” 3 | 两名剑士各自倒转剑尖,右手握剑柄,左手搭于右手手背,躬身行礼。 4 | 两人身子尚未站直,突然间白光闪动,跟着铮的一声响,双剑相交,两人各退一步。旁观众人都是“咦”的一声轻呼。 5 | 青衣剑士连劈三剑,锦衫剑士一一格开。青衣剑士一声吒喝,长剑从左上角直划而下,势劲力急。锦衫剑士身手矫捷,向后跃开,避过了这剑。他左足刚着地,身子跟着弹起,刷刷两剑,向对手攻去。青衣剑士凝里不动,嘴角边微微冷笑,长剑轻摆,挡开来剑。 6 | 锦衫剑士突然发足疾奔,绕着青衣剑士的溜溜的转动,脚下越来越快。青衣剑士凝视敌手长剑剑尖,敌剑一动,便挥剑击落。锦衫剑士忽而左转,忽而右转,身法变幻不定。青衣剑士给他转得微感晕眩,喝道:“你是比剑,还是逃命?”刷刷两剑,直削过去。但锦衫剑士奔转甚急,剑到之时,人已离开,敌剑剑锋总是和他身子差了尺许。 7 | 青衣剑士回剑侧身,右退微蹲,锦衫剑士看出破绽,挺剑向他左肩疾刺。不料青衣剑士这一蹲乃是诱招,长剑突然圈转,直取敌人咽喉,势道劲急无轮。锦衫剑士大骇之下,长剑脱手,向敌人心窝激射过去。这是无可奈何同归于尽的打法,敌人若是继续进击,心窝必定中剑。当此情形,对方自须收剑挡格,自己便可摆脱这无可挽救的绝境。 8 | 不料青衣剑士竟不挡架闪避,手腕抖动,噗的一声,剑尖刺入了锦衫剑士的咽喉。跟着当的一响,掷来的长剑刺中了他胸膛,长剑落地。青衣剑士嘿嘿一笑,收剑退立,原来他衣内胸口藏着一面护心铁镜,剑尖虽是刺中,却是丝毫无伤。那锦衫剑士喉头鲜血激喷,身子在地下不住扭曲。当下便有从者过来抬开尸首,抹去地下血迹。 9 | 青衣剑士还剑入鞘,跨前两步,躬身向北首高坐于锦披大椅中的一位王者行礼。 10 | 那王者身披锦袍,形貌拙异,头颈甚长,嘴尖如鸟,微微一笑,嘶声道:“壮士剑法津妙,赐金十斤。”青衣剑士右膝跪下,躬身说道:“谢赏!”那王者左手一挥,他右首一名高高瘦瘦、四十来岁的官员喝道:“吴越剑士,二次比试!” 11 | 东首锦衫剑士队走出一条身材魁梧的汉子,手提大剑。这剑长逾五尺,剑身极厚,显然份量甚重。西首走出一名青衣剑士,中等身材,脸上尽是剑疤,东一道、西一道,少说也有十二三道,一张脸已无复人性,足见身经百战,不知已和人比过多少次剑了。二人先向王者屈膝致敬,然后转过身来,相向而立,躬身行礼。 12 | 青衣剑士站直身子,脸露狞笑。他一张脸本已十分丑陋,这么一笑,更显得说不出的难看。锦衫剑士见了他如鬼似魅的模样,不由得机伶伶打个冷战,波的一声,吐了口长气,慢慢伸过左手,搭住剑柄。 13 | 青衣剑士突然一声狂叫,声如狼嗥,挺剑向对手急刺过去。锦衫剑士也是纵声大喝,提起大剑,对着他当头劈落。青衣剑士斜身闪开,长剑自左而右横削过去。那锦衫剑士双手使剑,一柄大剑舞得呼呼作响。这大剑少说也有五十来斤重,但他招数仍是迅捷之极。 14 | 两人一搭上手,顷刻间拆了三十来招,青衣剑士被他沉重的剑力压得不住倒退。站在大殿西首的五十余名锦衫剑士人人脸有喜色,眼见这场比试是赢定了。 15 | 只听得锦衫剑士一声大喝,声若雷震,大剑横扫过去。青衣剑士避无可避,提长剑奋力挡格。当的一声响,双剑相交,半截大剑飞了出去,原来青衣剑士手中长剑锋利无比,竟将大剑斩为两截,那利剑跟着直划而下,将锦衫剑士自咽喉而至小腹,划了一道两尺来长的口子。锦衫剑士连声狂吼,扑倒在地。青衣剑士向地下魁梧的身形凝视片刻,这才还剑入鞘,屈膝向王者行礼,脸上掩不住得意之色。 16 | 王者身旁的一位官员道:“壮士剑利术津,大王赐金十斤。”青衣剑士称谢退开。 17 | 西首一列排着八名青衣剑士,与对面五十余名锦衫剑士相比,众寡甚是悬殊。 18 | 那官员缓缓说道:“吴越剑士,三次比剑!”两队剑士队中各走出一人,向王者行礼后相向而立。突然青光耀眼,众人均觉寒气袭体。但见那青衣剑士手中一柄三尺长剑不住颤动,便如一根闪闪发出丝光的缎带。那官员赞道:“好剑!”青衣剑士微微躬身为礼,谢他称赞。那官员道:“单打独斗已看了两场,这次两个对两个!” 19 | 锦衫剑士队中一人应声而出,拔剑出鞘。那剑明亮如秋水,也是一口利器。青衣剑士队中又出来一人。四人向王者行过礼后,相互行礼,跟着剑光闪烁,斗了起来。这二对二的比剑,同伙剑士互相照应配合。数合之后,嗤的一声,一名锦衫剑士手中长剑竟被敌手削断。这人极是悍勇,提着半截断剑,飞身向敌人扑去。那青衣剑士长剑闪处,嗤的一声响,将他右臂齐肩削落,跟着补上一剑,刺中他的心窝。 20 | 另外二人兀自缠斗不休,得胜的青衣剑士窥伺在旁,突然间长剑递出,嗤的一声,又就锦衫剑士手中长剑削断。另一人长剑中宫直进,自敌手胸膛贯入,背心穿出。 21 | 那王者呵呵大笑,拍手说道:“好剑,好剑法!赏酒,赏金!咱们再来瞧一场四个对四个的比试。” 22 | 两边队中各出四人,行过礼后,出剑相斗。锦衫剑士连输三场,死了四人,这时下场的四人狠命相扑,说什么也要赢回一场。只见两名青衣剑士分从左右夹击一名锦衫剑士。余下三名锦衫剑士上前邀战,却给两名青衣剑士挡住,这两名青衣剑士取的纯是守势,招数严密,竟一招也不还击,却令三名锦衫剑士无法过去相援同伴,余下两名青衣剑士以二对一,十余招间便将对手杀死,跟着便攻向另一名锦衫剑士。先前两名青衣剑士仍使旧法,只守不攻,挡住两名锦衫剑士,让同伴以二对一,杀死敌手。 23 | 旁观的锦衫剑士眼见同伴只剩下二人,胜负之数已定,都大声鼓噪起来,纷纷拔剑,便欲一拥而上,就八名青衣剑士乱剑分尸。 24 | 那官员朗声道:“学剑之士,当守剑道!”他神色语气之中有一股凛然之威,一众锦衫剑士立时都静了下来。 25 | 这时众人都已看得分明,四名青衣剑士的剑法截然不同,二人的守招严密无比,另二人的攻招却是凌厉狠辣,分头合击,守者缠住敌手,只剩下一人,让攻者以众凌寡,逐一蚕食杀戮。以此法迎敌,纵然对方武功较高,青衣剑士一方也必躁胜算。别说四人对四人,即使是四人对六人甚或八人,也能取胜。那二名守者的剑招施展开来,便如是一道剑网,纯取守势,要挡住五六人实是绰绰有余。 26 | 这时场中两名青衣剑士仍以守势缠住了一名锦衫剑士,另外两名青衣剑士快剑攻击,杀死第三名锦衫剑士后,转而向第四名敌手相攻。取守势的两名青衣剑士向左右分开,在旁掠阵。余下一名锦衫剑士虽见败局已成,却不肯弃剑投降,仍是奋力应战。突然间四名青衣剑士齐声大喝,四剑并出,分从前后左右,一齐刺在锦衫剑士的身上。 27 | 锦衫剑士身中四剑,立时毙命,只见他双目圆睁,嘴巴也是张得大大的。四名青衣剑士同时拔剑,四人抬起左脚,将长剑剑刃在鞋底一拖,抹去了血渍,刷的一声,还剑入鞘。这几下动作干净利落,固不待言,最难得的是齐整之极,同时抬脚,同时拖剑,回剑入鞘却只发出一下声响。 28 | 那王者呵呵大笑,鼓掌道:“好剑法,好剑法!上国剑士名扬天下,可教我们今日大开眼界了。四位剑士各赐金十斤。”四名青衣剑士一齐躬身谢赏。四人这么一弯腰,四个脑袋摆成一道直线,不见有丝毫高低,实不知花了多少功夫才练得如此划一。 29 | 一名青衣剑士转过身去,捧起一只金漆长匣,走上几步,说道:“敝国君王多谢大王厚礼,命臣奉上宝剑一口还答,此剑乃敝国新铸,谨供大王玩赏。” 30 | 那王者笑道:“多谢了。范大夫,接过来看看。” 31 | 那王者是越王勾践。那官员是越国大夫范蠡。锦衫剑士是越王宫中的卫士,八名青衣剑士则是吴王夫差派来送礼的使者。越王昔日为夫差所败,卧薪尝胆,欲报此仇,面子上对吴王十分恭顺,暗中却日夜不停的训练士卒,俟机攻吴。他为了试探吴国军力,连出卫士中的高手和吴国剑士比剑,不料一战之下,八名越国好手尽数被歼。勾践又惊又怒,脸上却不动声色,显得对吴国剑士的剑法欢喜赞叹,衷心钦服。 32 | 范蠡走上几步,接过了金漆长匣,只觉轻飘飘地,匣中有如无物,当下打开了匣盖。旁边众人没见到匣中装有何物,却见范蠡的脸上陡然间罩上了一层青色薄雾,都是“哦”的一声,甚感惊讶。当真是剑气映面,发眉俱碧。 33 | 范蠡托着漆匣,走到越王身前,躬身道:“大王请看!”勾践见匣中铺以锦缎,放着一柄三尺长剑,剑身极薄,刃上宝光流动,变幻不定,不由得赞道:“好剑!”握住剑柄,提了起来,只见剑刃不住颤动,似乎只须轻轻一抖,便能折断,心想:“此剑如此单薄,只堪观赏,并无实用。” 34 | 那为首的青衣剑士从怀中取出一块轻纱,向上抛起,说道:“请大王平伸剑刃,剑锋向上,待纱落在剑上,便见此剑与众不同。”眼见一块轻纱从半空中飘飘扬扬的落将下来,越王平剑伸出,轻纱落在剑上,不料下落之势并不止歇,轻纱竟已分成两块,缓缓落地。原来这剑已将轻纱划而为二,剑刃之利,实是匪夷所思。殿上殿下,采声雷动。 35 | 青衣剑士说道:“此剑虽薄,但与沉重兵器相碰,亦不折断。” 36 | 勾践道:“范大夫,拿去试来。”范蠡道:“是!”双手托上剑匣,让勾践将剑放入匣中,倒退数步,转身走到一名锦衫剑士面前,取剑出匣,说道:“拔剑,咱们试试!” 37 | 那锦衫剑士躬身行礼,拔出佩剑,举在空中,不敢下击。范蠡叫道:“劈下!”锦衫剑士道:“是!”挥剑劈下,落剑处却在范蠡身前一尺。范蠡提剑向上一撩,嗤的一声轻响,锦衫剑士手中的长剑已断为两截。半截断剑落下,眼见便要碰到范蠡身上,范蠡轻轻一跃避开。众人又是一声采,却不知是称赞剑利,还是范大夫身手敏捷。 38 | 范蠡将剑放回匣中,躬身放在越王脚边。 39 | 勾践说道:“上国剑士,请赴别座饮宴领赏。”八名青衣剑士行礼下殿。勾践手一挥,锦衫剑士和殿上侍从也均退下,只除下范蠡一人。 40 | 勾践瞧瞧脚边长剑,又瞧瞧满地鲜血,只是出神,过了半晌,道:“怎样?” 41 | 范蠡道:“吴国武士剑术,未必尽如这八人之津,吴国武士所用兵刃,未必尽如此剑之利。但观此一端,足见其余。最令人心忧的是,吴国武士群战之术,妙用孙武子兵法,臣以为当今之世,实乃无敌于天下。”勾践沉吟道:“夫差派这八人来送宝剑,大夫你看是何用意?”范蠡道:“那是要咱们知难而退,不可起侵吴报仇之心。” 42 | 勾践大怒,一弯身,从匣中抓起宝剑,回手一挥,察的一声响,将坐椅平平整整的切去了一截,大声道:“便有千难万难,勾践也决不知难而退。终有一日,我要擒住夫差,便用此剑将他脑袋砍了下来!”说着又是一剑,将一张檀木椅子一劈为二。 43 | 范蠡躬身道:“恭喜大王,贺喜大王!”勾践愕然道:“眼见吴国剑士如此了得,又有甚么喜可贺?”范蠡道:“大王说道便有千难万难,也决不知难而退。大王即有此决心,大事必成。眼前这难事,还须请文大夫共同商议。”勾践道:“好,你去传文大夫来。” 44 | 范蠡走下殿去,命宫监去传大夫文种,自行站在宫门之侧相候。过不多时,文种飞马赶到,与范蠡并肩入宫。 45 | 范蠡本是楚国宛人,为人倜傥,不拘小节,所作所为,往往出人意表,当地人士都叫他“范疯子”。文种来到宛地做县令,听到范蠡的名字,便派部属去拜访。那部属见了范蠡,回来说道:“这人是本地出名的疯子,行事乱七八糟。”文种笑道:“一个人有与众不同的行为,凡人必笑他胡闹,他有高明独特的见解,庸人自必骂他糊涂。你们又怎能明白范先生呢?”便亲自前去拜访。范避而不见,但料到他必定去而复来,向兄长借了衣冠,穿戴整齐。果然过了几个时辰,文种又再到来。两人相见之后,长谈王霸之道,投机之极,当真是相见恨晚。 46 | 两人都觉中原诸国暮气沉沉,楚国邦大而乱,眼前霸兆是在东南。于是文种辞去官位,与范蠡同往吴国。其时吴王正重用伍子胥的种种兴革措施确是才识卓越。自己未必胜得他过。两人一商量,以越国和吴国邻近,风俗相似,虽然地域较小,却也大可一显身手,于是来到越国。勾践接见之下,于二人议论才具颇为赏识,均拜为大夫之职。 47 | 后来勾践不听文种、范蠡劝谏,兴兵和吴国交战,以石买为将,在钱塘江边一战大败,勾践在会稽山被围,几乎亡国殒身。勾践在危机之中用文种、范蠡之计,买通了吴王身边的坚臣太宰伯pi,替越王陈说。吴王夫差不听伍子胥的忠谏,答允与越国讲和,将勾践带到吴国,后来又放他归国。其后勾践卧薪尝胆,决定复仇,采用了文种的灭吴九术。 48 | 那九术第一是尊天地,事鬼神,令越王有必胜之心。第二是赠送吴王大量财币,既是他习于奢侈,又去其防越之意。第三是先向吴国借粮,再以蒸过的大谷归还,吴王见谷大,发给农民当谷种,结果稻不生长,吴国大饥。第四是赠送美女西施和郑旦,使吴王迷恋美色,不理政事。第五是赠送巧匠,引诱吴王大起宫室高台,耗其财力民力。第六是贿赂吴王左右的坚臣,使之败坏朝政,第七是离间吴王的忠臣,终于迫得伍子胥自杀。第八是积蓄粮草,充实国家财力。第九是铸造武器,训练士卒,待机攻吴。 49 | 八术都已成功,最后的第九术却在这时遇上了重大困难。眼见吴王派来剑士八人,所显示的兵刃之利、剑术之津,实非越国武士所能匹敌。 50 | 范蠡将适才比剑的情形告知了文种。文种皱眉道:“范贤弟,吴国剑士剑利术津。固是大患,而他们在群斗之时,善用孙武子遗法,更是难破难当。”范蠡道:“正是,当年孙武子辅佐吴王,统兵破楚,攻入郢都,用兵如神,天下无敌。虽齐晋大国,亦畏其锋,他兵法有言道:‘我专为一,敌分为十,是以十攻其一也,则我众而敌寡。能以众击寡者,则吾之所与战者,约矣。’吴士四人与我越士四人相斗,吴士以二人专攻一人,以众击寡,战无不胜。” 51 | 言谈之间,二人到了越王面前,只见勾践手中提着那柄其薄如纸的利剑,兀自出神。 52 | 过了良久,勾践抬起头来,说道:“文大夫,当年吴国有干将莫邪夫妇,善于铸剑。我越国有良工欧治子,铸剑之术,亦不下于彼。此时干将、莫邪、欧治子均已不在人世。吴国有这等铸剑高手,难道我越国自欧治子一死,就此后继无人吗?”文种道:“臣闻欧治子传有弟子二人,一名风胡子,一名薛烛。风胡子在楚,薛烛尚在越国。”勾践大喜,道:“大夫速召薛烛前来,再遣人入楚,以重金聘请风胡子来越。”文种遵命而退。 53 | 次日清晨,文种回报已遣人赴楚,薛烛则已宣到。 54 | 勾践召见薛烛,说道:“你师父欧治子曾奉先王之命,铸剑五口。这五口宝剑的优劣,你倒说来听听。”薛烛磕头道:“小人曾听先师言道,先师为先王铸剑五口,大剑三,小剑二,一曰湛卢,二曰纯钧,三曰胜邪,四曰鱼肠,五曰巨阙。至今湛卢在楚,胜邪、鱼肠在吴,纯钧、巨阙二剑则在大王宫中。”勾践道:“正是。” 55 | 原来当年勾践之父越王允常铸成五剑后,吴王得讯,便来相求。允常畏吴之强,只得以湛卢、胜邪、鱼肠三剑相献。后来吴王阖庐以鱼肠剑遣专诸刺杀王僚。湛卢剑落入水中,后为楚王所得,秦王闻之,求而不得,兴师击楚,楚王始终不与。 56 | 薛烛禀道:“兴师曾言,五剑之中,胜邪最上,纯钧、湛卢二剑其次,鱼肠又次之,巨阙居末。铸巨阙之时,金锡和铜而离,因此此剑只是利剑,而非宝剑。”勾践道:“然则我纯钧、巨阙二剑,不敌吴王之胜邪、鱼肠二剑了?”薛烛道:“小人死罪,恕小人直言。”勾践抬头不语,从薛烛这句话中,已知越国二剑自非吴国二剑之敌。 57 | 范蠡说道:“你既得传尊师之术,可即开炉铸剑。铸将几口宝剑出来,未必便及不上吴国的宝剑。”薛烛道:“回禀大夫:小人已不能铸剑了。”范蠡道:“却是为何?”薛烛伸出手来,只见他双手的拇指食指具已不见,只剩下六根手指。薛烛黯然道:“铸剑之劲,全仗拇指食指。小人苟延残喘,早已成为废人。” 58 | 勾践奇道:“你这四根手指,是给仇家割去的么?”薛烛道:“不是仇家,是给小人的师兄割去的。”勾践更加奇怪,道:“你的师兄,那不是风胡子么?他为甚么要割你手指?啊,一定是你铸剑之术胜过师兄,他心怀妒忌,断你手指,教你再也不能铸剑。”勾践自加推测,薛烛不便说他猜错,只有默然不语。 59 | 勾践道:“寡人本要派人到楚国去召风胡子来。他怕你报仇,或许不敢回来。”薛烛道:“大王明鉴,风师兄目下是在吴国,不在楚国。”勾践微微一惊,说道:“他……他在吴国,在吴国干甚么?” 60 | 薛烛道:“三年之前,风师兄来到小人家中,取出宝剑一口,给小人观看。小人一见之下,登时大惊,原来这口宝剑,乃先师欧治子为楚国所铸,名曰工布,剑身上文如流水,自柄至尖,连绵不断。小人曾听先师说过,一见便知。当年先师为楚王铸剑三口,一曰龙渊、二曰泰阿、三曰工布。楚王宝爱异常,岂知竟为师哥所得。” 61 | 勾践道:“想必是楚王赐给你师兄了。” 62 | 薛烛道:“若说是楚王所赐,原也不错,只不过是转了两次手。风师兄言道,吴师破楚之后,伍子胥发楚平王之棺,鞭其遗尸,在楚王墓中得此宝剑。后来回吴之后,听到风师兄的名字,便叫人将剑送去楚国给他,说道此是先师遗泽,该由风师兄承受。” 63 | 勾践又是一惊,沉吟道:“伍子胥居然舍得此剑,此人真乃英雄,真乃英雄也!”突然间哈哈大笑,说道:“幸好夫差中我之计,已逼得此人自杀,哈哈,哈哈!” 64 | 勾践长笑之时,谁都不敢作声。他笑了好一会,才问:“伍子胥将工布宝剑赠你师兄,要办甚么事?”薛烛道:“风师兄言道,当时伍子胥只说仰慕先师,别无所求。风师兄得到此剑后,心下感激,寻思伍将军是吴国上卿,赠我希世珍宝,岂可不去当面叩谢?于是便去到吴国,向伍将军致谢。伍将军待以上宾之礼,替风师兄置下房舍,招待极是客气。”勾践道:“伍子胥叫人为他卖命,用的总是这套手段,当年叫专诸刺王僚,便是如此。” 65 | 薛烛道:“大王料事如神。但风师兄不懂得伍子胥的陰谋,受他如此厚待,心下过意不去,一再请问,有何用己之处。伍子胥总说:‘阁下枉驾过吴,乃是吴国嘉宾,岂敢劳动尊驾?’”勾践骂道:“老坚巨滑,以退为进!”薛烛道:“大王明见万里。风师兄终于对伍子胥说,他别无所长,只会铸剑,承蒙如此厚待,当铸造几口希世的宝剑相赠。” 66 | 勾践伸手在大退上一拍,道:“着了道儿啦!”薛烛道:“那伍子胥却说,吴国宝剑已多,也不必再铸了。而且铸剑极耗心力,当年干将莫邪铸剑不成,莫邪自身投入剑炉,宝剑方成。这种惨事,万万不可再行。”勾践奇道:“他当真不要风胡子铸剑?那可奇了。”薛烛道:“当时风师兄也觉奇怪。一日伍子胥又到宾馆来和风师兄闲谈,说起吴国与北方齐晋两国争霸,吴士勇悍,时占上风,便是车战之术有所不及,若与之以徒兵步战,所用剑戟又不够锋锐。风师兄便与之谈论铸造剑戟之法。原来伍子胥所要铸的,不是一口两口宝剑,而是千口万口利剑。” 67 | 勾践登时省悟,忍不住“啊哟”一声,转眼向文种、范蠡二人瞧去,只见文种满脸焦虑之色,范蠡却是呆呆出神,问道:“范大夫,你以为如何?”范蠡道:“伍子胥虽然诡计多端,别说此人已死,就算仍在世上,也终究逃不脱大王的掌心。” 68 | 勾践笑道:“嘿嘿,只怕寡人不是伍子胥的对手。”范蠡道:“伍子胥已被大王巧计除去,难道他还能奈何我越国吗?”勾践呵呵大笑,道:“这话倒也不错。薛烛,你师兄听了伍子胥之言,便助他铸造利剑了?”薛烛道:“正是。风师哥当下便随着伍子胥,来到莫干山上的铸剑房,只见有一千余名剑匠正在铸剑,只是其法未见其善,于是风师兄逐一点拨,此后吴剑锋利,诸国莫及。”勾践点头道:“原来如此。” 69 | 薛烛道:“铸得一年,风师哥劳瘁过度,津力不支,便向伍子胥说起小人名字,伍子胥备下礼物,要风师哥来召小人前往吴国,相助风师哥铸剑。小人心想吴越世仇,吴国铸了利剑,固能杀齐人晋人,也能杀我越人,便劝风师哥休得再回吴国。”勾践道:“是啊,你这人甚有见识。” 70 | 薛烛磕头道:“多谢大王奖勉。可是风师哥不听小人之劝,当晚他睡在小人家中,半夜之中,他突然以利剑架在小人颈中,再砍去了小人四根手指,好教小人从此成为废人。” 71 | 勾践大怒,厉声说道:“下次捉到风胡子,定将他斩成肉酱。” 72 | 种道:“薛先生,你自己虽不能铸剑,但指点剑匠,咱们也能铸成千口万口利剑。”薛烛道:“回禀文大夫:铸剑之铁,吴越均有,唯津铜在越,良锡在吴。” 73 | 范蠡道:“伍子胥早已派兵守住锡山,不许百姓采锡,是不是?”薛烛脸现惊异之色,道:“范大夫,原来你早知道了。”范蠡微笑道:“我只是猜测而已,现下伍子胥已死,他的遗命吴人未必遵守。高价收购,要得良锡也是不难。” 74 | 勾践道:“然而远水救不着近火,待得采铜、炼锡、造炉、铸剑,铸得不好又要从头来起,少说也是两三年的事。如果夫差活不到这么久,岂不成终生之恨?” 75 | 种、范蠡同时躬身道:“是。臣等当再思良策。” 76 | 范蠡退出宫来,寻思:“大王等不得两三年,我是连多等一日一夜,也是……”想到这里,胸口一阵隐隐发痛,脑海中立刻出现了那个惊世绝艳的丽影。 77 | 那是浣纱溪畔的西施。是自己亲去访寻来的天下无双美女夷光,自己却亲身将她送入了吴宫。 78 | 从会稽到姑苏的路程很短,只不过几天的水程,但便在这短短的几天之中,两人情根深种,再也难分难舍。西施皓洁的脸庞上,垂着两颗珍珠一般的泪珠,声音像若耶溪中温柔的流水:“少伯,你答应我,一定要接我回来,越快越好,我日日夜夜的在等着你。你再说一遍,你永远永远不会忘了我。” 79 | 越国的仇非报不可,那是可以等的。但夷光在夫差的怀抱之中,妒忌和苦恼在咬啮着他的心。必须尽快大批铸造利剑,比吴国剑士所用利剑更加锋锐…… 80 | 他在街上漫步,十八名卫士远远在后面跟着。 81 | 突然间长街西首传来一阵吴歌合唱:“我剑利兮敌丧胆,我剑捷兮敌无首……” 82 | 八名身穿青衣的汉子,手臂挽着手臂,放喉高歌,旁若无人的大踏步过来。行人都避在一旁。那正是昨日在越宫中大获全胜的吴国剑士,显然喝了酒,在长街上横冲直撞。 83 | 范蠡皱起了眉头,愤怒迅速在胸口升起。 84 | 八名吴国剑士走到了范蠡身前。为首一人醉眼惺忪,斜睨着他,说道:“你……你是范大夫……哈哈,哈哈,哈哈!”范蠡的两名卫士抢了上来,挡在范蠡身前,喝道:“不得无礼,闪开了!”八名剑士纵声大笑,学着他们的声调,笑道:“不得无礼,闪开了!”两名卫士怞出长剑,喝道:“大王有命,冲撞大夫者斩!” 85 | 为首的吴国剑士身子摇摇晃晃,说道:“斩你,还是斩我?” 86 | 范蠡心想:“这是吴国使臣,虽然无礼,不能跟他们动手。”正要说:“让他过去!”突然间白光闪动,两名卫士齐声惨叫,跟着当当两声响,两人右手手掌随着所握长剑都已掉在地下。那为首的吴国剑士缓缓还剑入鞘,满脸傲色。 87 | 范蠡手下的十六名卫士一齐拔剑出鞘,团团将八名吴国剑士围住。 88 | 为首的吴士仰天大笑,说道:“我们从姑苏来到会稽,原是不想再活着回去,且看你越宫要动用多少军马,来杀我吴国八名剑士。”说到最后一个“士”字时,一声长啸,八人同时执剑在手,背靠背的站在一起。 89 | 范蠡心想:“小不忍则乱大谋,眼下我国准备未周,不能杀了这八名吴士,致与夫差起衅。”喝道:“这八名是上国使者,大家不得无礼,退开了!”说着让在道旁。他手下卫士都是怒气填膺,眼中如要喷出火来,只是大夫有令,不敢违抗,当即也都让在街边。 90 | 八名吴士哈哈大笑,齐声高歌:“我剑利兮敌丧胆,我剑捷兮敌无首!” 91 | 忽听得咩咩羊叫,一个身穿浅绿衫子的少女赶着十几头山羊,从长街东端走来。这群山羊来到吴士之前,便从他们身边绕过。 92 | 一名吴士兴犹未尽,长剑一挥,将一头山羊从头至婰,剖为两半,便如是划定了线仔细切开一般,连鼻子也是一分为二,两片羊身分倒左右,剑术之津,实是骇人听闻。七名吴士大声喝彩。范蠡心中也忍不住叫一声:“好剑法!” 93 | 那少女手中竹棒连挥,将余下的十几头山羊赶到身后,说道:“你为甚么杀我山羊?”声音又娇嫩,也寒有几分愤怒。 94 | 那杀羊吴士将溅着羊血的长剑在空中连连虚劈,笑道:“小姑娘,我要将你也这样劈为两半!” 95 | 范蠡叫道:“姑娘,你快过来,他们喝醉了酒。” 96 | 那少女道:“就算喝醉了酒,也不能随便欺侮人。” 97 | 那吴国剑士举剑在她头顶绕了几个圈子,笑道:“我本想将你这小脑袋瓜儿割了下来,只是瞧你这么漂亮,可当真舍不得。”七名吴士一齐哈哈大笑。 98 | 范蠡见这少女一张瓜子脸,睫长眼大,皮肤白晰,容貌甚是秀丽,身材苗条,弱质纤纤,心下不忍,又叫:“姑娘,快过来!”那少女转头应声道:“是了!” 99 | 那吴国剑士长剑探出,去割她腰带,笑道:“那也……”只说得两个字,那少女手中竹棒一抖,戳在他手腕之上。那剑士只觉腕上一阵剧痛,呛啷一声,长剑落地。那少女竹棒挑起,碧影微闪,已刺入他左眼之中。那剑士大叫一声,双手捧住了眼睛,连声狂吼。 100 | 这少女这两下轻轻巧巧的刺出,戳腕伤目,行若无事,不知如何,那吴国剑士竟是避让不过。余下七名吴士大吃一惊,一名身材魁梧的吴士提起长剑,剑尖也往少女左眼刺去。剑招嗤嗤有声,足见这一剑劲力十足。 101 | 那少女更不避让,竹棒刺出,后发先至,噗的一声,刺中了那吴士的右肩。那吴士这一剑之劲立时卸了。那少女竹棒挺出,已刺入他右眼之中。那人杀猪般的大嗥,双拳乱挥乱打,眼中鲜血涔涔而下,神情甚是可怖。 102 | 这少女以四招戳瞎两名吴国剑士的眼睛,人人眼见她只是随手挥刺,对手便即受伤,无不耸然动容。六名吴国剑士又惊又怒,各举长剑,将那少女围在核心。 103 | 范蠡略通剑术,眼见这少女不过十六七岁年纪,只用一根竹棒便戳瞎了两名吴国高手的眼睛,手法如何虽然看不清楚,但显是极上乘的剑法,不由得又惊又喜,待见六名剑士各挺兵刃围住了她,,心想她剑术再津,一个少女终是难敌六名高手,当即郎声说道:“吴国众位剑士,六个打一个,不怕坏了吴国的名声?倘若以多为胜,嘿嘿!”双手一拍,十六名越国卫士立即挺剑散开,围住了吴国剑士。 104 | 那少女冷笑道:“六个打一个,也未必会赢!”左手微举,右手中的竹棒已向一名吴士眼中戳去。那人举剑挡格,那少女早已兜转竹棒,戳向另一名吴士胸口。便在此时,三名吴士的长剑齐向那少女身上刺到。那少女身法灵巧之极,一转一侧,将来剑尽数避开,噗的一声,挺棒戳中左首一名吴士的手腕。那人五指不由自主的松了,长剑落地。 105 | 十六名越国卫士本欲上前自外夹击,但其时吴国剑士长剑使开,已然幻成一道剑网,青光闪烁,那些越国卫士如何欺得近身? 106 | 却见那少女在剑网之中飘忽来去,浅绿色布衫的衣袖和带子飞扬开来,好看已极,但听得“啊哟”、呛啷之声不断,吴国众剑士长剑一柄柄落地,一个个退开,有的举手按眼,有的蹲在地下,每一人都被刺瞎了一只眼睛,或伤左目,或损右目。 107 | 那少女收棒而立,娇声道:“你们杀了我羊儿,赔是不赔?” 108 | 八名吴国剑士又是惊骇,又是愤怒,有的大声咆哮,有的全身发抖。这八人原是极为勇悍的吴士,即使给人砍去了双手双足,也不会害怕示弱,但此刻突然之间为一个牧羊少女所败,实在摸不着半点头脑,震骇之下,心中都是一团混乱。 109 | 那少女道:“你们不赔我羊儿,我连你们另一只眼睛也戳瞎了。”八剑士一听,不约而同的都退了一步。 110 | 范蠡叫道:“这位姑娘,我赔你一百只羊,这八个人便放他们去吧!”那少女向他微微一笑,道:“你这人很好,我也不要一百只羊,只要一只就够了。” 111 | 范蠡向卫士道:“护送上国使者回宾馆休息,请医生医治伤目。”卫士答应了,派出八人,挺剑押送。八名吴士手无兵刃,便如打败了的公鸡,垂头丧气的走开。 112 | 范蠡走上几步,问道:“姑娘尊姓?”那少女道:“你说甚么?”范蠡道:“姑娘姓甚么?”那少女道:“我叫阿青,你叫甚么?” 113 | 范蠡微微一笑:心想:“乡下姑娘,不懂礼法,只不知她如何学会了这一身出神入化的剑术。只须问到她的师父是谁,再请她师父来教练越士,何愁吴国不破?”想到和西施重逢的时刻指日可期,不由得心口感到一阵爇烘烘得暖意,说道:“我叫范蠡,姑娘,请你到我家吃饭去。”阿青道:“我不去,我要赶羊去吃草。”范蠡道:“我家里有大好的草地,你赶羊去吃,我再赔你十头肥羊。” 114 | 阿青拍手笑道:“你家里有大草地吗?那好极了。不过我不要你赔羊,我这羊儿又不是你杀的。”她蹲下地来,抚摸被割成了两片的羊身,凄然道:“好老白,乖老白,人家杀死了你,我……我可救你不活了。” 115 | 范蠡吩咐卫士道:“把老白的两片身子缝了起来,去埋在姑娘屋子的旁边。” 116 | 阿青站起身来,面额上有两滴泪珠,眼中却透出喜悦的光芒,说道:“范蠡,你……你不许他们把老白吃了?”范蠡道:“自然不许。那是你的好老白,乖老白,谁都不许吃。”阿青叹了口气,道:“你真好。我最恨人家拿我的羊儿去宰来吃了,不过妈说,羊儿不卖给人家,我们就没钱买米。”范蠡道:“打从今儿起,我时时叫人送米送布给你妈,你养的羊儿,一只也不用卖。”阿青大喜,一把抱住范蠡,叫道:“你真是个好人。” 117 | 众卫士见她天真烂漫,既直呼范蠡之名,又当街抱住了他,无不好笑,都转过了头,不敢笑出声来。 118 | 范蠡挽住了她的手,似乎生怕这是个天上下凡的仙女,一转身便不见了,在十几头山羊的咩咩声中,和她并肩缓步,同回府中。 119 | 阿青赶着羊走进范蠡的大夫第,惊道:“你这屋子真大,一个人住得了吗?”范蠡微微一笑,说道:“我正嫌屋子太大,回头请你妈和你一起来住好不好?你家里还有什么人?”阿青道:“就是我妈和我两个人,不知道我妈肯不肯来。我妈叫我别跟男人多说话。不过你是好人,不会害我们的。” 120 | 范蠡要阿青将羊群赶入花园之中,命婢仆取出糕饼点心,在花园的凉亭中殷勤款待。众仆役见羊群将花园中的牡丹、芍药、玫瑰种种名花异卉大口咬嚼,而范蠡却笑吟吟的瞧着,无不骇异。 121 | 阿青喝茶吃饼,很是高兴。范蠡跟她闲谈半天,觉她言语幼稚,于世务全然不懂,终于问道:“阿青姑娘,教你剑术的那位师父是谁?” 122 | 阿青睁着一双明澈的大眼,道:“什么剑术?我没有师父啊。”范蠡道:“你用一根竹棒戳瞎了八个坏人的眼睛,这本事就是剑术了,那是谁教你的?”阿青摇头道:“没有人教我,我自己会的。”范蠡见她神情坦率,实无丝毫作伪之态,心下暗异:“难道当真是天降异人?”说道:“你从小就玩这竹棒?” 123 | 阿青道:“本来是不会的,我十三岁那年,白公公来骑羊玩儿,我不许他骑,用竹棒来打我,我就和他对打。起初他总是打到我,我打不着他。我们天天这样打着玩,近来我总是打到他,戳得他很痛,他可戳我不到。他也不大来跟我玩了。” 124 | 范蠡又惊又喜,道:“白公公住在哪里?你带我去找他好不好?”阿青道:“他住在山里,找他不到的。只有他来找我,我从来没去找过他。”范蠡道:“我想见见他,有没有法子?”阿青沉吟道:“嗯,你跟我一起去牧羊,咱们到山边等他。就是不知道他什么时候会来。”叹了口气道:“进来好久没见到他啦!” 125 | 范蠡心想:“为了越国和夷光,跟她去牧羊却又怎地?”便道:“好啊,我就陪你去牧羊,等那位白公公。”寻思:“这阿青姑娘的剑术,自然是那位山中老人白公公所教的了。料想白公公见她年幼天真,便装作用竹棒跟她闹着玩。他能令一个乡下姑娘学到如此神妙的剑术,请他去教练越国吴士,破吴必矣!” 126 | 请阿青在府中吃了饭后,便跟随她同到郊外的山里去牧羊。他手下部属不明其理,均感骇怪。一连数日,范蠡手持竹棒,和阿青在山野间牧羊唱歌,等候白公公到来。 127 | 第五日上,文种来到范府拜访,见范府掾吏面有忧色,问道:“范大夫多日不见,大王颇为挂念,命我前来探望,莫非范大夫身子不适么?”那掾吏道:“回禀文大夫:范大夫身子并无不适,只是……只是……”文种道:“只是怎样?”那掾吏道:“文大夫是范大夫的好友,我们下吏不敢说的话,文大夫不妨去劝劝他。”文种更是奇怪,问道:“范大夫有什么事?”那掾吏道:“范大夫迷上了那个……那个会使竹棒的乡下姑娘,每天一早便陪着她去牧羊,不许卫士们跟随保护,直到天黑才会来。小吏有公务请示,也不敢前去打扰。” 128 | 种哈哈大笑,心想:“范贤弟在楚国之时,楚人都叫他范疯子。他行事与众不同,原非俗人所能明白。” 129 | 这时范蠡正坐在山坡草地上,讲述楚国湘妃和山鬼的故事。阿青坐在他身畔凝神倾听,一双明亮的眼睛,目不转瞬的瞧着他,忽然问道:“那湘妃真是这样好看么?” 130 | 范蠡轻轻说道:“她的眼睛比这溪水还要明亮,还要清澈……”阿青道:“她眼睛里有鱼游么?”范蠡道:“她的皮肤比天上的白云还要柔和,还要温软……”阿青道:“难道也有小鸟在云里飞吗?”范蠡道:“她的嘴唇比这朵小红花的花瓣还要娇嫩,还要鲜艳,她的嘴唇湿湿的,比这花瓣上的露水还要晶莹。湘妃站在水边,倒影映在清澈的湘江里,江边的鲜花羞惭的都枯萎了,鱼儿不敢在江里游,生怕弄乱了她美丽的倒影。她白雪一般的手伸到湘江里,柔和得好像要溶在水里一样……” 131 | 阿青道:“范蠡,你见过她的是不是?为甚么说得这样仔细?” 132 | 范蠡轻轻叹了口气,说道:“我见过她的,我瞧得非常非常仔细。” 133 | 他说的是西施,不是湘妃。 134 | 他抬头向着北方,眼光飘过了一条波浪滔滔的大江,这美丽的女郎是在姑苏城中吴王宫里,她这时候在做什么?是在陪伴吴王么?是在想着我么? 135 | 阿青道:“范蠡,你的胡子中有两根是白色的,真有趣,像是我羊儿的毛一样。” 136 | 范蠡想:分手的那天,她伏在我肩上哭泣,泪水湿透了我半边衣衫,这件衫子我永远不洗,她的泪痕之中,又加上了我的眼泪。 137 | 阿青说:“范蠡,我想拔你一根胡子来玩,好不好?我轻轻的拔,不会弄痛你的。” 138 | 范蠡想:她说最爱坐了船在江里湖里慢慢的顺水漂流,等我将她夺回来之后,我大夫也不做了,便是整天和她坐了船,在江里湖里漂流,这么漂游一辈子。 139 | 突然之间,颏下微微一痛,阿青已拔下了他一根胡子,只听得她在咯咯娇笑,蓦地里笑声中断,听得她喝道:“你又来了!” 140 | 绿影闪动,阿青已激射而出,只见一团绿影、一团白影已迅捷无轮的缠斗在一起。 141 | 范蠡大喜:“白公公到了!”眼见两人斗得一会,身法渐渐欢乐下来,他忍不住“啊”的一声叫了出来。 142 | 和阿青相斗的竟然不是人,而是一头白猿。 143 | 这白猿也拿着一根竹棒,和阿青手中竹棒纵横挥舞的对打。这白猿出棒招数巧妙,劲道凌厉,竹棒刺出时带着呼呼风声,但每一棒刺来,总是给阿青拆解开去,随即以巧妙之极的招数还击过去。 144 | 数日前阿青与吴国剑士在长街相斗,一棒便戳瞎一名吴国剑士的眼睛,每次出棒都一式一样,直到此刻,范蠡方见到阿青剑术之津。他于剑术虽然所学不多,但常去临观越国剑士练剑,剑法优劣一眼便能分别。当日吴越剑士相斗,他已看得挤舌不下,此时见到阿青和白猿斗剑,手中所持虽然均是竹棒,但招法之津奇,吴越剑士相形之下,直如儿戏一般。 145 | 白猿的竹棒越使越快,阿青却时时凝立不动,偶尔一棒刺出,便如电光急闪,逼得白猿接连倒退。 146 | 阿青将白猿逼退三步,随即收棒而立。那白猿双手持棒,身子飞起,挟着一股劲风,向阿青急刺过来。范蠡见到这般猛恶的情势,不由得大惊,叫道:“小心!”却见阿青横棒挥出,拍拍两声轻响,白猿的竹棒已掉在地下。 147 | 白猿一声长啸,跃上树梢,接连几个纵跃,已窜出数十丈外,但听得啸声凄厉,渐渐远去,山谷间猿啸回声,良久不绝。 148 | 阿青回过身来,叹了口气,道:“白公公断了两条手臂,再也不肯来跟我玩了。”范蠡道:“你打断了它两条手臂?”阿青点头道:“今天白公公凶得很,一连三次,要扑过来刺死你。”范蠡惊道:“它……它要刺死我?为什么?”阿青摇了摇头,道:“我不知道。”范蠡暗暗心惊:“若不是阿青挡住了它,这白猿要刺死我当真是不费吹灰之力。” 149 | 第二天早晨,在越王的剑室之中,阿青手持一根竹棒,面对着越国二十名第一流剑手。范蠡知道阿青不会教人如何使剑,只有让越国剑士模仿她的剑法。 150 | 但没一个越国剑士能当到她的三招。 151 | 阿清竹棒一动,对手若不是手腕被戳,长剑脱手,便是要害中棒,委顿在地。 152 | 第二天,三十名剑士败在她的棒下。第三天,又是三十名剑士在她一根短竹棒下腕折臂断,狼狈败退。 153 | 到第四天上,范蠡再要找她去会斗越国剑士时,阿青已失了踪影,寻到她的家里,只余下一间空屋,十几头山羊。范蠡派遣数百名部署在会稽城内城外,荒山野岭中去找寻,在也觅不到这个小姑娘的踪迹。 154 | 八十名越国剑士没学到阿青的一招剑法,但他们已亲眼见到了神剑的影子。每个人都知道了,世间确有这样神奇的剑法。八十个人将一丝一忽勉强捉摸到的剑法影子传授给了旁人,单是这一丝一忽的神剑影子,越国吴士的剑法便已无敌于天下。 155 | 范蠡命薛烛督率良工,铸成了千千万万口利剑。 156 | 三年之后,勾践兴兵伐吴,战于五湖之畔。越军五千人持长剑面前,吴兵逆击。两军交锋,越兵长剑闪烁,吴兵当者披靡,吴师大败。 157 | 吴王夫差退到余杭山。越兵追击,二次大战,吴病始终挡不住越兵的快剑。夫差兵败自杀。越军攻入吴国的都城姑苏。 158 | 范蠡亲领长剑手一千,直冲到吴王的馆娃宫。那是西施所住的地方。他带了几名卫士,奔进宫去,叫道:“夷光,夷光!” 159 | 他奔过一道长廊,脚步成发出清朗的回声,长廊下面是空的。西施脚步轻盈,每一步都像是弹琴鼓瑟那样,有美妙的音乐节拍。夫差建了这道长廊,好听她奏着音乐般的脚步声。 160 | 在长廊彼端,音乐般的脚步声响了起来,像欢乐的锦瑟,像清和的瑶琴,一个轻柔的声音在说:“少伯,真的是你么?” 161 | 范蠡胸口爇血上涌,说道:“是我,是我!我来接你了。”他听得自己的声音嘶嘎,好像是别人在说话,好像是很远很远的声音。他踉踉跄跄的奔过去。 162 | 长廊上乐声繁音促节,一个柔软的身子扑入了他怀里。 163 | 春夜溶溶。花香从园中透过帘子,飘进馆娃宫。范蠡和西施在倾诉着别来得相思。 164 | 忽然间寂静之中传来了几声咩咩的羊叫。 165 | 范蠡微笑道:“你还是忘不了故乡的风光,在宫室之中也养了山羊吗?” 166 | 西施笑着摇了摇头,她有些奇怪,怎么会有羊叫?然而在心爱之人的面前,除了温柔的爱念,任何其他的念头都不会在心中停留长久。她慢慢伸手出去,握住了范蠡的左手。炽爇的血同时在两人脉管中迅速流动。 167 | 突然间,一个女子声音在静夜中响起:“范蠡!你叫你的西施出来,我要杀了她!” 168 | 范蠡陡地站起身来。西施感到他的手掌忽然间变得冰冷。范蠡认得这是阿青的声音。她的呼声越过馆娃宫的高墙,飘了进来。 169 | “范蠡,范蠡,我要杀你的西施,她逃不了的。我一定要杀你的西施。” 170 | 范蠡又是惊恐,又是迷惑:“她为甚么要杀夷光?夷光可从来没得罪过她!”蓦地立心中一亮,霎时之间都明白了:“她并不真是个不懂事的乡下姑娘,她一直在喜欢我。” 171 | 迷惘已去,惊恐更甚。 172 | 范蠡一生临大事,决大疑,不知经历过多少风险,当年在会稽山被吴军围困,粮尽援绝之时,也不及此刻的惧怕。西施感到他手掌中湿腻腻的都是冷汗,觉到他的手掌在发抖。 173 | 如果阿青要杀的是他自己,范蠡不会害怕的,然而她要杀的是西施。 174 | “范蠡,范蠡!我要杀了你的西施,她逃不了的!” 175 | 阿青的声音忽东忽西,在宫墙外传进来。 176 | 范蠡定了定神,说道:“我要去见见这人。”轻轻放脱了西施的手,快步向宫门走去。 177 | 十八名卫士跟随在他身后。阿青的呼声人人都听见了,耳听得她在宫外直呼破吴英雄范大夫之名,大家都感到十分诧异。 178 | 范蠡走到宫门之外,月光铺地,一眼望去,不见有人,朗声说道:“阿青姑娘,请你过来,我有话说。”四下里寂静无声。范蠡又道:“阿青姑娘,多时不见,你可好么?”可是仍然不闻回答。范蠡等了良久,始终不见阿青现身。 179 | 他低声吩咐卫士,立即调来一千名甲士、一千名剑士,在馆娃宫前后守卫。 180 | 他回到西施面前,坐了下来,握住她的双手,一句话也不说。从宫外回到西施身畔,他心中已转过了无数念头:“令一个宫女假装夷光,让阿青杀了她?我和夷光化装成为越国甲士,逃出吴宫,从此隐姓埋名?阿青来时,我在她面前自杀,求她饶了夷光?调二千名弓箭手守住宫门,阿青若是硬闯,那便万剑齐发,射死了她?”但每一个计策都有破绽。阿青于越国有大功,也不忍将她杀死,他怔怔的瞧着西施,心头忽然感到一阵温暖:“我二人就这样一起死了,那也好得很。我二人在临死之前,终于是聚在一起了。” 181 | 时光缓缓流过。西施觉到范蠡的手掌温暖了。他不再害怕,脸上露出了笑容。 182 | 破晓的日光从窗中照射进来。 183 | 蓦地里宫门外响起了一阵吆喝声,跟着呛啷郎、呛啷朗响声不绝,那是兵刃落地之声。这声音从宫门外直响进来,便如一条极长的长蛇,飞快的游来,长廊上也响起了兵刃落地的声音。一千名甲士和一千名剑士阻挡不了阿青。 184 | 只听得阿青叫道:“范蠡,你在哪里?” 185 | 范蠡向西施瞧了一眼,朗声道:“阿青,我在这里。” 186 | “里”字的声音甫绝,嗤的一声响,门帷从中裂开,一个绿衫人飞了进来,正是阿青。她右手竹棒的尖端指住了西施的心口。 187 | 她凝视着西施的容光,阿青脸上的杀气渐渐消失,变成了失望和沮丧,再变成了惊奇、羡慕,变成了崇敬,喃喃的说:“天……天下竟有着……这样的美女!范蠡,她……她比你说的还……还要美!”纤腰扭处,一声清啸,已然破窗而出。 188 | 清啸迅捷之极的远去,渐远渐轻,余音袅袅,良久不绝。 189 | 数十名卫士疾步奔到门外。卫士长躬身道:“大夫无恙?”范蠡摆了摆手,众卫士退了下去。范蠡握着西施的手,道:“咱们换上庶民的衣衫,我和你到太湖划船去,再也不回来了。” 190 | 西施眼中闪出无比快乐的光芒,忽然之间,微微蹙起了眉头,伸手捧着心口。阿青这一棒虽然没戳中她,但棒端发出的劲气已刺伤了她心口。 191 | 两千年来人们都知道,“西子捧心”是人间最美丽的形象。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《深度学习必修课:进击算法工程师》配套代码 2 | 3 | ## 简介 4 | 5 | 课程总共16章100节,会帮你打牢深度学习基础,包括必要数学概念和代码工具,从最简单的多层感知机开始,循着深度学习的发展脉络带你掌握CNN、RNN及其各种变体。同时会带你熟悉业界前沿技术,包括注意力机制、概率图模型、迁移学习等核心知识。最后还会有计算机视觉、自然语言处理和多模态AI内容生成方面最新模型和实战介绍,手把手带你实现贴合工业界需求的案例项目。 6 | 7 | ## 相关内容 8 | 9 | [B站](https://space.bilibili.com/1921388479) [知乎](https://www.zhihu.com/people/qiu-qiu-27-64-51) [课程链接](https://appmixy0usl5902.h5.xiaoeknow.com) 10 | 11 | ![catalog](./assets/catalog.png) 12 | 13 | -------------------------------------------------------------------------------- /assets/catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gengzhige/Deep-Learning-Code/7897466284437bafb53fdf688281aa160fb2c06d/assets/catalog.png --------------------------------------------------------------------------------