BERT-BILSTM-CRF中文NER实战:原理、预处理与PyTorch训练指南
简介这是一份基于BERT-BILSTM-CRF进行中文命名实体识别的完整项目源码包适合计算机相关专业学生用于毕业设计、课程设计或入门进阶。资源以dgre数据集为例包含从数据处理、模型训练到预测的整套Python代码并配有使用说明、预训练模型及标注数据可帮助读者快速复现NER流程并迁移到其他数据集。包内共20个文件以Python脚本、JSON配置与数据、txt标签说明为主整体大小约1.03MB。目录划分清晰checkpoint保存模型model_hub集成chinese-bert-wwm-ext预训练模型data提供dgre和duie的原始及处理数据main.py/predict.py等可直接运行。依赖版本已列明支持调整max_seq_len、batch_size等参数适配显存。目前已有1250人学习下载代码均经过运行验证。除完整实现外还包含数据处理脚本和预测入口便于在此基础上修改拓展适合作为项目初期演示或实战练习。1. 中文命名实体识别为什么绕不开BERT-BILSTM-CRF这条路线做中文NER的从业者无论是从法律合同里抽公司名、在病历文本里找药名还是从新闻语料中识别地名和人名最常用到的开源组合就是BERT-BILSTM-CRF。这个标题背后的源码包并不神秘它把预训练语义特征、双向序列建模和标签约束三层东西串在一起解决的是怎么从一句中文里稳定地抽出结构化实体这个具体问题。适合的人群很明确已经掌握Python和PyTorch基础手上有一批标注样本或想用自己的数据微调需要一套能训练、能评估、能断言的完整工程。它不适合做算法科普更适合把它当工具箱拆开改。2. 三层结构拆解BERT、BILSTM、CRF各自在解决什么问题一个常见误区是BERT已经很能打为什么还要接BILSTM和CRF。BERT输出的每个token的向量确实包含上下文语义但中文NER面对的标签序列有严格的结构约束比如一个实体必须有开头且内部连续两个实体不能交叉嵌套。这三层解决的问题完全不同各管一段。2.1 BERT层中文语义特征为什么不能只用静态词向量中文没有天然空格分词实体边界和语义高度依赖上下文。比如长春可以是地名也可以是机构名的一部分静态词向量如Word2Vec和GloVe在具体句子里给不出动态区分。而BERT在预训练阶段通过掩码语言模型学到了字的上下文表示同一个字在不同句子里的向量不一样这是它作为NER基底层的核心价值。用bert-base-chinese或bert-base-whole-word-masking-chinese是常见做法。前者按字切分适合以字为粒度做NER后者用了全词掩码对中文词语整体建模能力更强。下游任务不是特别吃词边界语义时bert-base-chinese更容易和逐字标注的标签对齐是多数项目起步时的选择。BERT层本身不训练实体分类头它只负责把每个token编码成768维的语义向量。通常的做法是取最后一层的last_hidden_state作为BILSTM的输入不加Pooler。网络深层和浅层各有信息但NER任务上实践表明最后一层语义最直接。2.2 BILSTM层双向LSTM到底补了BERT的什么短板BERT的注意力是各向同性的它会把句子所有位置的信息加权融合但对实体紧邻边界这类局部约束不够敏感标签序列的前后关联并不是它显式优化的目标。BILSTM在BERT输出的基础上做了一次按时间步的双向序列建模前向隐状态负责累积从左往右的上下文后向隐状态负责累积从右往左的上下文拼接后得到每个token增强后的局部特征。BILSTM层的hidden_size一般取128或256num_layers1就够用。层数再加对NER指标提升非常有限反而增加参数量和过拟合风险这正是新手容易踩的地方。BILSTM输出的维度是双向拼接所以乘二之后过一个线性层把维度压到标签类别数得到每个token在每个实体标签上的发射分数。BILSTM本身做不了标签之间的约束它只是给CRF提供更好的发射分数。2.3 CRF层标签依赖关系是最后一道闸门CRF不是神经网络它是一个基于转移矩阵的序列标签解码层。训练时CRF计算整条标签路径的对数似然把标签之间的转移合法性也纳入损失函数。推理时用Viterbi算法在指数级标签路径中找出全局最优序列。CRF的关键作用体现在标签转移矩阵上。比如用BIO标注体系B-ORG后面跟I-ORG合法跟I-PER非法O后面直接跟I-PER非法。没有CRF逐token做softmax会选择各自最大概率的标签结果可能出现O I-PER这种在物理世界不存在的实体片段。CRF用转移矩阵直接惩罚这类非法转移训练中它会自动学实体开头之后必须是同类实体内部标签这类隐性语法规则。PyTorch实现中torchcrf库提供现成的CRF类和Viterbi解码虽然项目页面很多年没更新接口稳定且和PyTorch的batch_first兼容不需要自己重写前向算法。如果你拿到的源码里是手动实现的CRF核心就是转移矩阵的log-sum-exp归一化和路径解码逻辑可以检查但没必要自己造轮子。3. 数据和预处理从原始中文文本到模型输入张量做NER的人都会卡在第一步手上是几百条Excel或JSON里的中文句子标签只标了实体文字但模型要的是和token一一对应的标签序列。数据预处理决定模型上限模型结构只是把上限逼近。这一章的步骤是踩过无数坑之后沉淀下来的标准流程。3.1 标注格式选择BIO还是BIOESBIO把标签拆成B-实体类型表示实体开头I-实体类型表示实体内部O表示非实体。BIOES在此基础上多加了E-实体类型表示实体结尾、S-实体类型表示单字实体。从实现和标注成本看BIO最简单绝大多数源码包默认用BIO。BIOES在实体边界上约束更细配合CRF通常能稍微提升边界切分准确率但标注工作量变大。一个不常被提到的细节是BIOES的S单字标签对中文地名这类单字实体特别有用没有S的话单字实体只能标成B-LOC然后靠CRF推断其长度容易产生歧义。如果数据量中等且以地名、人名为主可以用BIOES调试但最终比较F1再定不要盲目套用。无论选哪种原数据里凡是标了实体但没有标注内部词性的都需要一个转换脚本统一成BIO或BIOES。常见格式是{text: 王小明在北京实习, entities: [{name: 王小明, type: PER, start: 0, end: 3}]}需要把区间转成逐字标签。转换逻辑如下def entities_to_bio(text, entities, label_typeBIO): # 按字初始化标签 labels [O] * len(text) for ent in entities: start, end ent[start], ent[end] etype ent[type] if end len(text): continue if end - start 1: if label_type BIOES: labels[start] fS-{etype} else: labels[start] fB-{etype} else: labels[start] fB-{etype} for i in range(start 1, end): labels[i] fI-{etype} if label_type BIOES: labels[end - 1] fE-{etype} return labels这里有一个必须处理的点实体区间在原文本里可能跨越空格或标点转换前要先统一原始文本的清洗规则空格全角半角不一致会导致start和end偏移后续所有标签全部错位。日志里一旦发现标签序列和文本逐字对不上先查原始文本用什么方式切分的。转换后最好把BIO标签序列存成独立文件不要每次训练临时转换方便回看。3.2 文本切分与BERT tokenizer对齐中文BERT的字表覆盖常用汉字一个字映射一个token看起来把句子按字切分再转token就行。但遇到英文、数字、特殊符号情况就变了。bert-base-chinese的wordpiece会把OpenAI切成open、##ai两个token如果你在原始文本层面按字母给它配标签token级标签序列就必然错位。安全做法是用tokenizer自带的对齐机制。传入按字切好的列表用is_split_into_wordsTrue让tokenizer返回word_ids再把每个token的标签通过word_id映射回原始位置from transformers import BertTokenizer tokenizer BertTokenizer.from_pretrained(bert-base-chinese) def encode_sample(text, labels, label2id, max_len128): # text和labels都必须按原始字粒度对齐 chars list(text) enc tokenizer( chars, is_split_into_wordsTrue, truncationTrue, max_lengthmax_len, paddingmax_length ) input_ids enc[input_ids] attention_mask enc[attention_mask] word_ids enc.word_ids() label_ids [] for wid in word_ids: # wid是None表示[CLS]/[SEP]/[PAD] label_ids.append(0 if wid is None else label2id[labels[wid]]) return input_ids, attention_mask, label_idsenc.word_ids()是新版transformers的接口返回list长度和input_ids一致每个值对应原始文本中的字位置None代表非token位置。[CLS]和[SEP]天然不计入损失pad位置的标签全部置为0O对应的id并且后续计算CRF损失时用attention_mask屏蔽。这里注意原始文本里一个字在极端情况下可能映射到多个token比如生僻字被拆成两段wordpieceword_ids会把两个token映射到同一个字索引标签也会复制两份CRF转移矩阵会把这个连续重复当实体内部处理通常不会产生合法性问题但会让实体长度统计偏长。真正想规避可以在预处理阶段把生僻字替换为[UNK]让标签对齐逻辑更干净。3.3 标签映射与数据集划分标签需要固定成字典序的label2id并且O的id固定为0因为pad位置的标签都以0填充。实体类别多时label2id是手工维护还是脚本生成都行但一旦训练开始就不能再改。数据划分的三个坑要注意一是按句子随机划分会导致同一文档的上下文被切到训练集和测试集同一个专有名词在测试集里被模型见过了F1虚高最好按文档或来源字段做group划分二是实体类别分布不均时用分层采样保证每个类别在训练集和验证集都出现三是验证集要包含足够多的实体数目少于200个实体的验证集F1波动太大模型之间差1个点很难判断是谁的问题。数据量少时冻结BERT层参数只训练BILSTM和CRF能显著减少过拟合和显存压力数据量在1万条以上时全量微调BERT通常能再多几个点F1。这是选型决策里最值得投入验证的一件事。4. 跑通与调参基于PyTorch的BERT-BILSTM-CRF训练全流程源码包到手之后第一步不是直接跑而是先确认目录里有没有模型权重文件。如果没有预训练BERT权重脚本会尝试从HuggingFace下载国内网络慢或下载中断训练直接卡死。我的习惯是先载入BERT权重做一次forward能出结果再进训练循环。跑通基线之后再按本章的参数策略逐步调。4.1 源码骨架与文件职责清单一个规范的BERT-BILSTM-CRF项目通常包含以下几类文件拿到源码先对照这个清单核对缺什么文件职责缺少时的表现model.py定义BertBilstmCrf模型类训练报ModuleNotFoundErrordata_loader.py读取标注数据并转成Dataloader输入维度对不上模型train.py训练循环、保存checkpoint只有模型没有权重predict.py载入权重做实体抽取无法产出可用结果config.py/args.py超参数集中管理到处改参数容易改漏源码包里如果没有config.py建议自己建一个把max_len、batch_size、lr_bert、lr_lstm、num_epochs、model_path全部集中避免每次训练在命令行里敲一长串参数。Python项目的可维护性往往不是靠代码而是靠参数的集中管理。4.2 核心模型实现与forward设计PyTorch下模型类核心是三层串联加一个损失函数。参考实现如下import torch import torch.nn as nn from transformers import BertModel class BertBilstmCrf(nn.Module): def __init__(self, bert_dir, num_labels, lstm_hidden256, dropout0.5): super().__init__() self.bert BertModel.from_pretrained(bert_dir) self.dropout nn.Dropout(dropout) self.bilstm nn.LSTM( input_sizeself.bert.config.hidden_size, hidden_sizelstm_hidden, num_layers1, batch_firstTrue, bidirectionalTrue ) self.fc nn.Linear(lstm_hidden * 2, num_labels) self.crf CRF(num_labels, batch_firstTrue) def forward(self, input_ids, attention_mask, label_idsNone): # BERT输出[batch, seq_len, hidden_size] bert_out self.bert( input_idsinput_ids, attention_maskattention_mask ).last_hidden_state bert_out self.dropout(bert_out) # BILSTM继续编码[batch, seq_len, 2*hidden] lstm_out, _ self.bilstm(bert_out) logits self.fc(lstm_out) mask attention_mask.bool() if label_ids is not None: # 训练CRF负对数似然损失 loss -self.crf(logits, label_ids, maskmask) return loss # 推理Viterbi解码出最优标签序列 pred self.crf.decode(logits, maskmask) return predlstm_hidden256时最终特征维度是512对多数中文NER数据集足够。dropout0.5是BERT底座之下常用的经验值它打在BERT输出之上、BILSTM之前。注意nn.LSTM默认num_layers1时dropout参数无效源码里如果写了dropoutlstm_dropout但num_layers1这个dropout实际不生效真正生效的是上面那个nn.Dropout。模型内不要忘了把bert之外的新增参数注册为需要梯度的模块PyTorch自动处理但在冻结BERT时要用requires_grad_控制。CRF层的输入维度必须是[batch, seq_len, num_labels]label_ids是[batch, seq_len]mask是[batch, seq_len]的bool张量数据类型不对会在torchcrf内部报错。这条踩的人特别多值得先打印各张量的shape再组batch。4.3 训练循环与分组学习率BERT层的参数和随机初始化的LSTM、FC层必须用不同学习率。BERT是预训练权重学习率过大直接灾难性遗忘随机初始化层则需要相对较大的学习率才能收敛。常见分组策略是lr_bert2e-5、lr_lstm1e-3优化器用AdamW。训练循环里需要梯度裁剪CRF在长序列上梯度幅度偏大不裁剪的话loss曲线会出现突然跳高的毛刺。def train_epoch(model, loader, optimizer, device): model.train() total_loss 0.0 for step, batch in enumerate(loader): input_ids batch[input_ids].to(device) attention_mask batch[attention_mask].to(device) label_ids batch[label_ids].to(device) optimizer.zero_grad() loss model(input_ids, attention_mask, label_ids) loss.backward() # 梯度裁剪对CRF训练很关键 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm5.0) optimizer.step() total_loss loss.item() if step % 100 0: print(fstep {step}, loss {loss.item():.4f}) return total_loss / len(loader)梯度裁剪的max_norm5.0是常用起点太小会拖慢收敛太大会让CRF的转移矩阵学得激进。反馈到实际项目里loss在epoch初期就该明显下降如果三个epoch后loss还在高位徘徊先检查BERT是否被冻结以及学习率是否打到了天量级。预测阶段不要在torch.no_grad()里直接取logits.argmax(-1)那会绕开CRF的转移约束开发集F1也许还行真实数据上会频繁出现非法标签。推理必须走crf.decode和训练保持一致。4.4 模型保存与checkpoint策略保存模型时不能只存state_dict因为BertModel.from_pretrained需要的是BERT目录结构或权重路径。单独存bert权重和下游权重分开管理最省心torch.save(model.state_dict(), ./checkpoints/best.pt)torch.save可以传dict把bert和bilstm_fc分别拆开存方便只替换BERT底座时不动下游参数。配合model.save_pretrained把BERT权重存在./bert_model/下之后推理直接用这个目录初始化不用再从HuggingFace拉一次。判断best.pt不能用训练loss要用验证集的F1。Serper知识里行业惯例是每epoch结束后跑一次验证F1比当前最高则保存并覆盖。F1的计算要基于实体级别一个实体所有token都预测正确才算对token级别正确率会掩盖边界偏移问题。用一个实体级评估函数逐句对比预测序列和真实序列按(B-XXX, I-XXX...)分组还原实体后计算精确率、召回率、F1。5. 五个高频翻车点及排查清单这个项目在实际跑的过程中常见的坑集中在数据、损失、解码、显存四个方面。每一条都是真实复现过的按照现象、原因、解决的顺序写可以直接对照排查。5.1 标签分布严重失衡现象训练loss正常下降但实体级别的F1只有20%左右预测结果几乎全是O标签。查看CRF输出的转移矩阵发现模型把所有token都判成了O。 原因数据里O占比通常在80%以上BILSTM输出的logits被O类别主导加上CRF在学习时也会倾向于选择全局概率最大的路径实体类别被淹没。 解决先统计各类别标签占比。如果实体标签总和低于10%考虑在计算CRF损失时给实体类别加权但torchcrf本身不直接支持权重。替代做法是在数据集层面做样本重采样保留实体密度高的句子把纯O句子的比例压下来。另外验证阶段改用微平均F1不要用准确率否则1%的实体错误率会被99%的O正确率稀释。5.2 BERT层学习率过大导致训练震荡现象第一个epoch loss降到2附近第二个epoch开始回升验证集F1波动很大。 原因整组参数共用1e-3学习率BERT预训练权重的embedding层被快速破坏。BERT的embedding是WordPiece向量粒度细但非常敏感。 解决分组学习率。BERT部分2e-5到5e-5BILSTM和FC部分1e-3。实现方式是对参数列表按名称分组bert_params [p for n, p in model.named_parameters() if bert in n and p.requires_grad] other_params [p for n, p in model.named_parameters() if bert not in n and p.requires_grad] optimizer torch.optim.AdamW([ {params: bert_params, lr: 2e-5}, {params: other_params, lr: 1e-3} ], weight_decay1e-2)5.3 长文本截断导致实体消失现象句子长度超过500字时模型的实体召回率断崖式下降。观察预测结果后半段全是O。 原因BERT位置编码上限是512超过部分被tokenizer截断后半段文本完全没进入模型。 解决先用长度分布统计如果文本普遍超过512就在encode_sample之外做滑动窗口切分。窗口长度取256或384重叠长度取64按实体粒度和文本语言调整。推理完成后把窗口的重叠区合并重叠区后半部分采用后一个窗口的预测。对中文而言实体一般不会跨窗口所以窗口边界刚好切断实体的概率可控但要注意把概率较高的实体类别如机构名多字放在窗口中间位置会更好。5.4 训练用CRF、推理用argmax现象开发集F1在训练每个epoch后评估很高但最终推理接口输出的标签序列有O I-PER这种非法片段。 原因验证脚本里用了logits.argmax(-1)取了每个token最大概率标签跳过了CRF的Viterbi解码而训练时CRF把非法转移的路径压掉两种情况下的最优路径不同。 解决统一预测入口。训练循环里的model.predict方法直接调crf.decode验证脚本和对外服务都用同一个方法。排查时在predict.py里搜索argmax凡是argmax(-1)出现在序列标签解码处都有问题。另外注意crf.decode返回的是label id列表长度是seq_len要和原始文本的字数对齐记得把[CLS]、[SEP]和pad位置剔除后再做实体还原。5.5 显存溢出与batch size的取舍现象batch_size32直接OOM改成8之后训练速度大幅下降。 原因BERT-base有110M左右参数中间激活的显存开销远大于模型参数本身。padding占比高时即使文本很短max_len512的padding也让计算量膨胀。 解决优先开混合精度训练PyTorch用torch.cuda.amp的GradScaler把FP16的BERT计算纳入自动混合精度显存能省下一半。其次是降低max_len如果实体分布偏短128的序列长度对F1影响很小。最后考虑梯度累积accumulation步数等于32除以实际batch size效果等于大batch但参数更新次数不变。做完这三级优化还不够再加torch.utils.checkpoint对BERT层做梯度检查点能够大幅降低中间激活但训练时间会变长属于兜底方案。6. 验证与进阶怎么判断这个NER模型真的能用跑通之后不要只看总F1把验证集按实体类别拆开统计精确率、召回率。人名、地名、机构名三类F1差距超过0.3是常态机构名边界复杂经常被切成子串。逐类别统计后把预测错的样本拉出来逐条看统计错误集中在边界偏移还是实体识别错误。边界偏移通常通过BIOES标注体系改善实体识别错误则要检查是否该实体属于OOV词如果是给它的类别增加训练样本比调模型参数更有效。进阶方向有两个一是把BERT-BILSTM-CRF中BILSTM替换成其他序列编码器比如在数据量大的时候用BERTCRF直接做端到端二是针对超长文本场景研究Longformer等长文档模型的中文权重和滑动窗口滤波方案。这里要强调一点中文NER的瓶颈通常不在模型结构而在标注数据质量单一模型在数据集上反复调参不如留一部分精力做数据清洗。另一个技巧是训练时用早停加验证集F1的监督保存最优权重后再用全量训练数据短训练一轮这会让测试集指标略微软性沾边如果是为了基层效果评估不太推荐但实际交付里是常见做法。最后说一个我的习惯每次调整参数后把改动和F1变化记录在项目里模型文件命名带参数版本号。这个项目的调试结果往往依赖数据分布某个batch size在本数据集上提分换个数据集可能完全无效自己的调参日志比网上任何教程都可靠。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

