kur
Kur 是一款致力于让深度学习变得“可描述”的开源框架,旨在帮助用户无需编写复杂代码即可设计、训练和评估先进的 AI 模型。它主要解决了传统深度学习开发门槛高、需大量编程工作以及多后端适配繁琐的痛点,让用户能将精力集中在模型逻辑本身而非底层实现细节上。
无论是刚入门的机器学习新手,还是希望快速验证想法的资深研究人员,都能从 Kur 中受益。用户只需通过简洁易读的配置文件来描述模型结构,即可完成从构建到部署的全流程。对于需要更高灵活性的开发者,Kur 也提供了友好的扩展 API 以支持定制化需求。
在技术亮点方面,Kur 原生支持 Theano、TensorFlow 和 PyTorch 三大主流后端,并开箱即用多 GPU 加速功能,显著提升了训练效率。此外,它巧妙集成了 Jinja2 模板引擎,允许用户通过参数化配置快速探索和优化模型版本。未来,Kur 还计划推出社区模型共享功能,进一步促进协作创新。如果你希望以更直观、高效的方式涉足深度学习领域,Kur 提供了一个极具价值的选择。
使用场景
一家初创语音分析公司的算法团队,正急需为客服录音数据构建一个高精度的情感识别模型以快速验证商业价值。
没有 kur 时
- 开发门槛高:团队成员若不熟悉 TensorFlow 或 PyTorch 的底层 API,需花费数周学习如何编写复杂的神经网络代码。
- 迭代效率低:每次调整网络结构(如增加卷积层或改变激活函数)都需要修改大量 Python 脚本,容易引入语法错误且难以回溯。
- 多卡训练复杂:想要利用公司服务器的多块 GPU 加速训练,必须手动编写繁琐的分布式训练配置和同步逻辑。
- 协作困难:资深工程师编写的模型代码对新手而言如同“黑盒”,非代码背景的领域专家无法直接参与模型设计的讨论与优化。
使用 kur 后
- 零代码建模:团队仅需编写易读的 YAML 描述文件即可定义复杂的深度学习架构,完全无需触碰底层训练代码。
- 敏捷实验:借助 Jinja2 模板引擎,研究人员能快速生成并对比多种模型变体,将原本数天的结构调整工作缩短至几分钟。
- 开箱即用的多 GPU 支持:kur 原生支持多显卡并行训练,只需简单配置即可自动调度硬件资源,大幅缩短模型收敛时间。
- 全员协同创新:清晰的描述性配置文件让产品经理和领域专家也能理解模型结构,真正实现了跨角色的深度协作与模型共享。
kur 通过“描述即模型”的理念,将深度学习从昂贵的编码工程转变为高效的配置实验,极大降低了先进 AI 技术的应用门槛。
运行环境要求
- 未说明
- 支持多 GPU(multi-GPU),但非必需
- 具体显卡型号、显存大小及 CUDA 版本未在文中明确指定,仅提及可在普通消费级硬件(如 Intel Core m7 CPU)上运行示例
未说明

