0%

matplotlib.animation:MovieWriter

在使用 matplotlib.animation:MovieWriter 存储影片时 memory 和 cache 不够

1
2
3
WARNING:matplotlib.animation:MovieWriter stderr:
convert-im6.q16: cache resources exhausted `./gym_animation.gif' @ error/cache.c/OpenPixelCache/4083.
convert-im6.q16: memory allocation failed `./gym_animation.gif' @ error/quantize.c/AssignImageColors/496

原因:For some reason, my ImageMagick came with very low limits:

cache 不够

解决办法:清理 pip cache

1
2
3
4
cd ~/.cache/pip
sudo rm -rf *
# 或者在 pip 安装的时候,跳过缓存
pip install ... --no-cache-dir

字符串 array 用 np.save 储存成 csv 档案

1
2
3
# 报错 TypeError: Mismatch between array dtype ('<U21') and format specifier ('%.18e,%.18e')
#You have to specify the format (fmt) of you data in savetxt, in this case as a string (% s):
np.savetxt ('test.csv', DAT, delimiter="", fmt="% s")

transforms.Resize () 只接受 PIL 类型

可以参考的 implement

有用到 d4rl 和 Atari

1


pytorch tutorial

安装流程,主要参考这两篇,但是安装 python3.6 会有问题,于是我安装 python3.8
安装 mujoco, mujoco-py,gym [all],robosuite
这篇主要参考 dm_control 的安装

安装 tf-gpu

1
2
3
4
5
6
7
8
9
10
conda create -n mujoco_38 python==3.8
conda activate mujoco_38
# 注意,一定要用 conda 来安装,而不是 pip,conda 会帮你安装相关依赖。依赖冲突后面我们再解决
conda install tensorflow-gpu

python
# 进入 python 程序
import tensorflow as tf
sess = tf.Session ()
# 若上述命名执行没有报错,则说明 tensorflow 安装成功。

安装 mujoco210

(1) 下载 license—mjkey.txt
(2) 下载 mujoco210

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#(3) 在 home 目录下创建隐藏文件夹 mujoco,并将刚才下载好的安装包解压到这个文件夹下
mkdir ~/.mujoco
cp mujoco210-linux-x86_64.tar.gz ~/.mujoco
cd ~/.mujoco
tar -zxvf mujoco210-linux-x86_64.tar.gz
# 注意,这时候要修改 mujoco210_linux 文件夹名称为 mujoco210

