Deep Java Library(六)DJLServing自定义模型,自定义Translator注意事项

news2024/10/16 20:23:20

DJLServing自定义模型中自定义Translator注意事项需要仔细读一下DJLServing源码中的ServingTranslatorFactory类,,一开始不了解以为DJLServing选择Translator像玄学,后来看了像迷宫一样ServingTranslatorFactory类大致明白了,以下是源码注释版,还有一个整理的流程图。
在这里插入图片描述

/*
 * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
 * with the License. A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 */
import ai.djl.Application;
import ai.djl.Model;
import ai.djl.modality.Input;
import ai.djl.modality.Output;
import ai.djl.modality.cv.translator.ImageClassificationTranslator;
import ai.djl.modality.cv.translator.ImageServingTranslator;
import ai.djl.translate.*;
import ai.djl.util.ClassLoaderUtils;
import ai.djl.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

class ServingTranslatorFactory implements TranslatorFactory {

    //日志打印
    private static final Logger logger = LoggerFactory.getLogger(ServingTranslatorFactory.class);

    //返回只有一个固定元素的SET,约束模型的输入,输出类型
    @Override
    public Set<Pair<Type, Type>> getSupportedTypes() {
        return Collections.singleton(new Pair<>(Input.class, Output.class));
    }

    //工厂实例化方法
    @Override
    @SuppressWarnings("unchecked")
    public <I, O> Translator<I, O> newInstance(
            Class<I> input, Class<O> output, Model model, Map<String, ?> arguments)
            throws TranslateException {

        //如果输出和输出不在支持的范围内直接抛出异常
        if (!isSupported(input, output)) {
            throw new IllegalArgumentException("Unsupported input/output types.");
        }

        //获取model的路径
        Path modelDir = model.getModelPath();
        //获取serving.properties里面的translatorFactory参数
        String factoryClass = ArgumentsUtil.stringValue(arguments, "translatorFactory");
        //如果translatorFactory参数不为null且长度不为0
        if (factoryClass != null && !factoryClass.isEmpty()) {
            //直接加载工厂类
            TranslatorFactory factory = loadTranslatorFactory(factoryClass);
            //如果工厂类加载成功并且工厂类支持要去的输入输出
            if (factory != null && factory.isSupported(input, output)) {
                //打印日志
                logger.info("Using TranslatorFactory: {}", factory.getClass().getName());
                //将工厂类实例化返回
                return factory.newInstance(input, output, model, arguments);
            }
        }

        //如果上面没有匹配上
        //获取serving.properties里面的translator参数
        String className = (String) arguments.get("translator");

        //获取model目录下的libs目录
        Path libPath = modelDir.resolve("libs");
        //如果这个libs目录不存在
        if (!Files.isDirectory(libPath)) {
            //那就找lib目录
            libPath = modelDir.resolve("lib");
            //如果lib目录也没有那就走loadDefaultTranslator(arguments)这个方法,加载默认的Translator
            if (!Files.isDirectory(libPath) && className == null) {
                return (Translator<I, O>) loadDefaultTranslator(arguments);
            }
        }
        //如果model目录下的libs目录存在那就加载class
        ServingTranslator translator = findTranslator(libPath, className);
        //如果加载上了
        if (translator != null) {
            //设置translator的参数
            translator.setArguments(arguments);
            //打印日志
            logger.info("Using translator: {}", translator.getClass().getName());
            //直接返回translator
            return (Translator<I, O>) translator;
        } else if (className != null) {
            //如果加载失败抛出异常
            throw new TranslateException("Failed to load translator: " + className);
        }
        //实在是找不到就走loadDefaultTranslator(arguments)这个方法,加载默认的Translator
        return (Translator<I, O>) loadDefaultTranslator(arguments);
    }

    private ServingTranslator findTranslator(Path path, String className) {
        //找目录里面的classes目录
        Path classesDir = path.resolve("classes");
        //把java编译成classes
        ClassLoaderUtils.compileJavaClass(classesDir);
        //返回出去Translator,该类必须是ServingTranslator的实现类,因为会强制转换成ServingTranslator在子类
        return ClassLoaderUtils.findImplementation(path, ServingTranslator.class, className);
    }

    private TranslatorFactory loadTranslatorFactory(String className) {
        try {
            //通过类名加载该类
            Class<?> clazz = Class.forName(className);
            //将该类强制转换成TranslatorFactory的子类
            Class<? extends TranslatorFactory> subclass = clazz.asSubclass(TranslatorFactory.class);
            //加载该类的构造方法
            Constructor<? extends TranslatorFactory> constructor = subclass.getConstructor();
            //构造该类返回实例
            return constructor.newInstance();
        } catch (Throwable e) {
            //捕获异常
            logger.trace("Not able to load TranslatorFactory: " + className, e);
        }
        return null;
    }