快速开始
.. |LICENSE| image:: https://img.shields.io/badge/license-Apache%202-blue.svg :target: https://github.com/deepgram/kur/blob/master/LICENSE .. |PYTHON| image:: https://img.shields.io/badge/python-3.4%2C3.5%2C3.6-lightgrey.svg :target: https://kur.deepgram.com/installing.html .. |BUILD| image:: https://travis-ci.org/deepgram/kur.svg?branch=master :target: https://travis-ci.org/deepgram/kur .. |GITTER| image:: https://badges.gitter.im/deepgram-kur/Lobby.svg :target: https://gitter.im/deepgram-kur/Lobby
.. _Facebook: https://www.facebook.com/sharer/sharer.php?u=https%3A//kur.deepgram.com .. _Google+: https://plus.google.com/share?url=https%3A//kur.deepgram.com .. _LinkedIn: https://www.linkedin.com/shareArticle?mini=true&url=https%3A//kur.deepgram.com&title=Kur%20-%20descriptive%20deep%20learning&summary=Kur%20is%20the%20future%20of%20deep%20learning%3A%20advanced%20AI%20without%20programming!&source= .. _Twitter: https://twitter.com/home?status=%40DeepgramAI%20has%20released%20the%20future%20of%20deep%20learning.%20https%3A//kur.deepgram.com%20%23Kur
.. image:: https://kur.deepgram.com/images/logo-small.png :align: center :target: https://deepgram.com
.. package_readme_starts_here
.. _Tutorial: https://kur.deepgram.com/tutorial.html
Kur:描述式深度学习
.. package_readme_ignore
|BUILD| |LICENSE| |PYTHON| |GITTER|
引言
欢迎使用 Kur!你已经找到了深度学习的未来!
- 通过
pip install kur轻松安装 Kur。 - 在无需编写任何代码的情况下设计、训练和评估模型。
- 使用易于理解的概念来描述你的模型。
- 利用强大的
Jinja2 <http://jinja.pocoo.org>_ 模板引擎,快速探索模型的改进版本。 - 支持 Theano、TensorFlow 和 PyTorch,并且开箱即用支持 多 GPU。
- 即将推出:与社区共享你的模型,使协作构建复杂模型变得极其容易。
赶快试一试吧:获取代码,然后进入 示例!接着在我们的教程_中构建你自己的模型。别忘了访问我们的 主页 <https://kur.deepgram.com>_,以获取完整的文档和最新资讯。
.. package_readme_ignore
喜欢我们吗?分享一下吧!
.. package_readme_ignore
- Facebook_
Google+_- LinkedIn_
- Twitter_
什么是 Kur?
Kur 是一个用于快速构建和应用最先进深度学习模型的系统,能够解决各种新颖而令人兴奋的问题。Kur 的设计旨在吸引整个机器学习社区,无论是初学者还是资深从业者。它使用简单易读且易于编写的配置文件,这意味着你可以开始构建复杂的模型,而无需编写任何代码。尽管如此,Kur 还提供了一个友好且可扩展的 API,以支持高级深度学习架构或工作流。心动了吗?直接跳到 示例_ 吧。
.. _get_the_code:
获取代码
Kur 的安装非常简单!你可以选择以下两种方式之一来安装 Kur。
注意:Kur 需要 Python 3.4 或更高版本。请参阅我们的 安装指南 <https://kur.deepgram.com/install.html>,其中包含安装 Kur 和设置 虚拟环境 <https://virtualenv.pypa.io/> 的分步说明。
最新 Pip 版本
如果你熟悉操作,那么这很简单:
.. code-block:: bash
pip install kur
最新开发版本
只需克隆仓库并运行安装脚本:
.. code-block:: bash
git clone https://github.com/deepgram/kur
cd kur
pip install .
快速入门:或者,如果你已经安装了 Python 3 <https://kur.deepgram.com/installing.html>_,那么只需几行命令即可开始训练你的第一个模型:
使用 pip 的快速入门:
.. code-block:: bash
pip install virtualenv # 确保已安装 virtualenv
virtualenv -p $(which python3) ~/kur-env # 创建一个用于 Kur 的 Python 3 环境
. ~/kur-env/bin/activate # 激活 Kur 环境
pip install kur # 安装 Kur
kur --version # 检查是否正常工作
git clone https://github.com/deepgram/kur # 获取示例
cd kur/examples # 进入示例目录
kur train mnist.yml # 开始训练!
使用 git 的快速入门:
.. code-block:: bash
pip install virtualenv # 确保已安装 virtualenv
virtualenv -p $(which python3) ~/kur-env # 创建一个用于 Kur 的 Python 3 环境
. ~/kur-env/bin/activate # 激活 Kur 环境
git clone https://github.com/deepgram/kur # 克隆最新代码
cd kur # 进入库目录
pip install . # 安装 Kur
kur --version # 检查是否正常工作
cd examples # 进入示例目录
kur train mnist.yml # 开始训练!
使用方法
如果一切顺利,你应该可以正常使用 Kur:
.. code-block:: bash
kur --version
通常你会使用类似 kur train model.yml 或 kur test model.yml 的命令。这些命令可以在 示例_ 中找到,这也是你接下来应该去的地方!
故障排除
如果你在安装或使用 Kur 时遇到任何问题,请查看我们的 故障排除页面 <https://kur.deepgram.com/troubleshooting.html>,那里有许多有用的帮助信息。如果你想获得更详细的安装说明,包括如何设置环境,请务必参考我们的 安装页面 <https://kur.deepgram.com/installing.html>。
.. package_readme_ends_here
.. _the_examples:
示例
让我们来看几个例子,了解 Kur 如何让最先进的深度学习变得既有趣又简单。
.. _mnist_example:
MNIST:手写数字识别
让我们直接上手,看看 Kur 有多强大!第一个例子是 Yann LeCun 的 MNIST <http://yann.lecun.com/exdb/mnist/>_ 数据集。这是一个包含 28x28 像素图像的数据集,每张图像代表 0 到 9 之间的单个手写数字。我们的目标是构建一个图像识别模型,为每张图像打上最可能的数字标签。
注意:与大多数命令行示例一样,以 $ 开头的行是你需要输入的命令(后接 ENTER 键)。没有 $ 的行则是屏幕上显示的内容,你不需要输入。
首先,你需要 获取代码_!如果你是通过 pip 安装的,那么你需要从仓库中检出 examples 目录,如下所示:
.. code-block:: bash
git clone https://github.com/deepgram/kur
cd kur/examples
如果你通过 git 安装了 Kur,那么你本地就已经有了 examples 目录,可以直接进入该目录:
.. code-block:: bash
$ cd examples
现在让我们来训练 MNIST 模型。这会直接从网上下载数据,然后开始训练 10 个 epoch。
.. code-block:: bash
$ kur train mnist.yml
Downloading: 100%|█████████████████████████████████| 9.91M/9.91M [03:44<00:00, 44.2Kbytes/s]
Downloading: 100%|█████████████████████████████████| 28.9K/28.9K [00:00<00:00, 66.1Kbytes/s]
Downloading: 100%|█████████████████████████████████| 1.65M/1.65M [00:31<00:00, 52.6Kbytes/s]
Downloading: 100%|█████████████████████████████████| 4.54K/4.54K [00:00<00:00, 19.8Kbytes/s]
Epoch 1/10, loss=1.524: 100%|███████████████████████| 480/480 [00:02<00:00, 254.97samples/s]
Validating, loss=0.829: 100%|█████████████████████| 3200/3200 [00:03<00:00, 889.91samples/s]
Epoch 2/10, loss=0.628: 100%|███████████████████████| 480/480 [00:02<00:00, 228.25samples/s]
Validating, loss=0.533: 100%|████████████████████| 3200/3200 [00:03<00:00, 1046.12samples/s]
Epoch 3/10, loss=0.547: 100%|███████████████████████| 480/480 [00:02<00:00, 185.77samples/s]
Validating, loss=0.491: 100%|████████████████████| 3200/3200 [00:03<00:00, 1030.57samples/s]
Epoch 4/10, loss=0.488: 100%|███████████████████████| 480/480 [00:02<00:00, 225.42samples/s]
Validating, loss=0.443: 100%|████████████████████| 3200/3200 [00:03<00:00, 1046.23samples/s]
Epoch 5/10, loss=0.464: 100%|███████████████████████| 480/480 [00:03<00:00, 115.17samples/s]
Validating, loss=0.403: 100%|█████████████████████| 3200/3200 [00:04<00:00, 799.46samples/s]
Epoch 6/10, loss=0.486: 100%|███████████████████████| 480/480 [00:03<00:00, 183.11samples/s]
Validating, loss=0.400: 100%|████████████████████| 3200/3200 [00:02<00:00, 1134.17samples/s]
Epoch 7/10, loss=0.369: 100%|███████████████████████| 480/480 [00:02<00:00, 214.10samples/s]
Validating, loss=0.366: 100%|█████████████████████| 3200/3200 [00:04<00:00, 735.61samples/s]
Epoch 8/10, loss=0.353: 100%|███████████████████████| 480/480 [00:03<00:00, 204.33samples/s]
Validating, loss=0.351: 100%|████████████████████| 3200/3200 [00:02<00:00, 1147.05samples/s]
Epoch 9/10, loss=0.399: 100%|███████████████████████| 480/480 [00:02<00:00, 219.17samples/s]
Validating, loss=0.343: 100%|████████████████████| 3200/3200 [00:02<00:00, 1149.07samples/s]
Epoch 10/10, loss=0.307: 100%|██████████████████████| 480/480 [00:02<00:00, 220.97samples/s]
Validating, loss=0.324: 100%|████████████████████| 3200/3200 [00:02<00:00, 1142.78samples/s]
刚才发生了什么?Kur 从 LeCun 的网站下载了 MNIST 数据集,然后训练了一个模型,共进行了十轮迭代。太棒了!
接下来我们来看看模型的实际表现如何:
.. code-block:: bash
$ kur evaluate mnist.yml
Evaluating: 100%|██████████████████████████████| 10000/10000 [00:06<00:00, 1537.74samples/s]
LABEL CORRECT TOTAL ACCURACY
0 969 980 98.9%
1 1118 1135 98.5%
2 910 1032 88.2%
3 926 1010 91.7%
4 923 982 94.0%
5 735 892 82.4%
6 871 958 90.9%
7 884 1028 86.0%
8 818 974 84.0%
9 868 1009 86.0%
ALL 9022 10000 90.2%
哇!我们的模型在识别手写数字方面已经达到了 90% 的准确率,而且只使用了 0.8% 的训练集!这就是 Kur 的强大之处。
是不是很兴奋?继续往下读吧!
注意:细心的读者会发现,每一轮训练只使用了 480 个样本。但 MNIST 总共有 60,000 个训练样本,这是怎么回事呢?很简单:我们中的许多人都是在消费级硬件上运行这段代码;事实上,我就是在一台搭载 Intel Core m7 CPU 的小型超极本上运行这个示例。正如你在 Under the Hood_ 中所看到的,我将训练过程截断为仅训练 10 个批次,每个批次 32 个样本,这样可以让训练循环在合理的时间内完成。这并不是作弊:你仍然可以获得 90% 的准确率!不过,如果你拥有强大的硬件,或者只是想看看你的模型能达到多高的准确率,那就请继续阅读,我们会教你如何进行调整。
Under the Hood
那么这里到底发生了什么呢?让我们来看看 MNIST 示例的配置文件:
.. code-block:: yaml
train:
data:
- mnist:
images:
url: "http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz"
labels:
url: "http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
include: mnist-defaults.yml
这只是一个普通的 YAML <http://yaml.org>_ 文件,这是一种旨在便于人类理解的标记语言(有关 YAML 语言特性的详细介绍,请参阅 Ansible 概述 <https://docs.ansible.com/ansible/YAMLSyntax.html>_)。
其中有一部分用于定义数据:
.. code-block:: yaml
train:
data:
- mnist:
images:
url: "http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz"
labels:
url: "http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"
然后还有一部分用于定义模型:
.. code-block:: yaml
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
此外还有一个 include 部分,包含了默认设置(高级用户可能会想要调整这些设置——不用担心,操作依然很简单):
.. code-block:: yaml
include: mnist-defaults.yml
非常简单!Kur 已经帮我们从 LeCun 的网站直接下载了数据,这一点很容易理解。那么一个 Kur 模型究竟包含哪些内容呢?其实就是一个清晰、简洁的列表,列出了你希望深度学习模型执行的操作。我们来逐条解析:
- 我们有一个名为
images的输入(没错,它与train部分中的images是同一个)。 - 将输入传递给一个卷积层。
- 添加一个修正线性单元(ReLU)激活函数。
- 将卷积层输出的高维特征图展平成一维向量,以便送入全连接层。
- 添加一个有 10 个输出的全连接层。
- 添加一个适合分类任务(如 MNIST)的 Softmax 激活函数,并将其标记为生成标签(
name: labels)。
就这么简单!虽然结构相当朴素——一次卷积 + 激活 + 全连接 + 激活——但它确实有效:我们只用了训练集的一小部分,就达到了 90% 的准确率。
但是,让我们试着让它变得更复杂一些。如果我们想要两个卷积层呢?很简单!只需在模型中再添加一个“卷积”部分即可。我们还将在两个卷积层之间加入另一个非线性激活函数(ReLU)。
.. code-block:: yaml
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
我们还可以添加更多的全连接层。你可能也希望这些层之间用激活层隔开。因此,如果我们在模型中加入一个包含32个节点的全连接层,那么现在的模型看起来就会是这样:
.. code-block:: yaml
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- flatten:
- dense: 32
- activation: relu
- dense: 10
- activation: softmax
name: labels
让我们试一试吧!保存你的更改,然后运行之前相同的 kur train mnist.yml 和 kur evaluate mnist.yml 命令。
注意:更复杂的模型通常需要更多的数据。因此,请务必查看 更高级的内容_ 中的提示,以使用更多数据集进行训练。
如果你想了解更多,Kur 所使用的 YAML 规范在我们的 使用 Kur <https://kur.deepgram.com/getting_started.html>_ 页面中有更详细的说明。
.. _more_advanced_things:
更高级的内容
在 mnist.yml 规范中,我们没有提到的一行是 include: mnist-defaults.yml。这只是我们用来将 MNIST 示例的默认行为分离出来的一种便捷方式。
如果你调整这个文件,可能最需要删除的是 num_batches: 10 这一行,它限制了每个 epoch 只训练前 10 个批次。只需删除这一行或将其注释掉,Kur 就会使用整个数据集进行训练。
更好的 MNIST
90% 已经相当不错了!但我们还能做得更好吗?当然可以!让我们来看看如何实现。
我们需要构建一个更具表现力、更深的模型。我们将使用更多的卷积层,并偶尔加入池化层。
.. code-block:: yaml
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- convolution:
kernels: 96
size: [3, 3]
- activation: relu
- pool: [3, 3]
- convolution:
kernels: 96
size: [3, 3]
- activation: relu
- flatten:
- dense: [64, 10]
- activation: softmax
name: labels
所以我们有三个卷积层,中间有一个 3x3 的池化层,以及两个全连接层。尝试训练这个模型:kur train mnist.yml。然后评估它的表现:kur eval mnist.yml。我们仅用训练集的 0.8% 就达到了超过 95% 的准确率。
如果我们给它更多的数据会怎样呢?正如我们 上面提到的__ 一样,可以通过调整 mnist-defaults.yml 文件中 train 部分的 num_batches 来改变 KUR 使用的数据量。让我们试试使用 5% 的数据集。为此,我们将设置 num_batches: 94(因为 60,000 的 5% 是 3,000,而默认的批次大小为 32,大约相当于 94 个批次)。现在再次尝试训练和评估。我们几乎达到了 98%!
__ more_advanced_things_
不要停下,让我们用全部数据进行训练(只需完全删除 num_batches 行,或将 num_batches 设置为 null)。仍然只训练 10 个 epoch,我们就达到了 98.6% 的准确率。太棒了!让我们与当前最先进的水平进行比较,Yann LeCun 在 MNIST 网站 <http://yann.lecun.com/exdb/mnist/>_ 上记录了最新的结果。看起来最佳的错误率同样使用了卷积网络,达到了 0.23% 的错误率(即 99.77% 的准确率)。仅仅通过几次调整,我们就已经比世界顶尖水平只差了一个百分点。Kur 真是太棒了!
.. _cifar_10:
CIFAR-10:图像分类
好吧,MNIST 确实很酷,但 Kur 能做的远不止这些。想象一下,你希望拥有任意数量的卷积层;或者每个卷积层都有不同数量的卷积核;又或者你真正需要 灵活性。那么你来对地方了。
灵活性:变量
Kur 使用一个 引擎 来处理变量替换。Jinja2 <http://jinja.pocoo.org>_ 是默认的模板引擎,功能非常强大且可扩展。让我们来看看如何使用它!
让我们来看一下 CIFAR-10 <https://www.cs.toronto.edu/~kriz/cifar.html>_ 数据集。这是一个小型 32x32 像素彩色(RGB)图像的分类数据集,每张图片属于十个类别之一(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车)。你可能会决定从一个与 MNIST 示例非常相似的模型开始:
.. code-block:: yaml
model:
- input: images
- convolution:
kernels: 64
size: [3, 3]
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
我们将从一个简单的修改开始:让卷积的 size 成为一个变量,这样我们以后就可以轻松地更改它。我们可以这样做:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
model:
- input: images
- convolution:
kernels: 64
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
那么刚才发生了什么?首先,我们添加了一个 settings: 部分。这部分是声明变量、设置和超参数的合适位置,这些内容将在模型中(或用于训练、评估等)被使用。我们声明了一个名为 cnn 的变量,其中嵌套了一个 size 变量。在 Python 中,这相当于一个字典:{"cnn": {"size": [3, 3]}}。
然后,我们在模型的卷积层中使用了这个变量:size: "{{ cnn.size }}"。这是标准的 Jinja2 语法。双括号表示需要进行变量替换(如果没有括号,我们就会错误地将 size 赋值为字符串 cnn.size,这显然没有意义)。我们获取的变量是 cnn.size,对应于我们在 settings 部分中添加的变量。
太棒了!现在我们可以使用变量了。但这对我们有什么帮助呢?似乎只是让事情变得更复杂了。不过,让我们想象一下,如果我们再添加一个卷积层会怎样。我们已经知道,只需再添加一个“卷积”块即可增加额外的卷积层(通常你还希望再加一个“activation: relu”层)。那么代码就会变成这样:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
model:
- input: images
- convolution:
kernels: 64
size: "{{ cnn.size }}"
- activation: relu
- convolution:
kernels: 64
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
啊!现在我们就能明白为什么将卷积核大小参数化是件好事了:如果我们 想要尝试使用不同大小卷积核的模型,只需要修改一行代码,而不是两行。
不过,我们仍然可能会遇到两个问题:
- 如果我们想尝试许多具有不同数量卷积层的模型呢?
- 如果我们希望在每个卷积层中使用 不同 的
size或kernel值呢?
Kur 可以做到!
灵活性:循环
让我们先解决第一个问题:如果我们想让卷积层数量可变怎么办?Kur 支持
许多被称为“算子”的“元层”。一个非常简单的算子就是经典的 "for" 循环 <https://en.wikipedia.org/wiki/For_loop>_。这使我们可以一次性添加
多个卷积层和激活层。代码如下所示:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
model:
- input: images
- for:
range: 2
iterate:
- convolution:
kernels: 64
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
这与没有 "for" 循环的版本是等价的。for: 循环告诉我们需要在
iterate: 部分重复执行两次。(为什么是两次?因为 range: 2。)
当然,我们也可以这样对迭代次数进行参数化:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
kernels: [64, 32]
layers: 2
model:
- input: images
- for:
range: "{{ cnn.layers }}"
iterate:
- convolution:
kernels: 64
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
请仔细思考一下。这是否合理?应该是合理的。该模型看起来如下:
- 一个输入图像的层。
- 若干个卷积层和激活层。有多少个呢?由
cnn.layers决定,这里是 2 个。 - 模型的其余部分按预期进行:先是一个全连接层,然后是一个激活层。
灵活性:可变长度的循环
现在我们已经解决了允许卷积层数量可变的问题。但如果每个卷积层应该
使用不同数量的卷积核(或不同的尺寸等)呢?嗯,Kur 同样可以轻松处理
这一点。事实上,for: 循环已经完成了大部分工作。每个 for: 循
环都会创建一个自己的“局部”变量,用来告诉你当前处于第几次迭代。这个
变量的默认名称是 index。因此,如果我们要为每个卷积层使用不同数
量的卷积核,可以这样做:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
kernels: [64, 32]
layers: 2
model:
- input: images
- for:
range: "{{ cnn.layers }}"
iterate:
- convolution:
kernels: "{{ cnn.kernels[index] }}"
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
再次强调,这只是 Jinja2 替换:我们请求的是 cnn.kernels 列表中的
第 index 个元素。因此,for: 循环的每次迭代都会获取不同的
kernels: 值。很酷,不是吗?
但我们可以做得更好。
灵活性:过滤器
我们当前模型的一个麻烦之处在于,没有任何机制强制要求 layers
的值必须等于 kernels 变量的长度。如果你把 kernels 设置得非常
长(比如长度为十七),却把 layers 保持为二,那很可能就是你犯了
错误。(你为什么要设置十七个卷积层,却只在循环中使用前两个呢?)你
真正想要的是确保 layers 的值等于 kernels 列表的长度。换句话说,
你希望添加的卷积层数量正好等于列表中卷积核的数量。
Jinja2 支持一种称为“过滤器”的概念,它本质上是可以应用于对象的函数。 你甚至可以定义自己的过滤器。但我们现在需要的是获取列表长度的方法。 这很简单,代码如下:
.. code-block:: yaml
settings:
cnn:
size: [3, 3]
kernels: [64, 32]
model:
- input: images
- for:
range: "{{ cnn.kernels|length }}"
iterate:
- convolution:
kernels: "{{ cnn.kernels[index] }}"
size: "{{ cnn.size }}"
- activation: relu
- flatten:
- dense: 10
- activation: softmax
name: labels
你会注意到,layers 变量已经消失了,取而代之的是在 for 循环的
range 中出现了这个奇怪的 |length。这是标准的 Jinja2 语法:
length 过滤器会返回列表的长度。因此,我们现在要求 for 循环
迭代的次数正好等于卷积核列表的长度。
仔细想想,这真的很酷。你想在网络中添加另一个卷积层吗?你只需要将其
尺寸添加到 kernels 列表中即可。 看吧!你的模型现在变得更加通用、
更加可重用。你本来可以用同样的模型来处理 MNIST 数据集!或者 CIFAR!
又或者许多其他应用。
这就是 Kur 理念的核心:你应该用一次且简单的方式描述你的模型。 规范 描述 你的模型:一堆卷积层,然后是一个全连接层。你可以将细节(例如 卷积层数量、参数等)放在别处指定。模型本身应保持简洁优雅。
注意:当然,编写可重用的模型并不总是容易的。学习曲线也可能成为 障碍。当我们说模型应该“简单”时,我们并不是指不需要动脑筋。而是说它 应该易于使用、易于修改以及易于共享。更通用的模型往往更加优雅:对其 进行更改很容易(只需修改设置即可)。这也使得它更容易在新的场景中复 用,或者与社区分享。简单就是力量。
训练 CIFAR-10 模型的实际操作
太好了,我们现在有了一个简单但功能强大且通用的模型。让我们来训练它。
和之前一样,你需要先切换到 examples 目录。
.. code-block:: bash
kur train cifar.yml
同样地,评估也非常简单:
.. code-block:: bash
kur evaluate cifar.yml
高级特性
cifar.yml 规范文件比 MNIST 的要复杂一些,主要是为了让你接触到更多
可以调整的参数。例如,在 train 部分你会看到以下几行:
.. code-block:: yaml
provider:
batch_size: 32
num_batches: 2
与 MNIST 情况类似,num_batches 告诉 Kur 每个 epoch 只训练这么多批
数据(主要是为了避免在没有高性能 GPU 的情况下,示例运行时间过长)。
而 batch_size 则表示每批次用于训练的样本数量。
.. _using_binary_logger:
train 部分还包含一行 log: cifar-log。这会指示 Kur 将日志文件保存到当前工作目录下的 cifar-log。该日志包含了关于当前训练损失、批次损失以及轮次数等大量有用信息。默认情况下,这些日志文件是二进制编码的,但你可以使用 Kur 的 API(在 Python 3 中)来加载它们:
.. code-block:: python
from kur.loggers import BinaryLogger
data = BinaryLogger.load_column(LOG_PATH, STATISTIC)
其中 LOG_PATH 是日志文件的路径(例如 cifar-log),而 STATISTIC 是所记录的统计量之一。data 将是一个 Numpy <http://www.numpy.org/>_ 数组。要查看可用的统计量,只需列出 LOG_PATH 目录下的文件,如下所示:
.. code-block:: bash
$ ls cifar-log
training_loss_labels
training_loss_total
validation_loss_labels
validation_loss_total
有关如何使用这些日志数据的示例,请参阅我们的教程_。
与 MNIST 示例相比,CIFAR 规范中引用权重的文件更多。例如,在 validate 部分有:
.. code-block:: yaml
weights: cifar.best.valid.w
这会指示 Kur 将最佳模型权重(对应于 验证集 上最低损失的权重)保存到 cifar.best.valid.w。类似地,在 train 部分也有以下内容:
.. code-block:: yaml
weights:
initial: cifar.best.valid.w
save_best: cifar.best.train.w
last: cifar.last.w
initial 键指示 Kur 在训练开始时尝试加载 cifar.best.valid.w(即以 验证集 损失为准的最佳权重)。如果该文件不存在,则不会执行任何操作。这意味着如果你多次运行训练循环(多次调用 kur train cifar.yml),你始终会从最佳模型权重处“重启”。
我们还将以 训练集 损失为准的最佳权重保存到 cifar.best.train.w,而最新的权重则保存到 cifar.last.w。
注意:权重文件与模型架构密切相关。假设你训练了 CIFAR 并生成了 cifar.best.valid.w,随后你在配置文件中对模型进行了调整。如果你尝试继续训练(kur train cifar.yml),Kur 会尝试加载 cifar.best.valid.w,但这些权重可能并不适用于新的架构!因此,为安全起见,在训练全新的、经过调整的模型之前,务必删除(或备份)你的权重文件。在生产环境中,建议为每个不同的模型变体或调整创建单独的子目录,以避免此类问题。
CIFAR-10 示例还在 train 部分显式指定了优化器:
.. code-block:: yaml
optimizer:
name: adam
learning_rate: 0.001
优化器函数通过 name 字段指定,其他参数(如 learning_rate)则在其他字段中定义。你可以安全地更改优化器,而不会破坏与旧版权重文件的向后兼容性。
常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器
LLMs-from-scratch
LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目,旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型(LLM)。它不仅是同名技术著作的官方代码库,更提供了一套完整的实践方案,涵盖模型开发、预训练及微调的全过程。 该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型,却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码,用户能够透彻掌握 Transformer 架构、注意力机制等关键原理,从而真正理解大模型是如何“思考”的。此外,项目还包含了加载大型预训练权重进行微调的代码,帮助用户将理论知识延伸至实际应用。 LLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API,而是渴望探究模型构建细节的技术人员而言,这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计:将复杂的系统工程拆解为清晰的步骤,配合详细的图表与示例,让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础,还是为未来研发更大规模的模型做准备