#(4) 将获得的 mjkey.txt 放到~/.mujoco 和~/.mujoco/mujoco210/bin 下
cp mjkey.txt ~/.mujoco
cp mjkey.txt ~/.mujoco/mujoco210/bin
#(5) 添加环境变量,打开~/.bashrc 文件,将以下命令添加进去
vim ~/.bashrc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/root/.mujoco/mujoco210/bin
export LD_LIBRARY_PATH=~/.mujoco/mujoco210/bin${LID_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export MUJOCO_KEY_PATH=~/.mujoco${MUJOCO_KEY_PATH}
source ~/.bashrc
#(6) 运行测试
cd ~/.mujoco/mujoco210/bin
./simulate ../model/humanoid.xml

报错:./simulate: error while loading shared libraries: libXrandr.so.2: cannot open shared object file: No such file or directory
You need to install the missing library

安装 mujoco_py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 同样在 mujoco_38 环境中
#(0) 先下载一些库
sudo apt install libosmesa6-dev libgl1-mesa-glx libglfw3
#(1) 先在 github 上下载源码(或是使用 wget)
git clone https://github.com/openai/mujoco-py.git
#(2) pip 国内源
cd ~ && mkdir .pip
cd .pip && vim pip.conf
# 加入这四句话
[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host=pypi.douban.com
timeout = 6000
# 编译
cd ~/.mujoco/mujoco-py-master
pip install -r requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install -r requirements.dev.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
python setup.py install
# 测试
python
# 进入 python
import mujoco_py
1
2
3
4
5
6
7
8
9
# 常见错误 (1) gcc error:
# 试了网上很多解决办法,包括 mujoco_py 的 github 官方解决办法都不行,试了如下方法,完美解决
sudo apt-get update -q
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y curl libgl1-mesa-dev libgl1-mesa-glx libglew-dev libosmesa6-dev
sudo apt-get clean
rm -rf /var/lib/apt/lists/*

# 常见错误 (2) No such file or directory: ‘patchelf’
conda install -y patchelf

安装 gym [all]

1
2
3
4
5
6
7
8
9
# 方法 1
git clone https://github.com/openai/gym.git
python setup.py install

# 方法 2
pip install gym [all] --no-deps mujoco_py

# 方法 3
conda install gym

安装 dm_control

1
2
3
4
5
6
7
8
git clone https://github.com/deepmind/dm_control.git
cd dm_control
pip install -r requirements.txt
python setup.py install
# 遇到 GL/glew.h 问题需要
sudo apt-get install libosmesa6-dev
# 遇到 absl 问题
pip install absl-py # 然后重新安装 dm_control

安装 d4rl

1
2
3
4
5
git clone https://github.com/rail-berkeley/d4rl.git
cd d4rl
pip install -e .
# 或
pip install git+https://github.com/rail-berkeley/d4rl@master#egg=d4rl

這些方法我試了都沒效
這些方法我試了都沒效
這些方法我試了都沒效
pip install -U -f https://github.com/deepmind/dm_control -e .
pip install -U -f https://github.com/rail-berkeley/d4rl -e .
這些方法我試了都沒效
pip install git+https://github.com/deepmind/dm_control@main#egg=dm_control

最后解决办法:
setup.py 中的 dm_control 和 mjrl

安装 opencv

1
2
pip install opencv-python
pip install opencv-contrib-python

补充注意事项

x86_64 = amd64

python 和 tensorflow 和各个软件之间都会有版本问题,要注意

Anaconda 创建环境、删除环境、激活环境、退出环境

conda create -n py36 python=3.6
conda remove -n py36 —all
conda activate py36
conda deactivate

anaconda 中的指定虚拟环境 python 版本升级

conda install python=3.6
但会有 package 匹配的问题,不如直接创立一个新环境

tensorflow1 和 2 的不同

AttributeError: module ‘tensorflow’ has no attribute ‘Session’

参数种类

【python】函数调用的参数规则、位置参数、关键参数、任意参数与解包

类的实例化

【Python】Missing 1 required positional argument 解决方案

python kwargs 传递多个参数

PackagesNotFoundError: The following packages are not available from current channels

一些解决办法

linux 下查看硬件架构

uname -m

ubuntu 安装 tar.gz 文件

1
2
3
4
5
tar -zxvf FileName.tar.gz
cd FileName
./configure
make
sudo make install

np.mean (data, axis=0) 函数

可以这么理解,axis 是几,那就表明哪一维度被压缩成 1

Python numpy 归一化和标准化 代码实现

1
2
3
4
def standardization (data):
mu = np.mean (data, axis=0)
sigma = np.std (data, axis=0)
return (data - mu) /sigma

犯的一些愚蠢错误

下载安装成 windows 的版本

参考

Ubuntu 18.04 强化学习 RL gym mujoco 环境配置
Installation error: “libgcrypt.so.11: cannot open shared object file”
安装 mujoco_py 遇到的一些问题与解决方法
fatal error: GL/osmesa.h: No such file or directory
ImportError:lib*.so—cannot open shared object file: No such file or directory
安装 Mujoco+Gym 踩的坑
安裝 pytorch
open3d free (): invalid pointer 未解之谜
【没派上用场】 linux 程序被 Killed,查看原因
ps -elf #查看进程

fatal error: GL/osmesa.h: No such file or directory
error while importing mujoco_py into python
/home/avi/miniconda3/compiler_compat/ld: cannot find -lmujoco150
/home/avi/miniconda3/compiler_compat/ld: cannot find -lglewosmesa

PackagesNotFoundError: The following packages are not available from current channels:

  • python==3.6

conda config —append channels conda-forge

下载 mujoco-py 2.0.2.9

conda update python

Ubuntu 安裝 CUDA cuDNN pytorch tensorflow mxnet

Ubuntu 安裝 CUDA cuDNN pytorch tensorflow mxnet

python3 自动继承 object 这个 class

[‘class‘, ‘delattr‘, ‘dir‘, ‘doc‘, ‘eq‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘gt‘, ‘hash‘, ‘init‘, ‘le‘, ‘lt‘, ‘ne‘, ‘new‘, ‘reduce‘, ‘reduce_ex‘, ‘repr‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘]

(待更:这些 attribute 的用法)

一个 object 就是某个 class 的 instance

怎么写一个 logger 模块

python log 从小白到入门

Python isinstance () 函数:判断 A 是否是 B 类型,输出 True 或 False

isinstance () 与 type () 区别:
type () 不会认为子类是一种父类类型,不考虑继承关系。
isinstance () 会认为子类是一种父类类型,考虑继承关系。

四种 python 底线命名

1.foo_

避免与 Python 的 built-in keywords 或 built-in functions 取一样的名字

2._foo

不希望他直接被访问

3.foo

Never invent such names; only use them as documented.

4.__foo

you have attributes that you do not want subclasses to use
(Python)底線 介紹!(轉錄)

一、前言

Objectives:

  • Solve a regression problem with deep neural networks (DNN).
  • Understand basic DNN training tips.
  • Familiarize yourself with PyTorch.

二、引入 python 库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"""# Import packages"""

# Numerical Operations
import math
import numpy as np

# Reading/Writing Data
import pandas as pd
import os
import csv

# For Progress Bar
from tqdm import tqdm

# Pytorch
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader, random_split

# For plotting learning curve
from torch.utils.tensorboard import SummaryWriter

三、Utility Functions

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

def same_seed (seed):
'''Fixes random number generator seeds for reproducibility.'''
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
np.random.seed (seed)
torch.manual_seed (seed)
if torch.cuda.is_available ():
torch.cuda.manual_seed_all (seed)

def train_valid_split (data_set, valid_ratio, seed):
'''Split provided training data into training set and validation set'''
valid_set_size = int (valid_ratio * len (data_set))
train_set_size = len (data_set) - valid_set_size
train_set, valid_set = random_split (data_set, [train_set_size, valid_set_size], generator=torch.Generator ().manual_seed (seed))
return np.array (train_set), np.array (valid_set)

def predict (test_loader, model, device):
model.eval () # Set your model to evaluation mode.
preds = []
for x in tqdm (test_loader):
x = x.to (device)
with torch.no_grad ():
pred = model (x)
preds.append (pred.detach ().cpu ())
preds = torch.cat (preds, dim=0).numpy ()
return preds
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

设置 torch.backends.cudnn.benchmark=True 将会让程序在开始时花费一点额外时间,为整个网络的每个卷积层搜索最适合它的卷积实现算法,进而实现网络的加速。适用场景是网络结构固定(不是动态变化的),网络的输入形状(包括 batch size,图片大小,输入的通道)是不变的,其实也就是一般情况下都比较适用。反之,如果卷积层的设置一直变化,将会导致程序不停地做优化,反而会耗费更多的时间。

torch.backends.cudnn.deterministic=True
每次返回的卷积算法将是确定的,即默认算法。cudnn 中包含很多卷积算法。基于 GEMM (General Matrix Multiply) 的,基于 FFT 的,基于 Winograd 算法的等等。

设置 seed () 里的数字就相当于设置了一个盛有随机数的 “聚宝盆”,一个数字代表一个 “聚宝盆”,当我们在 seed()的括号里设置相同的 seed,“聚宝盆” 就是一样的,从里面拿出的随机数就会相同。

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">rng</span> ():</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span> (<span class="number">5</span>):</span><br><span class="line"> np.random.seed (<span class="number">123</span>)</span><br><span class="line"> <span class="built_in">print</span> (np.random.rand (<span class="number">4</span>))</span><br><span class="line"> </span><br><span class="line">rng ()</span><br><span class="line">&gt;&gt;&gt;[<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"> [<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"> [<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"> [<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"> [<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">rng_n</span> ():</span></span><br><span class="line"> np.random.seed (<span class="number">123</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span> (<span class="number">5</span>):</span><br><span class="line"> <span class="built_in">print</span> (np.random.rand (<span class="number">4</span>))</span><br><span class="line"> </span><br><span class="line">rng_n ()</span><br><span class="line">&gt;&gt;&gt;[<span class="number">0.69646919</span> <span class="number">0.28613933</span> <span class="number">0.22685145</span> <span class="number">0.55131477</span>]</span><br><span class="line"> [<span class="number">0.71946897</span> <span class="number">0.42310646</span> <span class="number">0.9807642</span> <span class="number">0.68482974</span>]</span><br><span class="line"> [<span class="number">0.4809319</span> <span class="number">0.39211752</span> <span class="number">0.34317802</span> <span class="number">0.72904971</span>]</span><br><span class="line"> [<span class="number">0.43857224</span> <span class="number">0.0596779</span> <span class="number">0.39804426</span> <span class="number">0.73799541</span>]</span><br><span class="line"> [<span class="number">0.18249173</span> <span class="number">0.17545176</span> <span class="number">0.53155137</span> <span class="number">0.53182759</span>]</span><br></pre></td></tr></table></figure>
<p> 在神经网络中,参数默认是进行随机初始化的。如果不设置的话每次训练时的初始化都是随机的,导致结果不确定。如果设置初始化,则每次初始化都是固定的。<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> args.seed <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span>:</span><br><span class="line"> random.seed (args.seed) <span class="comment">#</span></span><br><span class="line"> torch.manual_seed (args.seed) <span class="comment"># 为 CPU 设置种子用于生成随机数,以使得结果是确定的    torch.cuda.manual_seed (args.seed) #为当前 GPU 设置随机种子;</span></span><br><span class="line"> cudnn.deterministic = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果使用多个 GPU,应该使用 torch.cuda.manual_seed_all () 为所有的 GPU 设置种子。</span></span><br></pre></td></tr></table></figure></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.utils.data.random_split (dataset, lengths, generator=&lt;torch._C.Generator <span class="built_in">object</span>&gt;)</span><br></pre></td></tr></table></figure>
<p> 在 CPU 中设置生成随机数的种子,并返回一个 torch.Generator 对象。当设置的种子固定下来的时候,之后依次 pytorch 生成的随机数序列也被固定下来。需要注意的是当只调用 torch.manual_seed () 一次时并不能生成相同的随机数序列。如果想要得到相同的随机数序列就需要每次产生随机数的时候都要调用一下 torch.manual_seed ()。<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">import</span> torch</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>torch.manual_seed (<span class="number">2</span>)</span><br><span class="line">&lt;torch._C.Generator <span class="built_in">object</span> at <span class="number">0x000001EB8F3A1918</span>&gt;</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span> (torch.randn (<span class="number">2</span>,<span class="number">2</span>))</span><br><span class="line">tensor ([[<span class="number">0.3923</span>, -<span class="number">0.2236</span>],</span><br><span class="line"> [-<span class="number">0.3195</span>, -<span class="number">1.2050</span>]])</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span> (torch.randn (<span class="number">2</span>,<span class="number">2</span>))</span><br><span class="line">tensor ([[<span class="number">1.0445</span>, -<span class="number">0.6332</span>],</span><br><span class="line"> [<span class="number">0.5731</span>, <span class="number">0.5409</span>]])</span><br><span class="line"></span><br></pre></td></tr></table></figure></p>
<p><a href="https://zhuanlan.zhihu.com/p/357075502">Pytorch:model.train () 和 model.eval () 用法和区别 </a></p>
<h3 id=" 四、Dataset”"><a href="# 四、Dataset”" class="headerlink" title=" 四、Dataset”"></a> 四、Dataset”</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">COVID19Dataset</span> (<span class="params">Dataset</span>):</span></span><br><span class="line"> <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"> x: Features.</span></span><br><span class="line"><span class="string"> y: Targets, if none, do prediction.</span></span><br><span class="line"><span class="string"> &#x27;&#x27;&#x27;</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, x, y=<span class="literal">None</span></span>):</span></span><br><span class="line"> <span class="keyword">if</span> y <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line"> self.y = y</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> self.y = torch.FloatTensor (y)</span><br><span class="line"> self.x = torch.FloatTensor (x)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getitem__</span>(<span class="params">self, idx</span>):</span></span><br><span class="line"> <span class="keyword">if</span> self.y <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line"> <span class="keyword">return</span> self.x [idx]</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">return</span> self.x [idx], self.y [idx]</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__len__</span>(<span class="params">self</span>):</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">len</span> (self.x)</span><br></pre></td></tr></table></figure>
<h3 id=" 五、Neural-Network-Model"><a href="# 五、Neural-Network-Model" class="headerlink" title=" 五、Neural Network Model"></a> 五、Neural Network Model</h3><p>Try out different model architectures by modifying the class below.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">My_Model</span> (<span class="params">nn.Module</span>):</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, input_dim</span>):</span></span><br><span class="line"> <span class="built_in">super</span> (My_Model, self).__init__()</span><br><span class="line"> <span class="comment"># <span class="doctag">TODO:</span> modify model&#x27;s structure, be aware of dimensions. </span></span><br><span class="line"> self.layers = nn.Sequential (</span><br><span class="line"> nn.Linear (input_dim, <span class="number">16</span>),</span><br><span class="line"> nn.ReLU (),</span><br><span class="line"> nn.Linear (<span class="number">16</span>, <span class="number">8</span>),</span><br><span class="line"> nn.ReLU (),</span><br><span class="line"> nn.Linear (<span class="number">8</span>, <span class="number">1</span>)</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">forward</span> (<span class="params">self, x</span>):</span></span><br><span class="line"> x = self.layers (x)</span><br><span class="line"> x = x.squeeze (<span class="number">1</span>) <span class="comment"># (B, 1) -&gt; (B)</span></span><br><span class="line"> <span class="keyword">return</span> x</span><br></pre></td></tr></table></figure>
<p>Pytorch Tensor 的通道排序:[batch, channel, height, weight]<br><a href="https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html">pytorch lenet</a><br><a href="https://blog.csdn.net/jokerxsy/article/details/108614661">nn.Conv1d\nn.Conv2d 以及 groups\dilation 参数的理解 </a><br><a href="https://www.jianshu.com/p/c1232e47661f">PyTorch 教程 - 3:PyTorch 中神经网络的构建与训练基础 </a><br><a href="https://blog.csdn.net/qq_26442553/article/details/81775449">Python 多继承与 super 使用详解 </a></p>
<p><img src="./machineLearning-1/1.png" alt=""></p>
<p><a href="https://blog.csdn.net/york1996/article/details/81949843">PyTorch 中 view 的用法 </a><br><a href="https://zhuanlan.zhihu.com/p/27382990"> 图像基本操作 torchvision.transforms</a></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span> ():</span></span><br><span class="line"> transform = transforms.Compose (</span><br><span class="line"> [transforms.ToTensor (),</span><br><span class="line"> transforms.Normalize ((<span class="number">0.5</span>, <span class="number">0.5</span>, <span class="number">0.5</span>), (<span class="number">0.5</span>, <span class="number">0.5</span>, <span class="number">0.5</span>))])</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 50000 张训练图片 </span></span><br><span class="line"> <span class="comment"># 第一次使用时要将 download 设置为 True 才会自动去下载数据集 </span></span><br><span class="line"> train_set = torchvision.datasets.CIFAR10 (root=<span class="string">&#x27;./data&#x27;</span>, train=<span class="literal">True</span>,</span><br><span class="line"> download=<span class="literal">False</span>, transform=transform)</span><br><span class="line"> train_loader = torch.utils.data.DataLoader (train_set, batch_size=<span class="number">36</span>,</span><br><span class="line"> shuffle=<span class="literal">True</span>, num_workers=<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 10000 张验证图片 </span></span><br><span class="line"> <span class="comment"># 第一次使用时要将 download 设置为 True 才会自动去下载数据集 </span></span><br><span class="line"> val_set = torchvision.datasets.CIFAR10 (root=<span class="string">&#x27;./data&#x27;</span>, train=<span class="literal">False</span>,</span><br><span class="line"> download=<span class="literal">False</span>, transform=transform)</span><br><span class="line"> val_loader = torch.utils.data.DataLoader (val_set, batch_size=<span class="number">5000</span>,</span><br><span class="line"> shuffle=<span class="literal">False</span>, num_workers=<span class="number">0</span>)</span><br><span class="line"> val_data_iter = <span class="built_in">iter</span> (val_loader)</span><br><span class="line"> val_image, val_label = val_data_iter.<span class="built_in">next</span> ()</span><br><span class="line"> ...</span><br></pre></td></tr></table></figure>
<p><img src="./machineLearning-1/photo2.png" alt=""></p>
<h3 id=" 六、Feature-Selection"><a href="# 六、Feature-Selection" class="headerlink" title=" 六、Feature Selection"></a> 六、Feature Selection</h3><p>Choose features you deem useful by modifying the function below.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">select_feat</span> (<span class="params">train_data, valid_data, test_data, select_all=<span class="literal">True</span></span>):</span></span><br><span class="line"> <span class="string">&#x27;&#x27;&#x27;Selects useful features to perform regression&#x27;&#x27;&#x27;</span></span><br><span class="line"> y_train, y_valid = train_data [:,-<span class="number">1</span>], valid_data [:,-<span class="number">1</span>]</span><br><span class="line"> raw_x_train, raw_x_valid, raw_x_test = train_data [:,:-<span class="number">1</span>], valid_data [:,:-<span class="number">1</span>], test_data</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> select_all:</span><br><span class="line"> feat_idx = <span class="built_in">list</span> (<span class="built_in">range</span> (raw_x_train.shape [<span class="number">1</span>]))</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> feat_idx = [<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>] <span class="comment"># <span class="doctag">TODO:</span> Select suitable feature columns.</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> raw_x_train [:,feat_idx], raw_x_valid [:,feat_idx], raw_x_test [:,feat_idx], y_train, y_valid</span><br></pre></td></tr></table></figure>
<h3 id=" 六、Training-Loop"><a href="# 六、Training-Loop" class="headerlink" title=" 六、Training Loop"></a> 六、Training Loop</h3><p>(1) batchsize:批大小。在深度学习中,一般采用 SGD 训练,即每次训练在训练集中取 batchsize 个样本训练;<br>(2) iteration:1 个 iteration 等于使用 batchsize 个样本训练一次;<br>(3) epoch:1 个 epoch 等于使用训练集中的全部样本训练一次;</p>
<p> 举个例子,训练集有 1000 个样本,batchsize=10,那么,<br> 训练完整个样本集需要:100 次 iteration,1 次 epoch。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">trainer</span> (<span class="params">train_loader, valid_loader, model, config, device</span>):</span></span><br><span class="line"></span><br><span class="line"> criterion = nn.MSELoss (reduction=<span class="string">&#x27;mean&#x27;</span>) <span class="comment"># Define your loss function, do not modify this.</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Define your optimization algorithm. </span></span><br><span class="line"> <span class="comment"># <span class="doctag">TODO:</span> Please check https://pytorch.org/docs/stable/optim.html to get more available algorithms.</span></span><br><span class="line"> <span class="comment"># <span class="doctag">TODO:</span> L2 regularization (optimizer (weight decay...) or implement by your self).</span></span><br><span class="line"> optimizer = torch.optim.SGD (model.parameters (), lr=config [<span class="string">&#x27;learning_rate&#x27;</span>], momentum=<span class="number">0.9</span>) </span><br><span class="line"></span><br><span class="line"> writer = SummaryWriter () <span class="comment"># Writer of tensoboard.</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> os.path.isdir (<span class="string">&#x27;./models&#x27;</span>):</span><br><span class="line"> os.mkdir (<span class="string">&#x27;./models&#x27;</span>) <span class="comment"># Create directory of saving models.</span></span><br><span class="line"></span><br><span class="line"> n_epochs, best_loss, step, early_stop_count = config [<span class="string">&#x27;n_epochs&#x27;</span>], math.inf, <span class="number">0</span>, <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> epoch <span class="keyword">in</span> <span class="built_in">range</span> (n_epochs):</span><br><span class="line"> model.train () <span class="comment"># Set your model to train mode.</span></span><br><span class="line"> loss_record = []</span><br><span class="line"></span><br><span class="line"> <span class="comment"># tqdm is a package to visualize your training progress.</span></span><br><span class="line"> train_pbar = tqdm (train_loader, position=<span class="number">0</span>, leave=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> x, y <span class="keyword">in</span> train_pbar:</span><br><span class="line"> optimizer.zero_grad () <span class="comment"># Set gradient to zero.</span></span><br><span class="line"> x, y = x.to (device), y.to (device) <span class="comment"># Move your data to device. </span></span><br><span class="line"> pred = model (x) </span><br><span class="line"> loss = criterion (pred, y)</span><br><span class="line"> loss.backward () <span class="comment"># Compute gradient (backpropagation).</span></span><br><span class="line"> optimizer.step () <span class="comment"># Update parameters.</span></span><br><span class="line"> step += <span class="number">1</span></span><br><span class="line"> loss_record.append (loss.detach ().item ())</span><br><span class="line"> </span><br><span class="line"> <span class="comment"># Display current epoch number and loss on tqdm progress bar.</span></span><br><span class="line"> train_pbar.set_description (<span class="string">f&#x27;Epoch [<span class="subst">&#123;epoch+<span class="number">1</span>&#125;</span>/<span class="subst">&#123;n_epochs&#125;</span>]&#x27;</span>)</span><br><span class="line"> train_pbar.set_postfix (&#123;<span class="string">&#x27;loss&#x27;</span>: loss.detach ().item ()&#125;)</span><br><span class="line"></span><br><span class="line"> mean_train_loss = <span class="built_in">sum</span> (loss_record)/<span class="built_in">len</span> (loss_record)</span><br><span class="line"> writer.add_scalar (<span class="string">&#x27;Loss/train&#x27;</span>, mean_train_loss, step)</span><br><span class="line"></span><br><span class="line"> model.<span class="built_in">eval</span> () <span class="comment"># Set your model to evaluation mode.</span></span><br><span class="line"> loss_record = []</span><br><span class="line"> <span class="keyword">for</span> x, y <span class="keyword">in</span> valid_loader:</span><br><span class="line"> x, y = x.to (device), y.to (device)</span><br><span class="line"> <span class="keyword">with</span> torch.no_grad ():</span><br><span class="line"> pred = model (x)</span><br><span class="line"> loss = criterion (pred, y)</span><br><span class="line"></span><br><span class="line"> loss_record.append (loss.item ())</span><br><span class="line"> </span><br><span class="line"> mean_valid_loss = <span class="built_in">sum</span> (loss_record)/<span class="built_in">len</span> (loss_record)</span><br><span class="line"> <span class="built_in">print</span> (<span class="string">f&#x27;Epoch [<span class="subst">&#123;epoch+<span class="number">1</span>&#125;</span>/<span class="subst">&#123;n_epochs&#125;</span>]: Train loss: <span class="subst">&#123;mean_train_loss:<span class="number">.4</span>f&#125;</span>, Valid loss: <span class="subst">&#123;mean_valid_loss:<span class="number">.4</span>f&#125;</span>&#x27;</span>)</span><br><span class="line"> writer.add_scalar (<span class="string">&#x27;Loss/valid&#x27;</span>, mean_valid_loss, step)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> mean_valid_loss &lt; best_loss:</span><br><span class="line"> best_loss = mean_valid_loss</span><br><span class="line"> torch.save (model.state_dict (), config [<span class="string">&#x27;save_path&#x27;</span>]) <span class="comment"># Save your best model</span></span><br><span class="line"> <span class="built_in">print</span> (<span class="string">&#x27;Saving model with loss &#123;:.3f&#125;...&#x27;</span>.<span class="built_in">format</span> (best_loss))</span><br><span class="line"> early_stop_count = <span class="number">0</span></span><br><span class="line"> <span class="keyword">else</span>: </span><br><span class="line"> early_stop_count += <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> early_stop_count &gt;= config [<span class="string">&#x27;early_stop&#x27;</span>]:</span><br><span class="line"> <span class="built_in">print</span> (<span class="string">&#x27;\nModel is not improving, so we halt the training session.&#x27;</span>)</span><br><span class="line"> <span class="keyword">return</span></span><br></pre></td></tr></table></figure>
<h2 id=" 七、Configurations"><a href="# 七、Configurations" class="headerlink" title=" 七、Configurations"></a> 七、Configurations</h2><p><code>config</code> contains hyper-parameters for training and the path to save your model.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">device = <span class="string">&#x27;cuda&#x27;</span> <span class="keyword">if</span> torch.cuda.is_available () <span class="keyword">else</span> <span class="string">&#x27;cpu&#x27;</span></span><br><span class="line">config = &#123;</span><br><span class="line"> <span class="string">&#x27;seed&#x27;</span>: <span class="number">5201314</span>, <span class="comment"># Your seed number, you can pick your lucky number. :)</span></span><br><span class="line"> <span class="string">&#x27;select_all&#x27;</span>: <span class="literal">True</span>, <span class="comment"># Whether to use all features.</span></span><br><span class="line"> <span class="string">&#x27;valid_ratio&#x27;</span>: <span class="number">0.2</span>, <span class="comment"># validation_size = train_size * valid_ratio</span></span><br><span class="line"> <span class="string">&#x27;n_epochs&#x27;</span>: <span class="number">3000</span>, <span class="comment"># Number of epochs. </span></span><br><span class="line"> <span class="string">&#x27;batch_size&#x27;</span>: <span class="number">256</span>, </span><br><span class="line"> <span class="string">&#x27;learning_rate&#x27;</span>: <span class="number">1e-5</span>, </span><br><span class="line"> <span class="string">&#x27;early_stop&#x27;</span>: <span class="number">400</span>, <span class="comment"># If model has not improved for this many consecutive epochs, stop training. </span></span><br><span class="line"> <span class="string">&#x27;save_path&#x27;</span>: <span class="string">&#x27;./models/model.ckpt&#x27;</span> <span class="comment"># Your model will be saved here.</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>“””# Dataloader<br>Read data from files and set up training, validation, and testing sets. You do not need to modify this part.<br>“””</p>
<h1 id="Set-seed-for-reproducibility"><a href="#Set-seed-for-reproducibility" class="headerlink" title="Set seed for reproducibility"></a>Set seed for reproducibility</h1><p>same_seed (config [‘seed’])</p>
<h1 id="train-data-size-2699-x-118-id-37-states-16-features-x-5-days"><a href="#train-data-size-2699-x-118-id-37-states-16-features-x-5-days" class="headerlink" title="train_data size: 2699 x 118 (id + 37 states + 16 features x 5 days)"></a>train_data size: 2699 x 118 (id + 37 states + 16 features x 5 days)</h1><h1 id="test-data-size-1078-x-117-without-last-day’s-positive-rate"><a href="#test-data-size-1078-x-117-without-last-day’s-positive-rate" class="headerlink" title="test_data size: 1078 x 117 (without last day’s positive rate)"></a>test_data size: 1078 x 117 (without last day’s positive rate)</h1><p>train_data, test_data = pd.read_csv (‘./covid.train.csv’).values, pd.read_csv (‘./covid.test.csv’).values<br>train_data, valid_data = train_valid_split (train_data, config [‘valid_ratio’], config [‘seed’])</p>
<h1 id="Print-out-the-data-size"><a href="#Print-out-the-data-size" class="headerlink" title="Print out the data size."></a>Print out the data size.</h1><p>print (f”””train_data size: {train_data.shape}<br>valid_data size: {valid_data.shape}<br>test_data size: {test_data.shape}”””)</p>
<h1 id="Select-features"><a href="#Select-features" class="headerlink" title="Select features"></a>Select features</h1><p>x_train, x_valid, x_test, y_train, y_valid = select_feat (train_data, valid_data, test_data, config [‘select_all’])</p>
<h1 id="Print-out-the-number-of-features"><a href="#Print-out-the-number-of-features" class="headerlink" title="Print out the number of features."></a>Print out the number of features.</h1><p>print (f’number of features: {x_train.shape [1]}’)</p>
<p>train_dataset, valid_dataset, test_dataset = COVID19Dataset (x_train, y_train), \<br> COVID19Dataset (x_valid, y_valid), \<br> COVID19Dataset (x_test)</p>
<h1 id="Pytorch-data-loader-loads-pytorch-dataset-into-batches"><a href="#Pytorch-data-loader-loads-pytorch-dataset-into-batches" class="headerlink" title="Pytorch data loader loads pytorch dataset into batches."></a>Pytorch data loader loads pytorch dataset into batches.</h1><p>train_loader = DataLoader (train_dataset, batch_size=config [‘batch_size’], shuffle=True, pin_memory=True)<br>valid_loader = DataLoader (valid_dataset, batch_size=config [‘batch_size’], shuffle=True, pin_memory=True)<br>test_loader = DataLoader (test_dataset, batch_size=config [‘batch_size’], shuffle=False, pin_memory=True)</p>

Start training!

1
2
3
4

model = My_Model (input_dim=x_train.shape [1]).to (device) # put your model and data on the same computation device.
trainer (train_loader, valid_loader, model, config, device)

Plot learning curves with tensorboard (optional)

Testing

The predictions of your model on testing set will be stored at pred.csv.

1
2
3
4
5
6
7
8
9
10
11
12
13

def save_pred (preds, file):
''' Save predictions to specified file '''
with open (file, 'w') as fp:
writer = csv.writer (fp)
writer.writerow (['id', 'tested_positive'])
for i, p in enumerate (preds):
writer.writerow ([i, p])

model = My_Model (input_dim=x_train.shape [1]).to (device)
model.load_state_dict (torch.load (config ['save_path']))
preds = predict (test_loader, model, device)
save_pred (preds, 'pred.csv')

Reference

This notebook uses code written by Heng-Jui Chang @ NTUEE (https://github.com/ga642381/ML2021-Spring/blob/main/HW01/HW01.ipynb)

一、深度学习基础

1. 前言

(1) 领域专家,数据科学家,AI 专家
Q:数据科学家和 AI 专家的区别?
数据科学家可以有两条职业规划
广:不断开拓模型在不同领域的应用
深:专攻一个领域,成为该领域的专家
(2) 2012 年令深度學習和 NVIDIA 股價火爆起來的真正關鍵──GPU
(3) 模型的可解释性
(4) 符号学可以和深度学习结合吗?可以,例如图神经网络
(5) 学习的阶段:看 -> 听 -> 看 + 听 -> 动手做 -> 讲解一遍给自己或别人听

2. 深度学习基础 - 线性神经网络,多层感知器

3. 卷积神经网络 - LeNet, Alexnet, VGG, Inception, Resnet

4. 循环神经网络 - RNN, GRU, LSTM, seq2seq

5. 注意力机制 - Attention, Transformer

6. 优化算法 - SGD, Momentum, Adam

7. 高性能算法 - 并行,多 GPU, 分布式

8. 计算机视觉 - 目标检测,语义分析

9. 自然语言处理 - 词嵌入,BERT

閱讀全文 »

一、安装

PyCharm+Anaconda+CUDA+Pytorch 安装教程(个人经验帖)

1. 工具的作用

(1) PyCharm

PyCharm 是一个 Python 语言的一个开发工具,类似于 Eclipse(Java)

(2) Anaconda

Anaconda 里面集成了很多关于 python 科学计算的第三方库。我们安装了它,就安装了很多我们需要用到的工具包

(3) CUDA(Compute Unified Device Architecture

CUDA 是显卡厂商 NVIDIA 推出的运算平台,可以针对 GPU 做加速神经网络计算。
CUDA™是一种由 NVIDIA 推出的通用并行计算架构,该架构使 GPU 能够解决复杂的计算问题。
cudnn 是 pytorch 搭建深度学习模型的依赖,没有它,不能运行卷积等操作。

(4) PyTorch 是一个开源的 Python 机器学习库,不仅能够实现强大的 GPU 加速,同时还支持动态神经网络

2. 安装

(1) 安装 Anaconda
(2) 打开 Anaconda Prompt
(3) 显卡配置(没有独立显卡,略)

CUDN 安装
cuDNN 下载

(4) 激活环境

检查 Python 版本:在 cmd 输入 python
管理环境

1
2
3
# 在 Anaconda Prompt 中输入
conda create -n pytorch python=3.7
conda activate pytorch

(5) 安装 pytorch
1
2
3
4
# 到 pytorch 官网查询安装指令
conda install pytorch torchvision cpuonly -c pytorch
# -c 参数指明了下载 pytorch 的通道,优先级比清华镜像更高
#(如果你有更改镜像源,会被盖过去)
(6) 验证 PyTorch 安装成功
1
2
3
4
5
# 在 Anaconda Prompt 中的 pytorch 环境中
# 输入 python 进到 python 界面
import torch
import torchvison
print (torch)

3.

(1)
(2)
(3)
(4)
1
 

Windows10 系统中配置安装 PyTorch 环境,无显卡配置

閱讀全文 »

介绍

作者

但丁

  • 中世纪伟大诗人
  • 文艺复兴的先驱
  • 意大利语之父

如果说西方文学史的殿堂只能保留两个名字,那只能是但丁和莎士比亚。但丁对后世的影响极为深远,我们中国的文化进程也深受其影响。比如,他曾激励戊戌变法失败后的梁启超,让在日本留学的鲁迅看到了用语言凝聚民族的希望,而发起 “白话文运动” 的胡适,效仿的正是但丁对意大利语的创造和革新。

但丁是用他惊人的原创力征服世界的。他发明了意大利语。但丁出生于 1265 年的意大利,当时意大利并不是一个统一的国家,只是一个地理概念。当时的欧洲通用语是拉丁文,各地老百姓说的语言被称为 “俗语”,英语、法语、意大利语,都是俗语。文人著书立说用的都是拉丁文,因为这种语言被认为是神圣和不朽的。拉丁文和俗语的关系,很像我们新文化运动前文言文和白话文的关系。

作品

《神曲》

  • 一部百科全书式作品
  • 一册不朽诗篇

简单地说,《神曲》写的是神游三界的故事:朝圣者但丁在人生旅途上迷失了,陷入了一片黑暗森林,找不到出路,这时,罗马大诗人维吉尔出现了,他和一个叫贝亚特丽斯的圣女带领但丁游历了地狱、炼狱和天堂,最终见到了上帝。

几个世纪以来,几乎每个重视教育的西方家庭中都有一本《神曲》,一般来说都是多雷的版画插图珍藏版,孩子们从小就阅读甚至背诵它,被其中或可怖或怪诞或恢宏的景象所征服。但其实,它实在是一本极为复杂的书。它是一部百科全书式作品,囊括了中世纪所有的人文知识,有着把整个宇宙囊括进去的野心。它写了一百多个人物,从地狱一路铺到天堂,这一百多个灵魂的故事,贯穿了从古希腊罗马到但丁生活的中世纪尾页的历史人物、神话人物、文学人物和与但丁同时代的真实人物。

创作神曲的原动力

贝亚特丽斯是最重要的事

美德美人 -> 精神苦恋 -> 私人神话 -> 永恒纪念

被佛罗伦萨放逐开始流亡

政治斗争 -> 放逐流亡 -> 独特观点 -> 创作史诗

那时候,流亡是对一个人最严厉的惩罚。因为在中世纪的观念中,一个人在城邦里占据的位置是他最重要的东西,不能占有城市中的一个位置,就意味着你什么也不是。这对一个致力于世俗生活的普通人来说是惩罚,但对一个诗人来说却是一种幸福。

开始流亡后,但丁彻底抛弃了忠于哪种党派的观念,开始拥有自己的独特观点。他开始了语言上的研究,试图找到一个统一的、可以综合所有意大利语言的可能,来描述以君主帝国来统一世界的必要性。他开始继续写作《神曲》,他的生命也因此重新绽放。这一次,他的创作从早年私人的爱情神话变成了属于公众的神话、史诗和百科全书。

神曲开篇

古罗马最伟大的诗人罗吉尔,他的灵活作为但丁的导师

神曲是有韵的诗,开篇的韵脚是由 vita(也就是 “生命” 这个词)和 smarrita(也就是 “迷失”)所构成的,故事的开局就是 “迷失的生命”。主人公是朝圣者但丁,一个迷途的普通人,而叙述者是全知全能的作者但丁,我们必须把这两者区分开。按照当时人对寿命的理解,人的寿命最长大约 70 岁,那么人生的中途就是 35 岁,一个容易产生中年危机的年龄。

开篇有一系列象征和用典。黑暗森林象征人类精神世界的种种罪恶和过失,也指当时的意大利社会的腐败和党派之争。三只猛兽来源于圣经中的典故,在《启示录》中代表 “反基督”,因为豹子(lonza)、狮子(leone)、狼(lupa)的意大利文都以字母 “l” 开头,这正是魔鬼路西法(Lucifer)名字的起首字母。豹象征的是肉欲和享乐,在政治上指的是将但丁驱逐出去的佛罗伦萨,狮子象征野心和强权,在政治上指法兰西国王出兵意大利,母狼象征贪欲,在政治上指的是贪婪的罗马教皇。在《地狱篇》第 2 歌中,但丁借维吉尔之口预言说,一只猎犬将成为意大利的救星,将象征贪欲的母狼赶回地狱,这只猎犬以 “智慧、爱和美德” 为食,指的是当时但丁给予厚望的君主:神圣罗马帝国的皇帝亨利七世。

你看,这里的象征都是具有双重含义的,既是在说人生面临的困境,也是在说意大利面临的困境,而但丁的写作意图也是双重的,他要讲述自己摆脱人性的诱惑,走出人生困境的旅程,也希望意大利能扫除罪恶,得到拯救。其实,《神曲》讲述的就是但丁在流亡期间,游走在不同城市之间,作为一个旁观者,深刻地发现意大利的真正问题所在的故事,他讲述自己对这个四分五裂的世界的认知,告诉人们如何才能齐心协力,从分裂走向整合。

朝圣者但丁的新三界

地狱

地狱最外围的一层叫灵泊,limbo,这里漂浮着古代圣贤的灵魂,其中有哲学家苏格拉底、诗人荷马,还有但丁诗歌上的老师维吉尔等等。你可能要问,他们有什么罪呢?

按照但丁的神学观念,古代圣贤生活在基督诞生之前,当然不可能有基督教信仰,所以,他们不能得到救赎,永远悬在半空,地狱不罚他们,天堂也不要他们。正像维吉尔说的,他们既不期盼,也不等候,不抱希望地存在着。所以,这其实也是一种惩罚,因为这种状态就是被放逐。但丁对灵泊的创造很可能来源于自己被放逐的经历。不同的是,但丁始终是怀有希望的。如今 limbo 早已成为一个常用词,用来指这种边缘和放逐的状态。比如电影《盗梦空间》中的 limbo,“迷失域”,指的就是潜意识的边缘,一种没有构建、没有秩序、仅有潜意识投射的状态。人一旦进入到这里,就会忘了自己在做梦,也忘了时间,这无疑是一种放逐。

我们再沿着《神曲》中的地狱往下走。真正的地狱开始于第二圈,这里住着色欲场中的灵魂,在狂风中飘荡;第三圈是犯了饕餮罪的,躺在臭雨冰雹之下,第四圈是贪婪浪费者,永远推着重物上山,互相冲撞;第五圈是愤怒者,他们的灵魂在死的河里争斗。地狱前五圈的罪基本对应的是 “七宗罪”:骄傲,妒忌,愤怒,懒惰,贪财,贪吃,贪色,第五圈之下是 “下层地狱”,这里的罪出自但丁的原创,因此分类也更详细。第六圈是不信灵魂存在的邪教徒。第七圈是残暴者,包括对他人施暴的人和对自己施暴的人也就是自杀者,以及对上帝残暴的人和对自然残暴的人等等。但丁的老师拉蒂尼就被安排在这一圈,学者认为,但丁给老师安排的罪名不太有说服力,他这么安排很可能只是为了凸显自己在道德上比老师更高尚。第八圈是欺诈者,包括但丁痛恨的贪官污吏、伪君子等,著名的尤利西斯的灵魂也在这里。第九圈是一个冰湖,罪人都冰冻在里面,中心是万恶所归的魔王路西法,就是撒旦。

爱欲问题是西方文化的关键词之一,很多学者认为,爱欲问题也是但丁的 “全部问题”。这里的爱是希腊语 Eros 也就是 “爱欲” 的爱,它是一种生命动力,类似于 “力比多” 和 “自由意志”。

在但丁心里,狂妄的求知欲是一种很深的罪。作为一个百科全书式的求知者,但丁是矛盾的。一方面,他像笔下的尤利西斯一样,想要穷尽一切知识,另一方面,按照他的信仰,求知欲始于过度的好奇,来自人对超越自身限度的善的渴望,而这种渴望是一种傲慢,傲慢是最深的罪。在圣经故事中,人类的始祖亚当夏娃正是因为过度的好奇而吃下智慧树的果子,有了原罪。对未知世界,正确的态度是保持几分审慎和谦卑。

炼狱

炼狱是一座山,形状跟地狱正相反,像一个倒立的漏斗,加上净界山和地上乐园,也是 9 层,越往上越接近天堂。炼狱的灵魂犯下的也是七宗罪,但跟地狱的灵魂不同的是,他们知道忏悔,还有得救的希望。

如果说《地狱篇》展示的是各种堕落的爱,《炼狱篇》展示的就是人用自由意志对爱欲的纠正,对爱之罪的医治。自由意志是《炼狱篇》重点讨论的关键词。

天堂

《天堂篇》所展示的,是爱的完满状态,这里居住着幸福的灵魂,他们是行善者、虔诚的教士、为信仰而战死的英雄、哲学家和神学家、正直的君主,基督和天使。

宇宙运转的真理 - 爱
这种爱,是基督教中的仁爱(caritas),或者说信仰之爱。

爱的完满状态就是兼具人性与神性,调和了尤利西斯的求知之爱,维吉尔的理智之爱,贝亚特丽斯的信仰之爱的状态。这就是但丁关于爱的理想,是他对自己灵魂进阶的要求,也是他为纷乱的人世间开出的药方。

延伸阅读 《月亮与六便士》 《千面英雄》 《荷马史诗》

仿生人的悲剧

外在环境的压力迫使人类文明趋向于创造出超越人类自身能力的造物,并把它们作为工具,而随着造物不断接近人类本体,双方必然产生无法调和的矛盾冲突。

仿生人悲剧的必然

人类必然需要为自己的造物上一层保险,限制它们的超级能力反过来危害人类,但同时这种限制成为检验人性善恶的一面镜子,将引起人类文明伦理道德基准的反思与动摇。

工具必然会接近并超越人类 vs 工具天然处于被支配地位 人类对工具严格限制
-> 矛盾造成悲剧

推论与现实对照

追求强大工具的客观现实必要性

这篇小说的设定里,作者采用了一个近未来后启示录背景,也就是《圣经》中启示录的末日预警之后。这种设定在科幻小说里很常见,巨大的灾难比如核战争,毁掉了地球,人类进入了极端残酷的生存环境。这样设定带来最重要的点,就是故事中的人类面临的生存压力非常大。在巨大的压力下,各种东西都会被推到极端,很多温情脉脉的面纱都会揭掉,露出最残忍的人性本性来。

我们可以对应地看一下现实,推动工具快速进步的主要是人类永远无法满足的欲望。地球人口有七十亿,2004 年的时候,地球生态报告警告人类消耗已经超出了地球负荷。光是维持人类的食物供应,农药,化肥,杂交育种,辐射育种,很多技术在争议中快速发展。如果停下来,我们可能就无法供养人类的生活。在这一点上,我们本质和小说中巨大的生存压力并无区别。

工具能力向人类逼近,直到超越人类

工具处于支配地位

所以必须严格限制出厂条件

必然产生矛盾

人类为何同情仿生人

约翰・罗尔斯在《正义论》里提出过一个重要的概念,叫 “无知之幕”。这个概念提出一种原则,来实现社会政策的正义公正。无知之幕的意思是,当选择社会政策的时候,每个选择的人都应该删除自己是什么身份地位出身的记忆,以 “无知” 的方式进行选择。比如选择应不应该保留黑人奴隶制度的时候,你不知道自己是黑人还是白人。选择买卖妇女是不是合法的时候,你不知道自己是男人还是女人。

这个无知之幕,立在一个基础上,就是 “我们” 拥有对等的能力和智慧,我们相信白人和黑人、男人和女人在幸福和痛苦上是平等的,一方感受到的东西,另一方也能感受到。所以我们能真切地 “同情” 到对方。你不能跟龙虾、跟带鱼一起披上无知之幕,因为你们在能力、智慧和感知上不可能平等。

但是当人类创造出来的工具越来越接近我们,在能力上越来越平等的时候,不管他们是 AI、机器人还是仿生人,我们总有一天能和他们一起披上无知之幕。当我们披上无知之幕,我们就能明白,我们对仿生人命运悲剧的同情,本质是希望避免自己有一天也遭遇同样的悲剧。

Q:为什么创造的工具外表要无限逼近人??