superpowers技能插件:让AI编程助手从聊天到动手干活

superpowers技能插件:让AI编程助手从聊天到动手干活

superpowers 这个单词在软件开发圈子里有两层意思:一层是心理学里的“心流状态”,另一层是这两年冒出来的 VS Code 技能插件。我这里要聊的是后者。先说结论:它是一套能把 AI 编程助手从“聊天机器人”变成“能动手干活的小弟”的技能插件&am…

2026/10/9 1:25:58 阅读更多 →
Moodle 5.0 qbank_bulkmove 升级指南:批量移动题目从「服务端表单渲染」迁移到「Modal + WebService」架构

Moodle 5.0 qbank_bulkmove 升级指南:批量移动题目从「服务端表单渲染」迁移到「Modal + WebService」架构

教育后端前端 【免费下载链接】moodle Moodle - the worlds open source learning platform 项目地址: https://gitcode.com/gh_mirrors/mo/moodle 点击查看 免费下载 本文以仓库中 qbank_bulkmove 升级说明 为骨架,系统梳理 Moodle 5.0 中「批量移动题…

2026/10/9 1:25:58 阅读更多 →
SSM+JSP酒店客房预定管理系统源码:部署实战与避坑指南

SSM+JSP酒店客房预定管理系统源码:部署实战与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 1:24:57 阅读更多 →