    private Translator<Input, Output> loadDefaultTranslator(Map<String, ?> arguments) {
        //获取serving.properties里面的application参数
        String appName = ArgumentsUtil.stringValue(arguments, "application");
        //如果不为空
        if (appName != null) {
            Application application = Application.of(appName);
            //如果是cv/image_classification
            if (application == Application.CV.IMAGE_CLASSIFICATION) {
                //那就加载ImageClassificationTranslator这个玩意
                return getImageClassificationTranslator(arguments);
            }
        }
        //否则的化就加载NoopServingTranslatorFactory这个玩意
        NoopServingTranslatorFactory factory = new NoopServingTranslatorFactory();
        //最后返回的是NoopServingTranslator这个玩意
        return factory.newInstance(Input.class, Output.class, null, arguments);
    }

    private Translator<Input, Output> getImageClassificationTranslator(Map<String, ?> arguments) {
        //返回ImageServingTranslator的实例
        return new ImageServingTranslator(ImageClassificationTranslator.builder(arguments).build());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/992516.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP-写了一个FUNCTION,用于读取订单中,指定工序的状态。

需求 在开发一个涉及工序的Report的过程中发现,SAP仅提供了Function去获取订单的状态,没有提供获取订单工序状态的Function。考虑到后续开发的过程中,还需要复用到这个功能,于是打算按这个需求去开发一个Function,传入AFVC表的主键,返回的是把该工序的全部已激活的状态,…

八 动手学深度学习v2 ——卷积神经网络之卷积+填充步幅+池化+LeNet

目录 1. 图像卷积总结2. 填充和步幅 padding和stride3. 多输入多输出通道4. 池化层5. LeNet 1. 图像卷积总结 二维卷积层的核心计算是二维互相关运算。最简单的形式是&#xff0c;对二维输入数据和卷积核执行互相关操作&#xff0c;然后添加一个偏置。核矩阵和偏移是可学习的参…

储能直流侧计量表DJSF1352

安科瑞 华楠 具有CE/UL/CPA/TUV认证 DJSF1352-RN导轨式直流电能表带有双路直流输入&#xff0c;主要针对电信基站、直流充电桩、太阳能光伏等应用场合而设计&#xff0c;该系列仪表可测量直流系统中的电压、电流、功率以及正反向电能等。在实际使用现场&#xff0c;即可计量总…

概念解析 | U-Net:医学图像分割的强大工具

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:U-Net。 U-Net:医学图像分割的强大工具 U-Net Architecture Explained - GeeksforGeeks 在医学图像分析的领域,一种称为U-Net的深度学习模型已经成为了一个标准工具。U-Net…

牛客练习赛115 A Mountain sequence

题目&#xff1a; 样例&#xff1a; 输入 3 5 1 2 3 4 5 3 3 3 3 3 1 2 1 输出 16 1 3 思路&#xff1a; 依据题意&#xff0c;再看数据范围&#xff0c;可以知道暴力肯定是不可能了&#xff0c;然后通过题目意思&#xff0c;我们可以排列模拟一下&#xff0c;这里排列所得结…

Decord库快速抽帧

Decord比Opencv块6倍&#xff01;&#xff01; 1. 使用教程 读取视频 # 1、读取使用 from decord import VideoReader from decord import cpu, gpuvr VideoReader(tiny-Kinetics-400\\abseiling\\_4YTwq0-73Y_000044_000054.mp4, ctxcpu(0))print(video frames:, len(vr)…

ArcGIS API for JavaScript 4.x 实现动态脉冲效果

1. 设计思路 主要通过定时刷新&#xff0c;每一次的脉冲渲染圈不停的放大&#xff0c;并且透明度缩小&#xff0c;直到达到一定的大小再退回0。 2. 实现代码 import MapView from "arcgis/core/views/MapView"; import GraphicsLayer from "arcgis/core/laye…

数学建模B多波束测线问题B

数学建模多波束测线问题 1.问题重述&#xff1a; 单波束测深是一种利用声波在水中传播的技术来测量水深的方法。它通过测量从船上发送声波到声波返回所用的时间来计算水深。然而&#xff0c;由于它是在单一点上连续测量的&#xff0c;因此数据在航迹上非常密集&#xff0c;但…

云备份——服务端客户端联合测试

一&#xff0c;准备工作 服务端清空备份文件信息、备份文件夹、压缩文件夹 客户端清空备份文件夹 二&#xff0c;开始测试 服务端配置文件 先启动服务端和客户端 向客户端指定文件夹放入稍微大点的文件&#xff0c;方便后续测试断点重传 2.1 上传功能测试 客户端自动上传成功…

【Altium Designer】AD20教程,实战,作图(一)

文章目录 完整制图方法1、建立一个完整的PCB工程&#xff0c;需要有sch文件、pcb文件、schlib文件、pcblib文件&#xff0c;后面两个不是必须的&#xff0c;后面两个用来自己创建库里面没有的东西。2、这个时候就可以画 原理图 ,这里我提一下库这个东西。3、画原理图4、编译原理…

系统架构设计师(第二版)学习笔记----计算机语言

【原文链接】系统架构设计师&#xff08;第二版&#xff09;学习笔记----计算机语言 文章目录 一、计算机语言的组成1.1 计算机语言的分类 二、机器语言2.1 机器语言指令信息2.2 机器语言指令格式的种类 三、汇编语言3.1 汇编语言中语句种类3.2 汇编语言指令和伪指令的语句格式…

数字孪生的深海迷航

上世纪70年代&#xff0c;美国宇航局&#xff08;NASA&#xff09;筹划构建复杂的大型载人航天器。当时科学家们发现&#xff0c;航天任务进行当中&#xff0c;航天器的维护和修理面临着环境复杂、危险性高、故障不易排查等问题。 与其“盲人摸象”式的找故障&#xff0c;不如干…

WRF DA环境需求、系统安装、调试与运行丨WRF DA变分资料同化、WRF DA混合同化新方法

目录 专题一 资料同化的基本理论与方法 专题二 WRF DA的环境需求、系统安装、调试与运行 专题三 观测资料与质量控制 专题四 WRF DA同化系统的配置、背景误差的构造 专题五 WRF DA变分资料同化、WRF DA混合同化新方法 专题六 变分同化的单点试验、混合同化的单点试验 专…

机器学习——Logistic Regression

0、前言&#xff1a; Logistic回归是解决分类问题的一种重要的机器学习算法模型 1、基本原理&#xff1a; Logistic Regression 首先是针对二分类任务提出的一种分类方法如果将概率看成一个数值属性&#xff0c;则二元分类问题的概率预测就可以转化为一个回归问题。这种思路最…

B Antiamuny wants to leaern binary search again

题目&#xff1a; C/C: int f(int l,int r,int x) { // l < x < rint cnt 0;while(l < r) {cnt;int mid (l r) / 2;if (mid x) break;if (mid < x) l mid 1;else r mid - 1;}return cnt; } 样例&#xff1a; 输入 5 3 7 2 6 12 2 2 10 3 6 14 8 5 8 1 输…

java实现调用百度地图

这里使用的springbootthymeleaf实现&#xff0c;所以需要有springboot技术使用起来更方便 当然&#xff0c;只使用html加js也可以实现&#xff0c;下面直接开始 首先我们需要去百度地图注册一个AK&#xff08;百度地图开放平台 | 百度地图API SDK | 地图开发&#xff09; 找到左…

神经网络与强化学习:揭示AI的超能力

文章目录 神经网络&#xff1a;模拟人脑的工具强化学习&#xff1a;通过试错学习结合神经网络和强化学习价值网络策略网络结合训练 应用领域游戏机器人控制金融交易 未来趋势自动化和自主系统个性化和自适应系统跨学科研究 结论 &#x1f389;欢迎来到AIGC人工智能专栏~神经网络…

谷粒商城----缓存与分布式锁

1、缓存使用 为了系统性能的提升&#xff0c;我们一般都会将部分数据放入缓存中&#xff0c;加速访问。而 db 承担数据落盘工作。 哪些数据适合放入缓存&#xff1f;  即时性、数据一致性要求不高的  访问量大且更新频率不高的数据&#xff08;读多&#xff0c;写少&…

day3_C++

day3_C 思维导图用C的类完成数据结构 栈的相关操作用C的类完成数据结构 循环队列的相关操作 思维导图 用C的类完成数据结构 栈的相关操作 stack.h #ifndef STACK_H #define STACK_H#include <iostream> #include <cstring>using namespace std;typedef int datat…

SplitMask:大规模数据集是自我监督预训练的必要条件吗?

自监督预训练需要大规模数据集吗?这是2021年发布的一篇论文&#xff0c;它在自监督预训练场景中使用小数据集&#xff0c;如Stanford Cars, Sketch或COCO&#xff0c;它们比ImageNet小几个数量级。并提出了一种类似于BEiT的去噪自编码器的变体SplitMask&#xff0c;它对预训练…