DJL与Spring集成:Java后端部署深度学习模型的实践指南
简介面向 Java 及 JVM 平台开发者这份压缩包聚焦 DJL 与 Spring 框架的整合提供从环境配置、数据预处理到模型训练、评估与推理的完整实践资料着力解决在 Java 生态中开发深度学习应用时的入门与集成难题。资源共 66 个文件以 29 个 java 源码文件为主辅以 12 张 jpg 与 12 张 png 图示说明、6 个 xml 配置、3 个 params 模型参数及 properties、json 等工程文件便于对照代码理解实现细节。已有 499 人浏览学习。资料覆盖 DJL 核心组件、数据集批量处理、损失函数与优化器选择、模型保存加载以及与 Spring Boot/RESTful API 集成等关键环节包内包含按模块整理的代码示例、笔记文档和小规模实战项目从环境搭建到故障排查均有涉及。无论初学者还是需要迁移技术栈的开发者都能获得清晰、可操作的参考路径。1. DJL 与 Spring 集成Java 后端跑深度学习的低成本路径标题里的 Fast Deep Java Library实际指的就是 DJLDeep Java Library。这个框架的价值在于Java 团队不用切到 Python就能在 JVM 里完成深度学习的训练与推理而把它和 Spring 工程整合是最常见也最实用的落地方式——模型加载、推理接口、训练任务都可以交给 Spring 管理服务还是原来那个 Spring Boot 服务不需要额外维护 Python 运行时。适合谁读手里已经有一套 Spring 服务、正在为 AI 功能纠结“要不要引入 Python 技术栈”的开发者或者已经决定用 DJL、但不确定该怎么把模型生命周期和 Spring 的 Bean 生命周期对齐的人。下面从核心抽象讲起一路到可复现的依赖、代码、训练闭环最后列出我在实际整合中踩过的坑。2. 先理解 DJL 的三个核心抽象再定 Spring 里的 Bean 边界2.1 Model、Predictor 与 Criteria加载与推理的分工DJL 的抽象层非常克制跟 Spring 整合之前只需要先弄清楚三个对象之间的边界Model是模型的生命周期载体持有网络结构和参数Criteria是描述“我要什么样的模型”的工厂参数Predictor是真正执行推理的会话对象。这三者的线程模型和生命周期都不同直接决定你在 Spring 里怎么配置 Bean。Model在 DJL 里是一个 AutoCloseable加载后可以长期持有、被并发读取适合做成 Spring 单例 BeanPredictor不是线程安全的但创建成本很低正确用法是用完即关。最典型的加载代码是这样的CriteriaImage, Classifications criteria Criteria.builder() // 输入输出类型影响后续 Translator 的选择 .setTypes(Image.class, Classifications.class) // 从 Model Zoo 里加载指定的模型 .optApplication(Application.CV.IMAGE_CLASSIFICATION) .optArtifactId(resnet18) .build(); Model model criteria.loadModel();这段代码的关键在于optArtifactId它指定了模型 Zoo 里的真实模型标识第一次加载会把网络结构和权重拉到本地缓存目录。如果你的网络环境受限这个下载经常会让加载卡在进度条阶段我一般会在加载前先手动把模型文件准备好再用optModelPath指向本地路径。setTypes决定了后续Predictor.predict方法的签名声明输入为Image、输出为Classifications代码就是强类型的写错类型编译期就报错。Predictor 的使用方式绝大多数人第一次都会写错。正确做法是每次推理都立刻创建一个、用完立刻关闭try (PredictorImage, Classifications predictor model.newPredictor()) { Classifications result predictor.predict(image); return result; }newPredictor的内部逻辑只是组装 Translator 和推理上下文并不加载模型所以这个创建动作开销很低没必要做池化。真正重的是model的加载动作它要做参数反序列化和网络初始化这个动作只应该在 Spring 启动时做一次。2.2 选型理由为什么 Java 团队选 DJL 而不是自建 Python 推理服务很多人第一反应是AI 能力本来就是 Python 的生态为什么要在 Java 里硬做我的理由很简单如果你的团队全是 Java 开发、公司基础设施也围绕 JVM 建设那么单独为 AI 功能维护一个 Python 微服务、网络通信、模型部署流水线成本远高于在同一个进程里直接调 DJL。两者对比下来维度DJL 同进程集成独立 Python 推理服务部署产物一个 Spring Boot jarPython 环境 Web 服务 接口协议推理延迟无网络开销数据直接进引擎多一跳 HTTP/RPC类型安全输入输出强类型需要定义接口协议、异常处理运维负担跟随 Spring 生命周期需要独立监控、日志、升级流程模型生态需要转 TorchScript / ONNX原生 Python 模型直接跑选 DJL 的真实痛点也很明确训练生态比 Python 弱不少很多新论文的模型根本没有 DJL 实现。所以我的选型建议是——训练用 DJL 处理中小规模模型没问题超大规模模型我仍然建议训练在 Python 侧完成然后把模型导出成 TorchScript 或 ONNX部署推理交给 DJL 和 Spring。这也是 DJL 定位里最成熟的路径两边都不耽误。3. 在 Spring Boot 里把模型加载和推理接起来依赖、Bean 与接口3.1 Maven 依赖怎么加engine、native 与 model-zooDJL 的依赖结构比普通 Java 库要复杂一点核心原因是它有引擎层和 native 层。api是通用抽象pytorch-engine是引擎实现而 native 二进制通过pytorch-native-auto按平台分类器引入。如果漏了最后这个分类器依赖工程能编译过但一运行就报言「找不到 native 库」。我一般会在 pom 里这样组织方便统一管理版本properties djl.version0.21.0/djl.version !-- 按部署机器的 OS 和架构改 -- jni.classifierlinux-x86_64/jni.classifier /properties dependencies dependency groupIdai.djl/groupId artifactIdapi/artifactId version${djl.version}/version /dependency dependency groupIdai.djl/groupId artifactIdmodel-zoo/artifactId version${djl.version}/version /dependency dependency groupIdai.djl.pytorch/groupId artifactIdpytorch-engine/artifactId version${djl.version}/version /dependency dependency groupIdai.djl.pytorch/groupId artifactIdpytorch-native-auto/artifactId version${djl.version}/version classifier${jni.classifier}/classifier /dependency /dependenciesjni.classifier是最容易踩坑的地方本地开发往往在 Mac 上osx-aarch64测试环境是 Linuxlinux-x86_64打包时如果单台机器上只配了一个 classifier部署到另一平台就会启动失败。我会把它从 pom 里抽出来放到构建配置里按环境替换或者在部署文档里明确标注这台机器用什么架构。需要注意model-zoo并不是必须项。如果完全用自己的模型只引入api和pytorch-engine就够了model-zoo只是为了加载官方预训练模型时能找到模型清单。版本上DJL 的 API 在 0.20 到 0.22 之间有一些函数签名调整跨大版本升级时不要直接改版本号就完事要跑一遍测试用例。3.2 用 Criteria 加载模型并注册为 Spring Bean在 Spring 里管理 DJL 模型核心思路是把“加载一次、长期持有”的模型声明成Bean销毁时交给 Spring 调用close()。这样模型生命周期和 Spring 容器完全对齐服务重启时模型只会被加载一次不会因为每次请求都重新初始化而把接口拖慢。一个可以直接抄的配置类Configuration public class DjlModelConfig { Bean(destroyMethod close) public Model imageClassificationModel() throws ModelException, IOException { CriteriaImage, Classifications criteria Criteria.builder() .setTypes(Image.class, Classifications.class) .optApplication(Application.CV.IMAGE_CLASSIFICATION) .optArtifactId(resnet18) // 明确使用 CPU避免开发机没有 CUDA 时启动报错 .optDevice(Device.cpu()) .build(); return criteria.loadModel(); } }这里要重点看destroyMethod close这个属性。Spring 容器关闭时它会自动调用Model.close()释放原生内存和线程资源。如果你漏掉这个配置开发环境可能没什么感觉生产环境反复发布后就会出现堆外内存持续增长的问题——因为旧模型对象没有被正确回收其 native 资源。optDevice(Device.cpu())是我被坑过之后习惯性加上的开发机上没有 CUDA 的话不指定设备会默认尝试 GPU报错信息不够直观。线上有 GPU 时再把这里改成Device.gpu()。3.3 Controller 里做推理Predictor 每次新建不要在请求间共享模型是单例但 Predictor 绝对不能用单例。原因在于 Predictor 内部持有输入数据的中间状态多个线程同时对它调用predict会互相污染结果。我的习惯是把它封装在一个 Service 里每次调用都新建让 Controller 层不感知这些细节Service public class ClassifyService { private final Model model; public ClassifyService(Model model) { this.model model; } public Classifications classify(Image image) throws TranslateException { try (PredictorImage, Classifications predictor model.newPredictor()) { return predictor.predict(image); } } }Controller 只负责解析请求和转换输入格式RestController public class ClassifyController { private final ClassifyService classifyService; public ClassifyController(ClassifyService classifyService) { this.classifyService classifyService; } PostMapping(/classify) public MapString, Double classify(RequestParam(file) MultipartFile file) throws IOException, TranslateException { Image image ImageFactory.getInstance().fromInputStream(file.getInputStream()); Classifications result classifyService.classify(image); // 取 Top-3方便前端展示置信度 return result.topK(3).stream() .collect(Collectors.toMap( entry - entry.getKey(), entry - entry.getValue())); } }topK(3)拿到的列表顺序是从高到低直接用Collectors.toMap转成 JSON 输出。这里注意Classifications的toString已经很好看了但接口返回时我还是建议只输出 Top-N避免把一个几千类的全量概率都吐给前端。ImageFactory.getInstance().fromInputStream会读取完整图片字节流如果图片很大这个操作本身就有一定耗时。对于高并发的图片上传接口我会在接入层加一个文件大小上限校验防止大图把线程池堵死。4. 用 Spring 管训练流程数据集、训练循环与模型回存4.1 准备数据集ImageFolder 与目录结构约定DJL 的ImageFolder数据集约定非常直观一类一个子目录子目录名就是类别名。结构像/data/train/cat/xxx.jpg、/data/train/dog/xxx.jpg这样调用prepare()之后它会自动扫描子目录并建立类别索引。这个设计让训练数据集的组织和 Spring 工程的资源目录一样有章可循。构建训练数据集的代码Dataset trainingDataset ImageFolder.builder() // 指向训练数据根目录 .setRepositoryPath(Paths.get(/data/images/train)) // 只扫描一层子目录 .optMaxDepth(1) // 随机裁剪缩放兼顾数据增强 .addTransform(new RandomResizedCrop(112, 112)) // 转成 NDArray归一化也在这里做 .addTransform(new ToTensor()) .build(); trainingDataset.prepare();optMaxDepth(1)很关键它限制采样时只往下找一层子目录否则会把类别目录里的子目录也当成类别。RandomResizedCrop是训练集专用的增广方式验证集不应该用它验证集一般只做Resize和ToTensor。所以训练和验证要分别构建两个ImageFolder实例。prepare()会在第一次调用时扫描整个目录树并建立索引数据量大时耗时明显。这个动作不适合放在训练循环里反复执行我在 Spring 工程里会把它放到训练任务的初始化阶段只在任务启动时调用一次。4.2 构建网络与训练配置用 Trainer 跑训练循环DJL 的 Block API 长得很像 PyTorch 和 Keras 的混合体。一个简单的分类网络可以这样搭Block block new SequentialBlock() // 把 112x112x3 展平成一维向量 .add(Blocks.batchFlattenBlock(112 * 112 * 3)) .add(Linear.builder().setUnits(64).build()) .add(Activation::relu) .add(Linear.builder().setUnits(10).build());这是一个全连接网络适合快速验证流程是否通。真实任务里一般会换成卷积模块或直接用 DJL Model Zoo 里的残差网络做迁移学习但训练代码结构完全一样。注意最后输出 10 个单元对应 10 个类别这个数字要和数据集的类别数一致。训练配置用DefaultTrainingConfig把损失函数、优化器、验证数据集挂进去DefaultTrainingConfig config new DefaultTrainingConfig(new SoftmaxCrossEntropyLoss()) .optOptimizer(Optimizer.adam().optLearningRate(0.001f).build()) .optDevices(Device.cpu()) .optValidateDataset(validationDataset); // 每次训练都新建模型实例避免重复加载残留 try (Model model Model.newInstance(image-classifier)) { model.setBlock(block); try (Trainer trainer model.newTrainer(config)) { // 初始化权重需要明确输入形状 trainer.initialize(new Shape(1, 3, 112, 112)); // fit 内部会按 epoch 循环数据并在结束时调用 validate EasyTrain.fit(trainer, 10, trainingDataset); model.save(Paths.get(build/model), image-classifier); } }trainer.initialize(new Shape(1, 3, 112, 112))的1是 batch 维度DJL 在 initialize 时只看形状不看具体数据。EasyTrain.fit这个封装会替你做 epoch 循环和 batch 迭代如果配置里加了optValidateDataset它会在每个 epoch 结束时用验证集算一次准确率打印到日志里。训练超参数就两个方向学习率太大训练震荡太小收敛慢。我习惯先把optLearningRate放到 0.001 跑一个 epoch 看 loss 曲线不收敛再往下调一个量级。epoch 数不是越大越好后面验证集准确率不再上升时就该考虑提前停止。4.3 模型保存与加载闭环训练产物回到 Spring Beanmodel.save(Paths.get(build/model), image-classifier)会把网络结构和参数文件写到一个目录下。这个目录就是训练和推理之间的交接物我一般会把目录路径写进 Spring 的配置文件让加载模型的地方和训练产物的落点保持一致。从保存目录加载到一个新的 Spring Bean只需要把 Criteria 的加载来源从 Model Zoo 改成模型路径Bean(destroyMethod close) public Model trainedModel() throws ModelException, IOException { CriteriaImage, Classifications criteria Criteria.builder() .setTypes(Image.class, Classifications.class) .optModelPath(Paths.get(build/model/image-classifier)) .optTranslator(ImageTranslator.builder() .optResize(112, 112) .build()) .build(); return criteria.loadModel(); }这里有一个容器上下文的问题训练任务通常不会放在 Web 请求里跑因为训练耗时长、占用资源高一个请求把它启动起来接口会直接超时。我的做法是在 Spring Boot 启动阶段用一个独立的组件来触发训练训练完成后推理用的 Bean 再被注入到 Controller。整个链路是训练组件读配置里的数据路径和超参数 → 训练并保存模型训练完成后保存路径变成模型加载 Bean 的输入推理接口运行期间不关心模型是哪里来的只管调predict这个闭环的好处是模型更新只需要替换训练产物目录下的文件再重启服务训练和部署就完成了交接。5. 集成中的 5 个常见问题与排查从依赖冲突到内存泄漏5.1 启动报 UnsatisfiedLinkErrornative 库加载失败现象Spring Boot 启动时一直正常加载模型时突然抛UnsatisfiedLinkError提示找不到 jni 相关的符号。原因pytorch-native-auto的 classifier 和实际操作系统不匹配。最常见的是开发机是 Mac ARM打包的 classifier 是linux-x86_64部署到 Linux ARM 机器上直接失败。另一个原因是多引擎同时引入——既加了 PyTorch 又加了 ONNX Runtime 的 native两个引擎的 JNI 符号互相干扰。解决先确认部署环境架构再回看 pom 里的jni.classifier。我把这个值拆到环境变量里之后再没因为架构问题翻车过。多引擎场景下如果必须共存就给不同的引擎设置独立的 ClassLoader 隔离或者干脆只保留一个引擎。5.2 并发一上来推理结果变成乱序或直接报错现象单线程测试一切正常用压测工具跑 20 个并发线程结果出现IllegalStateException或者返回的类别跟输入图片对不上。原因典型的 Predictor 共享。某个同学把Predictor当成 Bean 注入到了 Service 里所有线程共用一个实例内部状态被互相覆盖。解决严格执行“Predictor 每次新建、用完即 close”。如果用ThreadLocal复用 Predictor一定要记得在线程池任务结束后清理否则线程长期存活时 Predictor 的 native 资源无法及时释放。最简单的排查方法在所有用到predict的地方搜一下除了newPredictor()有没有其他地方持有了 Predictor 对象的引用。5.3 本地 IDE 跑得好好的打 jar 部署后模型找不到现象java -jar启动后加载模型时抛FileNotFoundException但同一个构建产物在 IDE 里运行完全正常。原因Spring Boot 的 fat jar 把模型文件压缩在 jar 包里Paths.get(build/model)是文件系统路径根本访问不到 jar 内部资源。解决模型不打进 jar而是放到独立目录通过配置项指定绝对路径。如果必须打包进 jar加载前先用工具类把资源复制到临时目录再让 DJL 读取临时目录文件。经验是模型文件几百 MB打进 jar 会让启动时解压很久独立目录对后续模型更新也更友好。5.4 训练跑完内存不见回落多次训练后直接 OOM现象训练任务循环跑完应用还在运行但 JVM 堆外内存持续上升几次训练后容器直接 OOM。原因DJL 的 NDArray 和 Batch 对象都在堆外分配原生内存它们不归 JVM GC 管。训练循环里如果某个Batch没有显式关闭每一轮都会泄漏一部分原生内存。解决训练循环里对Batch使用 try-with-resources或者迭代完后手动调用batch.close()。我用EasyTrain.fit时也会在训练方法外层套 try-with-resources确保 Trainer、Model 的 close 一定执行。排查时可以开启 DJL 的 NDArray 泄漏检测日志它会告诉你哪条创建路径没有关闭。5.5 自训练模型部署后分类结果是一串数字而不是类别名现象用ImageFolder训练、保存、再加载的模型推理返回的 Top-3 是像0: 0.982这样的数字标签。原因DJL 在保存自定义模型时不会自动把类别名表写进模型文件。模型推理时只输出类别索引ImageTranslator找不到 synset就直接显示索引号。解决为模型配置一个自定义 Translator在toClassifications时用你训练时那份类别列表映射索引到类名。public class CustomImageTranslator extends ImageTranslator { private final ListString synset; public CustomImageTranslator(ListString synset) { super(ImageTranslator.builder().build()); this.synset synset; } Override public Classifications toClassifications(NDArray array) { NDArray probabilities array.softmax(0); ListString classNames new ArrayList(); for (int i 0; i synset.size(); i) { classNames.add(synset.get(i)); } return new Classifications(classNames, probabilities); } }这段代码的关键是把训练时的classNames顺序保存下来作为配置项传给 Translator。softmax(0)是把原始输出转成概率分布如果训练损失函数里已经带了 softmax这里要避免二次计算直接取原始数组。这个坑很容易被忽视因为模型 Zoo 里官方模型都自带 synset自训练模型不会自动带。6. 上线前该做的验证预热、并发压测与线程参数模型加载成功后第一次推理通常会比后续慢一个量级因为引擎懒加载算子和内存池。直接在线上让第一个用户承担这个延迟体验很差。我的做法是在 Spring 启动完成后主动做一次预热推理用一个固定的小图触发全部初始化路径Component public class ModelWarmupRunner implements ApplicationRunner { private final ClassifyService classifyService; public ModelWarmupRunner(ClassifyService classifyService) { this.classifyService classifyService; } Override public void run(ApplicationArguments args) throws Exception { Image placeholder ImageFactory.getInstance() .fromUrl(https://resources.djl.ai/images/0.png); classifyService.classify(placeholder); } }预热代码里随便传一张图就行目标是把Predictor.newPredictor、引擎初始化和内存分配全部触发一次。如果团队不方便访问外网图片就用代码生成一张纯色的小图效果完全相同。压测时格外注意 CPU 线程参数。DJL 的 PyTorch 引擎默认会占用机器的所有计算资源如果 Spring 服务同时还处理其他业务请求两者会抢 CPU导致接口响应时间抖动。我的习惯是通过配置把引擎的计算线程数显式设置成 CPU 核数的一半给业务线程池留出余地。这个参数不调对压测曲线会出现神奇的毛刺看起来像玄学其实是底层算子把线程吃满了。并发验证也有一个小技巧先用 20 线程跑 100 次请求观察结果是否稳定、响应时间是否平滑再逐步加大到 50、100 线程。如果并发上去之后出现超时增长但不是错误说明每线程新建 Predictor 的逻辑是合理的如果直接报错回去查 Predictor 或者 native 库的线程模型。我习惯把每次推理耗时记录到日志里至少保留 p95 和 p99 两个指标DJL 推理很多时候受制于 CPU 调度而不是模型计算没有指标就看不出来。最后说一个我自己的教训第一次做 DJL 集成时我把 Predictor 当成普通 Service 顺手注册成了Bean压测一上并发立刻翻车排查了大半天。从那以后我养成了一个习惯——每个 DJL 对象都用 try-with-resources 管起来并且在代码注释里写明生命周期。DJL 这种东西显式管理资源会给你省下很多半夜排查的时间。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Unity实时摄像头画面处理:RenderTexture管线与Shader后处理实战

Unity实时摄像头画面处理:RenderTexture管线与Shader后处理实战

做Unity实时摄像头画面处理这个需求,我猜你大概率是被"实时"这两个字折磨了很久才搜到这里的。这个项目我前前后后折腾过三轮,从最初简单的USB摄像头画面采集,到后来接工业相机和RTSP网络流,再到把画面处理成美颜、风格…

2026/10/12 6:01:32 阅读更多 →
SVM三分类实战:从OvO/OvR策略到RBF核调参与避坑指南

SVM三分类实战:从OvO/OvR策略到RBF核调参与避坑指南

简介:一份基于MATLAB的SVM三分类完整实现,面向机器学习初学者、算法研究者以及需要在不平衡或多类别数据上快速验证分类效果的工程人员。压缩包仅有6个文件,包括5个m脚本与1份iris.data标准鸢尾花数据集;其中训练、分类、核函数、…

2026/10/12 6:01:32 阅读更多 →
嵌入式板级调试第六天:信号验证的坑与套路

嵌入式板级调试第六天:信号验证的坑与套路

如果你正在调一块嵌入式板子,并且到了项目的第六天,你会发现“信号相关功能验证”这几个字的分量很重。前面几天,你可能已经把板子点亮了:串口能打印、LED能闪烁、芯片能启动,一切看起来挺正常。但真正到了信号验证这一…

2026/10/12 6:01:32 阅读更多 →

最新新闻

C# WinForm自定义标题栏颜色与边框重绘实战

C# WinForm自定义标题栏颜色与边框重绘实战

简介:本资源是一份面向C# WinForm开发者的进阶实践方案,聚焦于突破系统默认限制、实现标题栏与边框的深度自定义绘制。针对希望提升桌面应用视觉表现力的中高级开发者,提供基于Windows API消息拦截(WM_NCPAINT)与非客户…

2026/10/12 6:42:54 阅读更多 →
为什么我选择Locust做性能测试:从协程并发模型到安装实战

为什么我选择Locust做性能测试:从协程并发模型到安装实战

1. 为什么性能测试工具那么多,我最终选了Locust聊到性能测试,很多人第一反应是打开JMeter的图形界面,拖几个线程组,配个聚合报告,一套流程走得行云流水。这是国内绝大多数团队的做法,没什么问题&#xff0c…

2026/10/12 6:42:54 阅读更多 →
SpringBoot+Vue全栈实战:七彩云南文旅网站管理系统开发

SpringBoot+Vue全栈实战:七彩云南文旅网站管理系统开发

做这个项目之前,我对文旅类网站的认知还停留在“景点照片轮播门票价格展示”的静态页面层面。真正拿到“基于SpringBootVue的七彩云南文化旅游网站管理系统”这个需求之后才发现,文化旅游网站管理系统和电商系统、企业官网完全不是一个量级的东西——它既…

2026/10/12 6:42:54 阅读更多 →
Edge打不开提示“并行配置不正确”?从SxS机制到VC++运行库修复指南

Edge打不开提示“并行配置不正确”?从SxS机制到VC++运行库修复指南

当你双击Edge浏览器图标,等来的不是熟悉的起始页,而是一个冷冰冰的系统弹窗:“应用程序无法启动,因为应用程序的并行配置不正确。有关详细信息,请参阅应用程序事件日志,或使用命令行sxstrace.exe工具。”先…

2026/10/12 6:42:54 阅读更多 →
低轨卫星OFDM信号检测MATLAB仿真方法

低轨卫星OFDM信号检测MATLAB仿真方法

简介:本资源是一份面向通信工程与信号处理方向研究生的低轨卫星OFDM通信链路信号检测方法研究开题报告,聚焦于解决低轨卫星动态信道下OFDM信号检测精度低、抗多普勒频移与多径干扰能力弱等关键技术难题。文档系统梳理了OFDM检测原理、低轨信道特性建模、…

2026/10/12 6:42:54 阅读更多 →
爬虫URL去重实战:从set到布隆过滤器与Redis方案

爬虫URL去重实战:从set到布隆过滤器与Redis方案

做爬虫做了这么多年,我一直觉得URL去重是那种"看起来简单,做起来全是坑"的环节。前阵子帮朋友排查一个采集任务,跑了一整夜,第二天看数据库,十二万条记录里将近四万条是重复的。查日志发现罪魁祸首特别蠢&am…

2026/10/12 6:41:53 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →