
简介面向零基础 AI 学习者的 DeepSeek 本地模型训练完整操作指南以 PDF 文档形式梳理从环境部署到微调的全流程。内容围绕 Ollama 本地部署 DeepSeek、纯文本训练数据准备、Python 环境搭建及 torch/transformers/datasets 三大依赖库安装展开并配有基于 VSCode 等编辑器的代码示例与目录结构说明适合只会 JavaScript 或略懂 PHP/Python 的入门读者逐步实践。资源共 1 个文件为 PDF 格式压缩包整体约 1.93MB轻松下载即可对照学习。目前已有 269 人学习使用。文档特别强调了训练过程中的关键细节包括模型文件存放路径、Add Python to PATH 勾选、安装耗时耐心等待、验证依赖库安装结果等并给出 fine_tune_deepseek 目录下 fine_tune.py 的完整加载与预处理代码可为初学者避开常见踩坑点快速建立本地模型训练的基础认知。1. 给 deepseek-r1:1.5b 做本地微调这事到底能不能成很多人拿到 Ollama 部署好的 DeepSeek第一反应就是“我能不能拿自己的 txt 教它说人话”。这篇笔记就是干这个的在已经用 Ollama 装好 deepseek-r1:1.5b 的前提下用 transformers 这套标准工具链对本地模型做一次真正的参数微调。先说结论能跑通但有几个前提——你的模型得是 PyTorch 格式而不是 Ollama 的 GGUF 量化格式你的 txt 数据量不能太少你的显卡显存最好别低于 6G。这条链路适合 JavaScript 出身、Python 只懂一点点的初学者全程跟着命令走大概率能见到“Generated Text”那行输出。但如果你是奔着“让 DeepSeek 变成我的专属客服”来的建议先看完第 5 章再决定要不要动这个工程。2. 前置环境Ollama 部署与 Python 三件套的安装边界2.1 Ollama 装模型路径不对后面全白搭先确认你已经走完了 Ollama 的本地部署流程。在 C:\ 盘装 Ollama然后用 cmd 跑ollama run deepseek-r1:1.5b模型文件会落在D:\ollama\models下。这套流程本身没有坑但有一个容易忽略的点Ollama 默认把模型存成 GGUF 量化格式而这份笔记里要用AutoModelForCausalLM.from_pretrained()加载的是 Hugging Face 格式的 PyTorch 模型。如果你在加载时报错“认不出这种格式”别慌这不是你环境坏了是格式不匹配。常见做法是再去 Hugging Face 把原版 deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B 下载下来放到D:\ollama\models\deepseek-r1-hf这种目录里。命令很好记ollama run deepseek-r1:1.5b这条命令拉下来的是 Ollama 专用权重。确认模型文件存在的方式是看目录大小一般 1.5B 模型量化后大约 1.1GB 左右。如果这个目录是空的说明模型还没拉完重新执行一次即可。2.2 安装 Python 与依赖慢是正常的看进度条就好Python 的安装没什么好说的官网下载最新 3.10 或 3.11安装时务必勾选 “Add Python to PATH”。这一步如果你漏了后面python fine_tune.py会直接提示“不是内部或外部命令”。勾上之后新开的 cmd 窗口里输入python --version能正常返回版本号才算数。三件套的安装是第一个耐心考验命令很简单但下载体量不小pip install torch transformers datasets逻辑说明torch 是 PyTorch 深度学习框架负责模型的张量计算和反向传播transformers 是 Hugging Face 的模型库提供加载、微调、推理的封装datasets 用于管理和加载训练数据。三者的组合是 NLP 微调的标准配方。参数说明这条命令会拉取 CPU 版或 CUDA 版 torch。如果是 CUDA 版下载体积可能到 200MB 以上速度 20KB/s 时等两小时很正常。安装时注意看终端里最后两行一行是“Successfully installed”一行是长长的包名列表。装完最好用pip list确认一下版本避免后面 import 报错。2.3 编辑器选型新手别折腾VSCode 够用VSCode、PyCharm、Jupyter 都可以但这份笔记的操作是在 cmd 里跑python fine_tune.py所以编辑器只是用来写代码的不需要 IDE 自带的运行按钮。我的习惯是 VSCode Python 插件补全好用报错红波浪线能提前拦住很多低级错误。工作目录按这个结构建D:\ollama\fine_tune_deepseek\ ├── data\ │ ├── file1.txt │ └── file2.txt └── fine_tune.py文件夹建立之后先别急着写代码先确认一件事你的模型路径。如果用的是 Hugging Face 格式脚本里的model_name就指向那个目录。如果用 Ollama 的 GGUF 文件脚本会直接崩在第 2.3 节的加载步骤这是新手最容易踩的第一道门槛。3. 把 txt 变成训练样本目录规划、编码与 Tokenizer 的预处理细节3.1 训练数据不是越多越好而是越“干净”越好很多人以为微调就是把一堆 txt 扔进去让模型自己“悟”。实际上txt 的组织方式直接决定微调效果。每个 txt 文件里的每一行建议是一个完整的、有语义的句子或对话片段。举个例子你好我是小明。 今天天气真好。 你喜欢编程吗这算一个合格的样本文件。但如果你把一个新闻稿整篇粘贴进去换行混乱模型学出来的东西就会前言不搭后语。建议每行控制在 50 字以内超过 100 字的长句会被max_length512截断截断的部分如果落在半个字上就是纯噪声。数据量方面微调 1.5B 模型最少准备 500 行左右的样本想看到明显的行为变化2000 行以上才稳妥。数据质量比数量重要宁可 500 条精编对话也别 5000 条复制粘贴。3.2 读取与 Tokenizer 编码第一次让中文文本变成张量数据文件的读取逻辑不复杂但要处理编码问题。Windows 下 txt 文件默认可能是 GBK 编码脚本里用encodingutf-8读取 UI 里保存的 Unicode 文件没问题但如果你从别处拷来的文件是 GBK就会在f.read()那行炸出UnicodeDecodeError。这个问题放到第 5 章避坑里细说这里先把代码写对import os from transformers import AutoTokenizer, AutoModelForCausalLM # 加载本地模型与分词器 model_name D:/ollama/models/deepseek-r1:1.5b tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained(model_name) # 读取 data 目录下所有 .txt 文件 data_dir D:/ollama/fine_tune_deepseek/data texts [] for filename in os.listdir(data_dir): if filename.endswith(.txt): with open(os.path.join(data_dir, filename), r, encodingutf-8) as f: texts.append(f.read()) # 统一编码为模型输入张量 inputs tokenizer( texts, return_tensorspt, max_length512, truncationTrue, paddingmax_length ) print(Data preprocessed successfully!)逻辑说明tokenizer把纯文本切分成 token 序列再映射成数字 IDreturn_tensorspt表示返回 PyTorch 张量模型才能计算。这一步的本质是把人类语言翻译成模型能读的向量空间。参数说明max_length512是截断上限超过 512 个 token 的内容会被丢弃。1.5B 模型的上下文窗口不算大512 是保守值。truncationTrue保证长文本被安全截断paddingmax_length则把所有样本补到统一长度方便组成 batch。需要留意的是中文一个字的 token 数大约是 1 到 2 个512 token 大约能容纳 300 到 500 个汉字短句训练样本绰绰有余。3.3 一个常被忽略的问题分词器的 pad_token 可能是空的1.5B 这类小模型的 tokenizer 有时没有定义pad_tokenpaddingmax_length会报错或者警告。稳妥的做法是在加载后主动设置if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token逻辑说明eos_token是句子结束符如果没有专门定义 padding 符号直接把结束符顶上去是社区常见的临时方案。这样做的副作用是 padding 区域也会被模型看到一部分语义但对短文本微调的实际影响可以忽略。这一步做完数据预处理的链路就通了。接下来进入训练核心环节。4. 训练脚本拆解从 Trainer 参数到显存耗尽的真实表现4.1 TrainingArguments这些参数照着抄但要知道为什么微调脚本的核心是 Hugging Face 的TrainerAPI。它把训练循环、日志、保存、评估全部封装好对新手友好。但封装不等于黑匣子几个关键参数必须理解否则出问题都不知道调哪里。先把训练参数配置贴出来from transformers import Trainer, TrainingArguments training_args TrainingArguments( output_dir./results, num_train_epochs3, per_device_train_batch_size1, gradient_accumulation_steps8, save_steps500, logging_steps50, learning_rate2e-4, warmup_steps100, fp16False, report_totensorboard )逻辑说明Trainer会按TrainingArguments里的配置自动执行前向传播、计算损失、反向传播、参数更新这四个步骤。output_dir用于存放中间 checkpoint 和最终结果。参数说明num_train_epochs3训练 3 轮。数据量小时 1 轮就够3 轮是均衡选择。轮次过多容易过拟合生成的内容会反复出现训练集中的原句。per_device_train_batch_size1每张显卡同时处理 1 个样本。1.5B 模型全参数微调非常吃显存batch_size 设 2 以上大概率 OOMOut of Memory。gradient_accumulation_steps8每 8 步做一次真正的梯度更新等效于 batch_size8 的效果但显存占用不增加这是省显存的关键设置。learning_rate2e-4微调的学习率比从头训练低 1 到 2 个数量级太大权重会被冲坏。fp16False如果没有 NVIDIA 显卡或者显存不够不要开混合精度。实测 6GB 显存开 fp16 可能反而更不稳定。4.2 Trainer 的输入格式别再直接塞 dict很多初学者按原笔记抄代码写成train_datasetinputs[input_ids]这在最新版 transformers 里会报错。标准做法是构造一个Dataset对象把input_ids和attention_mask一起传进去from datasets import Dataset import torch dataset Dataset.from_dict({ input_ids: inputs[input_ids], attention_mask: inputs[attention_mask], labels: inputs[input_ids] }) trainer Trainer( modelmodel, argstraining_args, train_datasetdataset, ) trainer.train() print(Model fine-tuning completed!)逻辑说明labels在因果语言模型里通常等于input_ids自身模型用前一个 token 预测下一个 token。attention_mask告诉模型哪些位置是真实文本、哪些是 padding训练时不计算 padding 位置的损失。参数说明trainer.train()一旦执行终端会开始滚动 loss 数值。能看到loss在逐渐下降就说明训练在走如果 loss 不变或者上下乱跳通常不是模型问题是数据问题回到第 3 章检查 txt 内容。4.3 训练时间的真实预期不是几分钟的事一个 1.5B 模型在消费级显卡比如 RTX 3060 12GB上单卡训练 1000 条样本、3 个 epoch大约需要 20 到 40 分钟。如果你的机器只有 CPU时间会膨胀到 2 到 6 小时。这里有一个经验公式每 100 条样本、每个 epochGPU 大约耗时 1 到 2 分钟CPU 耗时 5 到 10 分钟。训练过程中的日志文件会写入./logs目录可以用 TensorBoard 看曲线tensorboard --logdir./logs打开浏览器访问http://localhost:6006能看到 loss 曲线和梯度范数。这个界面不是必须的但如果你想知道模型到底在不在学习看一眼 loss 曲线比什么都直观。5. 常见问题排查五个让新手卡壳的坑5.1 模型加载报错“不是 Ollama 模型格式”现象执行AutoModelForCausalLM.from_pretrained(D:/ollama/models/deepseek-r1:1.5b)时报错提示找不到config.json或格式不识别。原因Ollama 用 GGUF 格式存储权重transformers 只认 PyTorch 的pytorch_model.bin或safetensors。两份文件体系完全不同Ollama 目录里根本没有config.json。解决去 Hugging Face 下载 DeepSeek-R1-Distill-Qwen-1.5B 的 PyTorch 权重。下载后把目录放到D:/ollama/models/hf/下把model_name指向这个新路径再重新运行脚本。5.2 读取 txt 报 UnicodeDecodeError现象f.read()抛出UnicodeDecodeError: utf-8 codec cant decode byte...。原因Windows 记事本另存为时默认编码可能是 GBK 或 ANSI不是 UTF-8。解决要么用 VSCode 打开文件后重新保存为 UTF-8 格式要么读取时指定容错编码。最省事的做法是with open(os.path.join(data_dir, filename), r, encodingutf-8, errorsignore) as f: texts.append(f.read())参数说明errorsignore会跳过无法解码的字节代价是丢掉部分字符但至少脚本能跑完。5.3 打印提示词出现tokenizer.pad_token警告现象控制台输出一大段警告说 pad token id 没有设置可能影响训练。原因新版本 tokenizer 对 padding 行为更严格没有pad_token时无法构建固定长度的 batch。解决在加载 tokenizer 后加一行兜底if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token5.4 训练时显存不够OOM现象终端报CUDA out of memory或者训练在第一个 step 就中断。原因1.5B 全参数训练模型本身占用约 3GB加上优化器和梯度6GB 显存可能刚好处在崩溃边缘。解决把per_device_train_batch_size降到 1gradient_accumulation_steps提到 16 或 32关闭fp16如果还不行把max_length从 512 降到 256显存占用会立竿见影地下降。5.5 训练完成但生成结果和原来一模一样现象微调后跑生成样例输出的文本跟原始模型完全没有差别。原因最常见的情况是数据量太小几百条样本对 1.5B 模型的影响微乎其微另一种情况是learning_rate太大模型权重被破坏后模型产生了退化输出。解决先把训练数据扩充到 1000 行以上学习率调到1e-5到5e-5之间再试。如果还是没有变化检查是否真的加载了微调后的权重路径有时候fine_tuned_model_path写错位置加载的是原始模型。6. 验证与导出微调不是跑完训练就结束训练完成后最容易被忽略的一步是验证模型到底学了什么。很多初学者保存完权重就以为大功告成实际上模型可能只是“记住了”训练集里的句子换个说法就露馅。我的验证习惯是准备三个不同角度的测试样本训练集中出现过的句子、语义相似但用词不同的句子、完全未见过的主题。分别跑一次生成对比三个输出才能判断微调是“学会”还是“背题”。# 加载微调后的模型 fine_tuned_model_path D:/ollama/fine_tune_deepseek/fine_tuned_model fine_tuned_tokenizer AutoTokenizer.from_pretrained(fine_tuned_model_path) fine_tuned_model AutoModelForCausalLM.from_pretrained(fine_tuned_model_path) # 多组测试样本 test_inputs [ 人工智能是, 今天天气, 你最喜欢的编程语言是 ] for input_text in test_inputs: input_ids fine_tuned_tokenizer.encode(input_text, return_tensorspt) output fine_tuned_model.generate( input_ids, max_length50, num_return_sequences1, do_sampleTrue, temperature0.7 ) generated_text fine_tuned_tokenizer.decode(output[0], skip_special_tokensTrue) print(输入:, input_text) print(生成:, generated_text) print(---)逻辑说明generate是自回归生成模型逐个预测下一个 token。do_sampleTrue开启采样让输出带随机性temperature0.7控制随机性大小数值越低输出越保守0.7 是通用值。参数说明max_length50限制生成长度防止模型无限循环输出。skip_special_tokensTrue在解码时去掉pad、eos这类特殊符号输出的文本更干净。微调模型的导出值得单独说一句。save_pretrained保存的目录结构包含config.json、pytorch_model.bin或model.safetensors、tokenizer.json和vocab.json。这四个文件缺一不可复制到别的机器时最好整个目录拷贝。如果你用的是新版 transformers权重文件可能是model.safetensors而不是pytorch_model.bin这是正常现象加载代码无需改动。另外一个玄学问题微调后的模型想重新导入 Ollama 使用需要先转成 GGUF 格式再通过 Modelfile 导入这个过程比训练本身还容易翻车。我的建议是如果只在本地测试直接用 transformers 加载就行没必要绕一圈回 Ollama。真要在生产环境用再把导出单独拿出来做别和微调混在一次操作里。验证完输出之后还有一件事值得做用pip list确认当前环境里的 torch 版本和 transformers 版本做个快照。微调工程的复现难不在代码而在环境版本一变之前的权重可能加载不了。把这几个版本号记下来比什么都值。说了这么多其实就一句话微调这条路跑通不难跑好才是功夫。从那以后我每次做完微调都强制自己走一遍三组验证确认不是背题才敢往外拿。希望帮到你。本文还有配套的精品资源点击获取