最新新闻

2026 Agent 开发实战手册:从架构、记忆到并发与安全的工程化落地

2026 Agent 开发实战手册:从架构、记忆到并发与安全的工程化落地

1. 这份报告到底在聊什么2026 年的 Agent 开发者调研报告,加上 Alibaba Cloud 的 AI Agent Handbook,这两个东西放在一起看,其实指向的是同一件事:Agent 开发这件事,已经从“能不能跑起来”进入到了“怎么跑得稳、跑得…

2026/10/9 1:58:18 阅读更多 →
EI_策略训练_Isaac sim

EI_策略训练_Isaac sim

Isaac Gym 本身不是动作采集(motion capture)框架,而是一个基于 GPU 加速的强化学习仿真训练平台。但它在利用动作数据(如 MoCap 录制的行走、跑跳等)来训练机器人运动控制策略方面具有显著优势,因此常被用…

2026/10/9 1:58:18 阅读更多 →
IL_动作捕捉和模仿学习

IL_动作捕捉和模仿学习

IL:Imitation Learning 实际机器人动作采集和策略训练中,完全可以将 CSV 文件(动作数据) 机器人模型 XML 文件(如 URDF、MJCF 或 MuJoCo XML)转换生成 .npz 文件,这是机器人模仿学习&#xff0…

2026/10/9 1:58:18 阅读更多 →
为什么团队应该从Cypress升级到e2e?3个真实场景分析

为什么团队应该从Cypress升级到e2e?3个真实场景分析

为什么团队应该从Cypress升级到e2e?3个真实场景分析 【免费下载链接】e2e Next generation e2e testing framework for web and mobile apps. 项目地址: https://gitcode.com/GitHub_Trending/e2e6/e2e e2e 是一个面向 Web 和移动应用的新一代端到端&#xf…

2026/10/9 1:58:18 阅读更多 →
研究生计算机网络实验3指南:抓包分析TCP状态机与重传机制

研究生计算机网络实验3指南:抓包分析TCP状态机与重传机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 1:58:18 阅读更多 →
OpenPencil Vue SDK 中的 useI18n:读取本地化界面消息并构建自定义语言切换器

OpenPencil Vue SDK 中的 useI18n:读取本地化界面消息并构建自定义语言切换器

前端桌面应用AI 应用MCP 服务 【免费下载链接】open-pencil AI-native design editor. Open-source Figma alternative. 项目地址: https://gitcode.com/gh_mirrors/op/open-pencil 点击查看 免费下载 useI18n() 是 OpenPencil Vue SDK(open-pencil/vue…

2026/10/9 1:57:18 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →