Downloads · 30 days
77
8% of all-time downloads
jingyaogong/minimind-3v
minimind-3v is a image-text-to-text model from jingyaogong. Use it for the image-text-to-text task on the model card, and read the license before you ship it in a product. The card lists the license as apache-2.0.
Downloads · 30 days
77
8% of all-time downloads
All-time downloads
949
Public
Repo size
409 MB
Likes
2
Public
Click a slice to open those files.
.bin130 MB · 94%
From the Hugging Face model README

中文 | English
</div><div align="center">注:本项目基于 Apache 2.0 协议开源,完全免费。“2 小时” 指 SFT 阶段在单张 NVIDIA 3090 上跑完
1 epoch的实测耗时,“3 块钱” 指对应时段的 GPU 租用成本。

“用乐高拼出一架飞机,远比坐在头等舱里飞行更让人兴奋!” 构建VLM范式的多模态大模型是否真的如想象中那样复杂?它的代码实现到底如何? 训练过程究竟难不难?那么现在,探索它们的答案,一起感受创造的乐趣吧!
[!TIP] (截至2026-04-20)MiniMind-V 系列已完成了以下型号模型训练,最小仅需65M (0.065B),即可具备识图和对话的能力!
| 模型 (大小) | release |
|---|---|
| minimind-3v-moe (200M-A65M) | 2026.04.20 |
| minimind-3v (65M) | 2026.04.20 |
| MiniMind2-V (104M) | 2025.02.20 |
| MiniMind2-Small-V (26M) | 2025.02.20 |
| minimind-v-v1-small (27M) | 2024.10.04 |
| minimind-v-v1 (109M) | 2024.10.04 |
LayerNorm,去掉 reshape token 合并(P32 原生 64 token,无需下采样)SiglipVisionModel(P32,固定 256×256)freeze_llm=1 解冻首末两层,Pretrain/SFT 默认改为 2/1;max_seq_len 360 → 450<|image_pad|>、新增WebUI:支持动态扫描模型目录、下拉菜单切换模型2025-04-27
2025-02-20
2024-10-05
# 克隆代码仓库
git clone --depth 1 https://github.com/jingyaogong/minimind-v
# 下载siglip2模型到 ./model 目录下
git clone https://huggingface.co/jingyaogong/siglip2-base-p32-256-ve
# 或
git clone https://modelscope.cn/models/gongjy/siglip2-base-p32-256-ve
# 下载minimind语言模型权重到 ./out 目录下(作为训练VLM的基座语言模型)
# HuggingFace
https://huggingface.co/jingyaogong/minimind-3v-pytorch/blob/main/llm_768.pth
# 国内源
https://modelscope.cn/models/gongjy/minimind-3v-pytorch/resolve/master/llm_768.pth
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
git clone https://huggingface.co/jingyaogong/minimind-3v
# load_from='model': 加载原生PyTorch权重, load_from='其他路径': 加载transformers格式
python eval_vlm.py --load_from model --weight sft_vlm
# 或使用transformers格式模型
python eval_vlm.py --load_from minimind-3v
# ⚠️ 须先将 transformers 格式模型文件夹复制到 ./scripts/ 目录下(例如:cp -r minimind-3v ./scripts/minimind-3v),web_demo_vlm 脚本会自动扫描该目录下包含权重文件的子文件夹,如不存在则报错
cd scripts && python web_demo_vlm.py
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
<details>
<summary>注:提前测试Torch是否可用cuda</summary>
import torch
print(torch.cuda.is_available())
如果不可用,请自行去torch_stable 下载whl文件安装。参考链接
</details>从下文提供的数据集链接
下载所需内容并放到./dataset下。
【注1】之前需解压50万零碎的图像文件可能非常慢。2025-12-27起,数据集格式统一为Parquet,图文一体化存储,体积更小,无需解压,加载更快。
【注2】Parquet是列式存储格式,支持高效压缩和快速读取。如果你对它感到陌生,可以预览数据内容,在dataset/目录下执行python lm_dataset.py可视化前5条图文对
Pretrain 数据(可选;仅包含 caption 子集):
wget https://hf-mirror.com/datasets/jingyaogong/minimind-v_dataset/resolve/main/pretrain_i2t.parquet
SFT 数据(必须;包含 caption + instruct + 纯文本全量合并):
wget https://hf-mirror.com/datasets/jingyaogong/minimind-v_dataset/resolve/main/sft_i2t.parquet
SFT 单文件 290 万条已把 Pretrain 作为子集合并,经全局 dictionary encoding 去重后体积只比 SFT 原版多 ~10%,可覆盖所有训练阶段。
</details>3.1 Pretrain(可选)
SFT 数据集
sft_i2t.parquet已把 Pretrain 数据作为子集合并进来,此阶段可跳过,直接--from_weight llm进入 SFT 即可;若想让 Projector 提前完成对齐、SFT 收敛更稳,可以提前执行 Pretrain。
# 基础训练命令(从LLM权重开始,仅训练 vision_proj)
python train_pretrain_vlm.py --epochs 2 --from_weight llm
执行 Pretrain,得到
pretrain_vlm_*.pth作为 Pretrain 的输出权重(其中*为模型的dimension,默认为768)
3.2 SFT(必须)
# 基础训练命令(默认 --freeze_llm 1:解冻 proj + LLM 首尾层,保留中间层原 LLM 知识)
# 若已执行 3.1:--from_weight pretrain_vlm;若跳过 Pretrain:--from_weight llm
python train_sft_vlm.py --epochs 2 --from_weight pretrain_vlm
<details> <summary>注:训练须知</summary>执行 SFT,得到
sft_vlm_*.pth作为 SFT 的输出权重
训练特性:
--from_resume 1参数可从上次中断处继续训练out/**.pth(模型权重)和checkpoints/**_resume.pth(训练状态)文件# 训练中断后,使用相同命令并添加 --from_resume 1
python train_sft_vlm.py --epochs 4 --from_resume 1
参数说明:
--from_weight: 基础权重名称(llm, pretrain_vlm, none等)--save_weight: 保存权重的前缀名--from_resume: 是否续训(0=从头开始,1=从检查点继续)--freeze_llm: 冻结策略(0=全参可训,1=proj + LLM 首尾层,2=仅训 proj)。Pretrain 默认 2,SFT 默认 1确保需要测试的模型*.pth文件位于./out/目录下。
也可以直接去此处下载使用我训练的*.pth文件。
# 测试SFT模型(默认)
python eval_vlm.py --weight sft_vlm
# 测试Pretrain模型
python eval_vlm.py --weight pretrain_vlm
[!TIP] 训练脚本均为 PyTorch 原生框架,均支持多卡加速,假设你的设备有N (N>1) 张显卡:
单机N卡启动训练方式 (DDP, 支持多机多卡集群)
torchrun --nproc_per_node N train_xxx.py
<details>
<summary>注:其它须知</summary>
<del>
单机N卡启动训练 (DeepSpeed)
deepspeed --master_port 29500 --num_gpus=N train_xxx.py
</del>
可根据需要开启wandb记录训练过程
# 需要登录: wandb login
torchrun --nproc_per_node N train_xxx.py --use_wandb
# and
python train_xxx.py --use_wandb
通过添加--use_wandb参数,可以记录训练过程,训练完成后,可以在wandb网站上查看训练过程。通过修改wandb_project
和wandb_run_name参数,可以指定项目名称和运行名称。
【注】:25年6月后,国内网络环境无法直连WandB,MiniMind项目默认转为使用SwanLab作为训练可视化工具(完全兼容WandB API),即import wandb改为import swanlab as wandb即可,其他均无需改动。
MiniMind-V 的语言主干即孪生项目 minimind 训练得到的 llm_768.pth,LLM 本身的结构、训练细节与实验分析不在本仓库重复,默认读者对 MiniMind LLM 已有基本了解。未接触过也不影响照着“快速开始”跑通 MiniMind-V,流程自洽。
顶部 “从 0 训练” 和 “65M” 两个简化口号在这里也需要说明。“从 0 训练” 指 VLM 本身从零构建(Projection 随机初始化、LLM 首末层微调对齐),但 LLM 主干并非从零 pretrain,而是基于 MiniMind 的语言模型权重续训而来;若要严格意义上的 “完全从零 pretrain”,请先在 MiniMind 训一版 LLM 再迁回本项目。“65M” 指可训练部分的主干规模(LLM ~64M + Projection ~1M);视觉编码器 SigLIP2 另有 ~95M 参数全程冻结、仅作图像特征提取,因此推理时整机参数量约 160M(dense)/ 294M(MoE)。
VLM 在 LLM 基础上增加 Visual Encoder 和特征投影两个子模块,引入模态混合分支以支持多模态输入:

此处不妨展开想一想两个问题:
这篇文章完美吻合本人的想法: 大语言模型(LLM)名字虽然带有语言二字,但它们其实与语言关系不大,这只是历史问题,更确切的名字应该是自回归 Transformer 或者其他。LLM 更多是一种统计建模的通用技术,它们主要通过自回归 Transformer 来模拟 token 流,而这些 token 可以代表文本、图片、音频、动作选择、甚至是分子等任何东西。 因此,只要能将问题转化为模拟一系列离散 token 的流程,理论上都可以应用 LLM 来解决。 实际上,随着大型语言模型技术栈的日益成熟,我们可能会看到越来越多的问题被纳入这种建模范式。也就是说,问题固定在使用 LLM 进行『下一个 token 的预测』,只是每个领域中 token 的用途和含义有所不同。
ZJU-LiXi老师同样谈及过类似观点(原话大意如下):
文本、视频、语音、动作等在人类看来属于「多模态」信号,但所谓的「模态」其实只是人类在信息存储方式上的一种分类概念。
就像.txt和.png文件,虽然在视觉呈现和高级表现形式上有所不同,但它们本质上并没有根本区别。
之所以出现「多模态」这个概念,仅仅是因为人类在不同的感知层面上对这些信号的分类需求。
然而,对于机器来说,无论信号来自何种「模态」,最终它们都只是以一串二进制的「单模态」数字序列来呈现。
机器并不会区分这些信号的模态来源,而只是处理和分析这些序列背后所承载的信息内容。
个人认为Generative Pretrained Transformer (GPT) 比 Large Language Model (LLM)更为贴切, 因此本人表达上更习惯用"GPT"去代表LLM/VLM/类GPT架构的系列模型,而非为了蹭OpenAI的热度。
至此,我们可以用一句话总结GPT的所作所为:
GPT模型根据现有token预测输出下一个下下一个下下下一个token ...,直到模型输出结束符;此处的"token"其实并不需要一定是文本!
> 对于LLM模型,如果需要理解"图片",我们只要把"图片"作为对一种特殊的从来没见过的"外国语言",通过"外语词典"翻译后即可作为特殊的语言输入LLM
> 对于LLM模型,如果需要理解"音频",我们只要把"音频"作为对一种特殊的从来没见过的"外国语言",通过"外语词典"翻译后即可作为特殊的语言输入LLM
> ...
<u>为了得到MiniMind-V,我们只需要完成这2件事即可:</u>
"外语词典" 称之为Visual Encoder模型。 和LlaVA、Qwen-VL等视觉语言模型类似,MiniMind-V当前选用开源SigLIP2系列模型作为Visual Encoder。 具体使用siglip2-base-p32-256-ve, 一种基于 ViT-B/32 架构的Visual Encoder用于描述图像文本信息。 当前使用的 SigLIP2 NaFlex 视觉编码器会根据预处理结果生成 64 个 patch token(256×256 图像 / patch_size 32 = 8×8 = 64)作为 encoder 编码层的输入, 最终产生1×768维的嵌入向量用于和文本对计算误差。 我们并不需要最终嵌入表示,因此只取encoder层的输出,也就是VIT核心主干的输出特征即可。 它拿到前一层 64×768 大小的特征,经过 LayerNorm + 2 层 MLP(Linear→GELU→Linear)投影到 LLM 的隐藏维度,最终作为 64 个 visual token 输入 MiniMind-V——这一步完成的就是跨模态特征对齐:让原生视觉特征进入文本 token 所在的语义空间,使两者可以在同一空间里交互。
LlaVA-1使用简单的线性变换完成对齐,LlaVA-1.5升级为2层MLP,MiniMind-V采用与LlaVA-1.5相同的MLP Projection方案(P32 原生输出 64 token,无需额外 reshape 压缩)。

MiniMind-V的主要结构已介绍完毕。
</details>下面,我们简单讨论MiniMind-V的外部输入输出的变化。
VLM的输入依然是一段文本,其中包含特殊的<image>占位符。
在计算文本嵌入后,可以将图像编码器生成的向量投影到该占位符对应的嵌入部分,替换掉原先的占位符embedding。
例如:
<image>\n这个图像中有什么内容?
在minimind-v中,使用64个<|image_pad|>组成的占位符代替图像(SigLIP2 P32 直接输出 64 个 patch token,经 MLP 投影为 64 个 visual token),因此minimind-v的prompt为:
<|image_pad|><|image_pad|>...<|image_pad|>(×64)\n这个图片描述的是什么内容?
计算完embedding和projection,用视觉特征替换掉对应占位符的embedding后,整个计算过程到输出则和LLM部分没有差异。

至此,MiniMind-V的所有细节呈现完毕,VLM模型子类继承自MiniMind,仅做最小变更而产生,核心算法改动< 50行,迁移难度极低,和LlaVA等模型具体实现存在区别,但思路一致。
本轮训练用到的图文数据全部来自 ALLaVA-4V 系列。 相比以往从几份 LLaVA 衍生集拼接得到的数据,ALLaVA-4V 的质量更整齐、中英双语原生对照,细粒度描述也更充分。 它由两个子源构成:一份是 LAION 里挑出来的高质量图片(自然图像为主),一份是 VFLAN 指令流里挑出来的图片(文档、图表、合成场景居多)。
Pretrain(pretrain_i2t.parquet,约 127 万条 / ~64 万张唯一图像)
ALLaVA-Caption-LAION-4V 英/中:~47万 + ~44万ALLaVA-Caption-VFLAN-4V 英/中:~19万 + ~17万SFT(sft_i2t.parquet,约 290 万条 / ~65 万张唯一图像)
ALLaVA-Instruct-LAION-4V 英/中:~47万 + ~47万ALLaVA-Instruct-VFLAN-4V 英/中:~19万 + ~17万Instruct-LAION-4v-gemini-claude-ensembled(Gemini/Claude 合成的增广指令):~5万Instruct-LAION-4oiterative(基于 GPT-4o 迭代润色的指令):~5万合计约 290 万条样本,Pretrain 阶段可直接跳过(SFT 已把 Pretrain 作为子集吸收)。中英比例大致均衡。 考虑到 MiniMind-V 的语言主干仅 65M,把英文和中文一起喂进去是比较稳妥的做法——中文语料对母语输出更友好,而英文原生描述通常更精细,两者互为补充。
图像统一 resize 到 256×256(与 SigLIP2 NaFlex 编码器的输入规格相对应,P32 产生 64 个 patch token),重新编码为 JPEG 打包进 parquet。
(pretrain_i2t.parquet) Pretrain 数据集格式:
列名: conversations (json string), image_bytes (binary)
conversations 示例:
[
{"role": "user", "content": "<image>\n请提供对图片的详细文字描述。"},
{"role": "assistant", "content": "这张图片展示的是一个..."}
]
image_bytes: <图像二进制数据>
(sft_i2t.parquet) 单图 SFT 数据集格式:
列名: conversations (json string), image_bytes (binary)
conversations 示例:
[
{"role": "user", "content": "根据图片推断这个场景的大致时间?<image>"},
{"role": "assistant", "content": "从光线和阴影来看..."}
]
image_bytes: <图像二进制数据>
注:sft_i2t.parquet 共约 290 万条数据,其中约 140 万条为图像 instruct 对话、约 127 万条为图像 caption 描述(Pretrain 数据合并而来)、约 23 万条为纯文本对话(t2t,图像列填 8×8 黑图占位,用于保持模型的基础语言能力)。由于 Pretrain 已作为子集并入,可选择跳过 Pretrain 阶段直接进行 SFT。
数据集下载地址:(ModelScope | HuggingFace)
训练分为两个阶段(Pretrain 可选;SFT 必需),均冻结 Visual Encoder 梯度,仅训练 Projection 和部分 LLM 层。 训练基于 LLM Pretrain 权重初始化,支持 DDP 多卡训练、混合精度(bfloat16)、torch.compile 加速和 swanlab 日志记录。
train_pretrain_vlm(可选)
Pretrain 阶段从约 127 万条图文描述数据中学习图片的通用知识(如鹿是鹿,狗是狗)。
此阶段采用较高学习率(~4e-4),最大序列长度 450,完全冻结 LLM 和 Visual Encoder,仅训练 Projection(--freeze_llm 2)。
目的是让 Projector 干净地完成视觉 token 到语言 token 的基础对齐,不扰动 LLM 原有权重。
由于 SFT 阶段数据已把 Pretrain 全部样本包含为子集,此步骤可选,跳过可节省时间,但先跑一轮 Pretrain 让 Projector 先行对齐,SFT 收敛更稳。
train_sft_vlm
SFT 阶段的数据即前述 sft_i2t.parquet,约 290 万条混合样本,涵盖 Pretrain 继承而来的图文 caption、自然图像上的推理问答、文档/图表的细节问答、Gemini/Claude/GPT-4o 合成的指令,以及约 23 万条纯文本对话(图像列填 8×8 黑图占位)。学习率降到 ~5e-6,最大序列 768。
常见做法是在 SFT 阶段把 LLM 全参解冻,但这通常建立在底座有几 B 参数、且 SFT 数据中混入大量纯文本这两个前提之上。MiniMind-V 的语言主干仅 64M,而当前 SFT 数据中 ~92% 与图像有关,若全参解冻,LLM 原有的通用语言能力极易被图文任务的梯度稀释。
这里采用 --freeze_llm 1:只解冻 Projection 与 LLM 的首、末层,其余 N-2 层保持 Pretrain 时的权重。首层是视觉 token 进入 LLM 后的第一道处理,直接承担跨模态融合;末层影响回答的格式与风格;中间层保留 LLM Pretrain 的知识,不被图文任务的梯度改写。那 23 万条纯文本样本对通用语言能力也起到类似正则的作用。
训练时间和 Loss 走势(仅供参考)
单张 NVIDIA 3090 上,SFT 跑完 1 epoch 实测约 2 小时,dense 与 MoE 用时接近(激活参数规模一致,差异主要来自 expert routing 的额外访存);Pretrain 数据量约为 SFT 的 45%,单 epoch 耗时按比例粗估即可。按云上 3090 约 1.5 元/小时的行情,SFT 单轮成本落在 3 元上下。
Pretrain [768+8] (dense & moe)

SFT [768+8] (dense & moe)

| 模型格式 | ModelScope | HuggingFace |
|---|---|---|
原生PyTorch (*.pth) | minimind-3v-pytorch | minimind-3v-pytorch |
| Transformers 格式 | minimind-v collection | minimind-v collection |
注:Transformers版本均为单图 SFT 后的
MiniMind-V模型
Prompt: <image>\n请描述这张图中的主要物体和场景。
两个模型在 6 张样本上均能正确识别主体对象(狗、雨伞、自行车、跑车、超级英雄、赛车),主体识别率均为 6/6,但仍伴随部分重复表述与细节幻觉,整体处于"能看懂大意、细节不够精准"的阶段。
MoE 版本的场景描述更丰富,对背景环境(城市街道、城市天际线、日落渐变色)和物体细节(彩虹色图案、蓝红服装配色、赛车车身标识)的捕捉优于 Dense。Dense 版本在表达简洁性上占优,重复表述更少。两者的幻觉程度接近,均会在局部细节上出现不准确的描述。
视觉信号对 LLM 而言相当于一门特殊的"外语","学外语"的上限因此受制于 LLM 自身的语言能力。底座越强,同样的图文数据喂进去收益越大;把 MiniMind-V 的主干换成几 B 量级的 LLM,细节准确度与推理连贯性的提升会相当明显。
> 可引入动态分辨率和Tile-based编码(如LLaVA-NeXT),突破固定分辨率限制。
> Visual Encoder可升级为更强的视觉编码器,获取更细粒度的图像特征。
> 拓展多图理解、视频理解和视觉定位(Visual Grounding)能力。
> ...
[!TIP] 如果您觉得
MiniMind-V对您有所帮助,可以在 GitHub 上加一个⭐<br/> 水平有限难免存在未知的纰漏,欢迎所有人在Issues交流指正或提交PR改进项目<br/> 您的支持就是持续改进项目的动力,谢谢!
<a href="https://github.com/xinyanghuang7"><b>@xinyanghuang7</b></a>: <a href="https://github.com/xinyanghuang7/minimind-v/tree/hxy">多图vlm分支</a> | <a href="https://github.com/jingyaogong/minimind-v/tree/32cf4c5c01337231fd907b92d513de8945594263">仓库截至此版本提供</a>
<details> <summary> <b>参考链接 & 感谢以下优秀的论文或项目</b> </summary>如果您觉得 MiniMind-V 对您的研究或工作有所帮助,请引用:
@misc{minimind-v,
title = {MiniMind-V: Train a Tiny VLM from Scratch},
author = {Jingyao Gong},
year = {2024},
url = {https://github.com/jingyaogong/minimind-v},
note = {GitHub repository, accessed 2026}
}
本仓库遵循 Apache-2.0 License 开源协议。