PyTorch框架的Yolov5移植–寒武纪开发者社区

本文对开源yolov5s模型进行寒武纪平台的移植

整个移植过程分为模型结构转换、添加后处理算子框架代码、模型量化、在线推理和离线推理共五个步骤。

对于原始Yolov5网络的后处理部分的逻辑,Cambricon-PyTorch直接使用一个大的BANGC算子完成后处理的计算,需要对原生的pytorch网络进行修改,将后处理部分的整体计算换成BANGC算子。

具体做法为是将yololayer层替换成了yolov5_detection_output,把三个yololayer的输入传给了yolov5_detection_output。修改部分在yolo.py中,如下:

ifx[0].device.type=='mlu':

foriinrange(self.nl):

x[i]=self.m[i](x[i])#conv

y=x[i].sigmoid()

output.append(y)

detect_out=torch.ops.torch_mlu.yolov5_detection_output(output[0],output[1],output[2],

self.anchors_list,self.nc,self.num_anchors,

self.img_h,self.img_w,self.conf_thres,self.iou_thres,self.maxBoxNum)

returndetect_out

ifx[0].device.type=='cpu':

z=[]

bs,_,ny,nx=x[i].shape#x(bs,255,20,20)tox(bs,3,20,20,85)

x[i]=x[i].view(bs,self.na,self.no,ny,nx).permute(0,1,3,4,2).contiguous()

ifnotself.training:#inference

ifself.grid[i].shape[2:4]!=x[i].shape[2:4]:

self.grid[i]=self._make_grid(nx,ny).to(x[i].device)

y[...,0:2]=(y[...,0:2]*2.-0.5+self.grid[i].to(x[i].device))*self.stride[i]#xy

y[...,2:4]=(y[...,2:4]*2)**2*self.anchor_grid[i]#wh

z.append(y.view(bs,-1,self.no))

returnxifself.trainingelsetorch.cat(z,1)

在第一步中我们使用了BANGC编写的Yolov5Detection算子替换掉了原始的后处理逻辑。为了保证能够正确调用到这个算子,需要将该Yolov5Detection算子集成到框架中。

共分成两步:先将算子集成到CNPlugin中,然后将CNPlugin算子集成到Cambricon-Pytorch。该算子的实现与集成到CNPlugin会在另一个教程中详细介绍,在这里只介绍将该算子集成到CambriconPytorch这一步骤。

-name:yolov5_detection_output//算子名称

use_mlu_dispatcher:custom//分发类型,unboxed_only为标准化算子,custom为客制化算子

derived_type:cnml//派生类型

schema_string:torch_mlu::yolov5_detection_output//用于算子注册

arguments://参数

-name:alpha_data//参数名称

type:constat::Tensor&//参数类型

-name:beta_data

type:constat::Tensor&

-name:gamma_data

-name:anchor_data

type:torch::List

-name:num_classes

type:int64_t

-name:num_anchors

-name:img_height

-name:img_width

-name:conf_thres

type:double

-name:nms_thres

-name:maxBoxNum

type:int64_treturn_type:at::Tensor//函数返回类型

2)添加OpMethods基类中的CPU实现。

//op_methods.h

virtualat::Tensoryolov5_detection_output(constat::Tensor&alpha_data,constat::Tensor&beta_data,constat::Tensor&gamma_data,torch::Listanchor_data,int64_tnum_classes,int64_tnum_anchors,int64_timg_height,int64_timg_width,doubleconf_thres,doublenms_thres,int64_tmaxBoxNum);

//op_methods.cpp因为在这里并没有添加CPU实现,直接抛出异常

at::TensorOpMethods::yolov5_detection_output(

constat::Tensor&alpha_data,constat::Tensor&beta_data,

constat::Tensor&gamma_data,torch::Listanchor_data,

int64_tnum_classes,int64_tnum_anchors,int64_timg_height,int64_timg_width,

doubleconf_thres,doublenms_thres,int64_tmaxBoxNum){

//Todo:cpukernel

throwstd::invalid_argument("TodoforCPU");

3)添加wrapper

推理算子或训练算子会优先分发到wrapper中。wrapper是对算子kernel的封装,每个算子对应一个wrapper。根据模板生成的wrapper头文件cnml_kernel.h,添加wrapper的实现。

//cnml_kernel.h

at::Tensorcnml_yolov5_detection_output(constat::Tensor&alpha_data,constat::Tensor&beta_data,constat::Tensor&gamma_data,torch::Listanchor_data,int64_tnum_classes,int64_tnum_anchors,int64_timg_height,int64_timg_width,doubleconf_thres,doublenms_thres,int64_tmaxBoxNum);

//yolov5_detection_output.cpp

at::Tensorcnml_yolov5_detection_output(constat::Tensor&alpha_data,

constat::Tensor&beta_data,

constat::Tensor&gamma_data,

torch::Listanchor_data,

int64_tnum_classes,

int64_tnum_anchors,

int64_timg_height,

int64_timg_width,

doubleconf_thres,

doublenms_thres,

int64_tmaxBoxNum){

autoalpha_new=alpha_data;

autobeta_new=beta_data;

autogamma_new=gamma_data;

boolcast_fp32_fp16=(toCnmlDataType(alpha_data.dtype())==CNML_DATA_FLOAT32);

if(cast_fp32_fp16){

alpha_new=cnml_cast_internal(alpha_new,CNML_CAST_FLOAT32_TO_FLOAT16);

beta_new=cnml_cast_internal(beta_new,CNML_CAST_FLOAT32_TO_FLOAT16);

gamma_new=cnml_cast_internal(gamma_new,CNML_CAST_FLOAT32_TO_FLOAT16);

}

returncnml_yolov5_detection_output_internal(alpha_new,

beta_new,

gamma_new,

anchor_data,

num_classes,

num_anchors,

img_height,

img_width,

conf_thres,

nms_thres,

maxBoxNum);

4)添加kernel

Wrapper中通过调用kernel实现算子功能。算子的具体实现主要通过调用CNML库来完成。以下是CNML库的简要逻辑。

//cnml_internal.h

at::Tensorcnml_yolov5_detection_output_internal(constat::Tensor&alpha_data,

int64_tmaxBoxNum);

//yolov5_detection_output_internal.cpp

intbatch_size=alpha_data.size(0);

intinputNum=3;

intoutput_num=2;

intmaskGroupNum=3;

intclassNum=num_classes;

intmaxbox_num=maxBoxNum;

intnet_w=img_width;

intnet_h=img_height;

floatconfidence_thresh=static_cast(conf_thres);

floatnms_thresh=static_cast(nms_thres);

cnmlTensor_tcnml_input_ptr[3];

cnmlTensor_tcnml_output_ptr[2];

//prepareinputcnmltensor

auto*alpha_impl=getMluTensorImpl(alpha_data);

autoalpha_cnml=alpha_impl->CreateCnmlTensor(CNML_TENSOR,

toCnmlDataType(alpha_data.dtype()));

auto*beta_impl=getMluTensorImpl(beta_data);

autobeta_cnml=beta_impl->CreateCnmlTensor(CNML_TENSOR,

toCnmlDataType(beta_data.dtype()));

auto*gamma_impl=getMluTensorImpl(gamma_data);

autogamma_cnml=gamma_impl->CreateCnmlTensor(CNML_TENSOR,

toCnmlDataType(gamma_data.dtype()));

autooutput=at::empty({batch_size,maxbox_num*7+64,1,1},

alpha_data.options());

auto*output_impl=getMluTensorImpl(output);

autooutput_cnml=output_impl->CreateCnmlTensor(CNML_TENSOR,

toCnmlDataType(output.dtype()));

//prepareinputcnmltensorformulticore

intbuf_size=1024*(alpha_data.size(2)*alpha_data.size(3)+

beta_data.size(2)*beta_data.size(3)+

gamma_data.size(2)*gamma_data.size(3));

autotemp_buf=at::empty({batch_size,buf_size,1,1},alpha_data.options());

auto*temp_buf_impl=getMluTensorImpl(temp_buf);

autotemp_buf_cnml=temp_buf_impl->CreateCnmlTensor(CNML_TENSOR,

toCnmlDataType(temp_buf.dtype()));

//EndtheexecutionflowifnotMLUdevice

CHECK_MLU_DEVICE(output);

cnml_input_ptr[0]=alpha_cnml;

cnml_input_ptr[1]=beta_cnml;

cnml_input_ptr[2]=gamma_cnml;

cnml_output_ptr[0]=output_cnml;

cnml_output_ptr[1]=temp_buf_cnml;

//prepareh_arr

std::vectorh_arr_data(64,1);

h_arr_data[0]=alpha_data.size(2);

h_arr_data[1]=beta_data.size(2);

h_arr_data[2]=gamma_data.size(2);

inth_data[]={h_arr_data[0],h_arr_data[1],h_arr_data[2]};

//preparew_arr

std::vectorw_arr_data(64,1);

w_arr_data[0]=alpha_data.size(3);

w_arr_data[1]=beta_data.size(3);

w_arr_data[2]=gamma_data.size(3);

intw_data[]={w_arr_data[0],w_arr_data[1],w_arr_data[2]};

//preparebias_arr

std::vectorbias_arr_data(64,1.0);

floatbias_data[64];

for(inti=0;i

bias_arr_data[i]=(float)anchor_data[i];

bias_data[i]=bias_arr_data[i];

cnmlPluginYolov5DetectionOutputOpParam_tYolov5params;

TORCH_CNML_CHECK(cnmlCreatePluginYolov5DetectionOutputOpParam(&Yolov5params,

batch_size,

inputNum,

classNum,

maskGroupNum,

maxbox_num,

net_w,

net_h,

confidence_thresh,

nms_thresh,

GET_CORE_VERSION,

w_data,

h_data,

bias_data));

cnmlBaseOp_tyolov5_op;

TORCH_CNML_CHECK(cnmlCreatePluginYolov5DetectionOutputOp(&yolov5_op,

Yolov5params,

cnml_input_ptr,

cnml_output_ptr));

//returntoJITifrunningmodeisfuse

CHECK_RETURN_TO_FUSE(yolov5_op,output);

//getqueueandfunc_param

cnrtInvokeFuncParam_tfunc_param;

staticu32_taffinity=0x01;

intdata_parallelism=1;

func_param.affinity=&affinity;

func_param.data_parallelism=&data_parallelism;

func_param.end=CNRT_PARAM_END;

autoqueue=getCurQueue();

//compileallops

TORCH_CNML_CHECK(cnmlCompileBaseOp(yolov5_op,

GET_CORE_NUMBER));

void*input_addrs[3];

void*output_addrs[2];

input_addrs[0]=alpha_impl->raw_mutable_data();

input_addrs[1]=beta_impl->raw_mutable_data();

input_addrs[2]=gamma_impl->raw_mutable_data();

output_addrs[0]=output_impl->raw_mutable_data();

output_addrs[1]=temp_buf_impl->raw_mutable_data();

//computeoperator

TORCH_CNML_CHECK(cnmlComputePluginYolov5DetectionOutputOpForward(yolov5_op,

input_addrs,

3,

output_addrs,

2,

&func_param,

queue));

syncQueue(queue);

TORCH_CNML_CHECK(cnmlDestroyPluginYolov5DetectionOutputOpParam(&Yolov5params));

TORCH_CNML_CHECK(cnmlDestroyBaseOp(&yolov5_op));

returnoutput;

5)重新编译Cambricon-Pytorch

上述步骤操作完,重新编译CambriconPytorch,进入python环境确认是否集成成功,如下:

Python3.5.2(default,Nov122018,13:43:14)

[GCC5.4.020160609]onlinux

Type"help","copyright","credits"or"license"formoreinformation.

>>>importtorch

>>>importtorch_mlu

CNML:7.7.0a414883

CNRT:4.6.0e158c88

>>>torch.ops.torch_mlu.yolov5_detection_output

为什么要量化:量化是将float32的模型转换为int8/int16的模型,可以保证计算精度在目标误差范围内的情况下,显著减少模型占用的存储空间和带宽,加速推理;比如int8模型是指将数值以有符号8位整型数据保存,并提供int8定点数的指数position和缩放因子scale,因此int8模型中每个8位整数i表示的实际值为:value=(i*2^position)/scale。设备在进行在线推理和生成离线模型时仅支持输入量化后的模型。

参数含义:

其中qconfig_spec包括:{‘iteration’:1,‘use_avg’:False,‘data_scale’:1.0,‘mean’:[0,0,0],‘std’:[1,1,1],‘firstconv’:True,‘per_channel’:False}

参考代码:

parser=argparse.ArgumentParser()

parser.add_argument('--cfg',type=str,default='yolov5s.yaml',help='model.yaml')

parser.add_argument('--device',default='cpu',help='cudadevice,i.e.0or0,1,2,3orcpu')

opt=parser.parse_args()

#获取yolov5网络文件

net=yolo.get_model(opt)

#在这里设置firstconv参数为False,因为该模型首层为focus算子,非卷积,无法开启first_conv

qconfig={'iteration':1,'use_avg':False,'data_scale':1.0,'firstconv':False,'per_channel':False}

#调用量化接口

quantized_net=mlu_quantize.quantize_dynamic_mlu(net.float(),qconfig_spec=qconfig,dtype='int8',gen_quant=True)

#设置为推理模式

quantized_net=quantized_net.eval().float()

#读取图片做预处理

img_mat=Image.open("./images/image.jpg")

ifimg_mat.mode!='RGB':

img_mat=img_mat.convert('RGB')

crop=640

resize=640

transform=transforms.Compose([

transforms.Resize(resize),

transforms.CenterCrop(crop),

transforms.ToTensor(),

])

img=transform(img_mat)

im_tensor=torch.unsqueeze(img,0)

im_tensor=im_tensor.float()

#推理生成量化值

quantized_net(im_tensor)

#保存量化后的模型

torch.save(quantized_net.state_dict(),'./yolov5s_int8.pt')

操作步骤:对步骤2生成的量化后的yolov5s_int8.pt进行在线推理测试。对图片进行推理,画出目标框和标注置信度。在yolov5_pytorch_demo/quantize_online目录中,示例如下:

1)逐层模式pythondetect.py

推理后的图片存储在./results目录下

推理过程:

融合模式:被融合的多个层作为单独的运算(单个Kernel)在MLU上运。根据络中的层是否可以被融合,络被拆分为若个络段。MLU与CPU间的数据拷只在各个络之间发。

逐层模式:逐层模式中,每层的操作都作为单独的运算(单个Kernel)在MLU上运,可以将每层结果导出到CPU上,便进调试。

一般来说,在线逐层模式更适用于调试环节,在线融合模式可以查看网络融合情况;

主要步骤:

1)设置:torch.set_grad_enabled(False)#注意:在运行MLU推理融合模式时,这个条件是必须要设置的。

2)获取模型加载权重:

4)如果要运行在线融合模式,需要在运行前向过程前调用jit.trace()接口生成静态图。首先会对整个网络运行一遍逐层模式,同时构建一个静态图;然后对静态图进行优化(包括去除冗余算子、小算子融、数据块复用等)得到一个优化后的静态图;之后会根据输入数据的设备类型进行基于设备的优化,生成针对当前设备的指令:

5)最后根据推理结果为图片加框和标记置信度

parser.add_argument('--jit',type=bool,help='fusion',default=False)

parser.add_argument('--save',type=bool,default=False,help='selectionofsave*.cambrcion')

#获取yolov5网络并加载量化后的权重

net=yolo.get_empty_model(opt)

quantized_net=torch_mlu.core.mlu_quantize.quantize_dynamic_mlu(net)

state_dict=torch.load('yolov5s_int8.pt')

quantized_net.load_state_dict(state_dict,strict=False)

#转移到MLU上进行推理

device=ct.mlu_device()

quantized_net.to(ct.mlu_device())

#读取图片

img_mat=cv2.imread('images/image.jpg')

#调用预处理函数做预处理

img=letter_box(img_mat)

#设置融合模式,save选项表示是否生成离线模型,因为在进行在线融合推理时,可以生成离线模型

ifopt.jit:

ifopt.save:

ct.save_as_cambricon('yolov5s')

torch.set_grad_enabled(False)

ct.set_core_number(4)

trace_input=torch.randn(1,3,640,640,dtype=torch.float)

trace_input=trace_input.to(ct.mlu_device())

quantized_net=torch.jit.trace(quantized_net,trace_input,check_trace=False)

#推理

detect_out=quantized_net(img.to(ct.mlu_device()))

#关闭生成离线模型

ct.save_as_cambricon("")

detect_out=detect_out.to(torch.device('cpu'))

#为原图添加框、检测类别和置信度

box_result=get_boxes(detect_out)

draw_boxes(box_result)

注意:原始的yolov5网络可以对输入的图片做自适应的预处理,使预处理后的图片可以有不同的大小。而在当前demo中,为了能够满足在线融合推理和离线推理必须是固定大小的要求,将预处理都改成了固定大小为640*640。

1)生成离线模型

操作步骤:

生成离线模型与在线推理代码相似,在yolov5_pytorch_demo/quantize_online目录中,示例如下:

pythondetect.py--jitTrue--saveTrue

会在当前目录生成离线模型yolov5s.cambricon和离线模型信息文件yolov5s.cambricon_twins

2)离线推理

对一张图片进行离线推理,画出目标框和置信度。

示例图片放置在yolov5_pytorch_demo/offline/yolov5_offline_simple_demo/data目录下,离线模型放置在model目录下。执行make.sh在src目录下生成可执行文件,执行run.sh对一张图片进行推理,在result目录下生成推理后的图片。

THE END
1.基于FPGA的高动态被控系统模型仿真零部件模型库中模型是完全公开的,用户可以针对具体项目需求进行调整,也可以由dSPACE提供工程服务。 2. 模型的扩展 由于模型完全开放,用户不仅可以自由调整模型,也可以在模型中扩展自己特性的模型组件。 3. 离线及在线仿真 支持在线仿真的同时,该模型库支持基于离线模型仿真的控制算法开发。相同的模型及参数可以无缝贯穿整个开发https://auto.vogel.com.cn/c/2012-08-28/686789.shtml
2.离线模型和在线模型有什么区别,cache里面有什么内容是在线模型runtime/python/onnxruntime/demo_vad_online.py中vad模型的调用每次都需要传个in_cache进去,如果我要将vad模型封装成一个http的接口,这样就需要知道每次调用这个接口缓存了哪些状态。 如果我不用online模型,只用offline模型,vad和模型的online版本会有哪些效果上的差异吗? https://github.com/modelscope/FunASR/issues/1824
3.推荐系统中离线推荐与在线推荐的困惑?其中模型训练部分与算法或策略相关性最高,下面详细介绍该模块的一些功能设计。主要挑战 在线学习与离线https://www.zhihu.com/question/525209410/answer/2417235234
4.OMG参数离线模型转换模型转换应用开发模型轻量化(可选) 概述 无训练量化 插件式量化 网络结构搜索训练 示例 常见问题 模型收益 AIPP(可选) 概述 AIPP参数 AIPP配置文件说明 AIPP集成方式 异构(可选) 可变data_type(可选) 模型转换 离线模型转换 OMG参数 模型转换前准备 模型转换示例 IR在线模型构建 集成准备 内存零拷https://developer.huawei.com/consumer/cn/doc/hiai-Guides/overall-parameter-0000001052966900
5.智能感知与人机协同教育部重点实验室多项研究成果入选NeurIPS极端数据异构下联邦学习——离线模型与在线模型的合作学习 数据异质性问题是联邦学习中的关键问题,目前尚无一个通用的算法框架可以解决多种异质性问题。针对这一挑战,本研究提出了基于模型合作的算法框架,并设计了用户内和用户间的知识迁移机制,从而更好地利用本地和全局知识。神经正切核理论证明这一算法比已有的算法Fehttps://www.shanghaitech.edu.cn/2023/1228/c1001a1087388/page.htm
6.通俗理解机器学习模式对比——离线在线与增量学习的差异#机器学习 #离线学习 #在线学习#增量学习 #模型训练 #数据更新 #预测准确率 第一节:机器学习模式的类比与核心概念 1.1 机器学习模式的类比 机器学习模式可以被视为不同的“烹饪方法”,离线学习像是准备一顿大餐,需要所有食材一次性备齐;在线学习则像是开一家快餐店,需要根据顾客的实时反馈调整菜单;增量学习则更https://blog.csdn.net/qq_37148940/article/details/117913147
7.千万IP创科普丨几何图神经网络综述:数据结构模型与应用等变图神经网络(equivariant GNNs)同时更新不变特征和同态特征,适用于需要同态输出的实际任务。等变GNNs将几何图上的函数设计为满足特定条件,通过信息传递推导出几何消息,并在图由连通性或邻接矩阵指定的邻域内进行聚合,考虑输入特征进行更新。目前实现https://mp.weixin.qq.com/s?__biz=MjM5ODIwNjEzNQ==&mid=2649895867&idx=3&sn=26ec63c6a8b4b74bf8340671c7f31236&chksm=bfdbb0299f4b3383bf6497931a0bf618c51862e998b910eb53eccc25d7da1637248b1c4f2b6e&scene=27
8.推荐系统完整的架构设计和算法(协同过滤隐语义)流式训练:、流式训练模块的主要作用是使用实时训练样本来更新模型。推荐算法中增量更新部分的计算,通过流式计算的方式来进行更新。在线训练的优势之一,是可以支持模型的稀疏存储。训练方面,在线模型不一定都是从零开始训练,而是可以将离线训练得到的模型参数作为基础,在这个基础上进行增量训练。 https://cloud.tencent.com/developer/article/1508050
9.屏南县公安局信息化采购项目附件▲5.平台应内置包括规则模型、关联模型、统计模型、情报模型、离线模型等在内的≥5大类安全分析模型,各类内置分析模型总条目数应不少于1300条;(投标人需提供相关截图证明进行佐证) 6. 模型可通过串并联方式组合编排,前一个模型的输出可以作为后一个模型的输入,支持分析模型编排层级>5层; 7. 支持与不同品 牌的网http://zfcg.czj.ningde.gov.cn/upload/document/20200807/9d142b566de140818484e071d457a4c2.html
10.除了这个以外,离线使用大模型这个解决了很多人的痛点,之前和做科研除了这个以外,离线使用大模型这个解决了很多人的痛点,之前和做科研的学长和一些已经就业的校友聊天,说大模型有一个问题是开源,因此把他们的数据传上去,会泄密,因此他们选择不用。用大模型的时候,比如让它分析科研数据(科研),让它分析专家纪要的文本(金融),让它https://xueqiu.com/1614824153/271176979
11.优秀供水解决方案:“智能在线模型,提升运营效率”2. 模型可看也可改,操作更简单:将模型编辑工作转移到B/S端,在线编辑,操作简单,易于掌握,突破以往在线模型只能查看不能编辑的局限。以方案对比这一功能为例,在线模型操作步骤明显简化,主要体现在以往很多需要专业人工操作和编辑的环节,现在都能够通过系统的自动计算实现(在线模型工作流程图为左,离线模型工作流程图为右https://www.h2o-china.com/news/292016.html
12.20信昆仑供水管网在线模型建设的关键问题与应用展望.pdf,供水管网在线模型建设的 关键问题与应用展望 信昆仑 教授 博士生导师 同济大学环境科学与工程学院 上海市四平路1239号,邮编:200092 电话:021-65985869 传真:021-65986313 Email :xkl@tongji.edu.cn 2019.4· 浙江义乌 提https://max.book118.com/html/2019/0522/8114013073002024.shtm
13.BIM管理平台与BIM模型之间是怎么运行的2. 离线模型快速加载平台支持在线模型浏览和离线模型浏览两种模式,在线浏览BIM模型需要耗费一定的云端加载模型的时间,影响模型浏览速度,而离线模型浏览模式可以从本地电脑硬盘读取轻量化模型数据,大大加快模型加载速度;且无需消耗流量。3.轻量化模型浏览平台支持BIM模型浏览、漫游、属性查看、剖切、测量、https://wen.baidu.com/question/1311576217225922299.html
14.基于SpeedgoatFPGA板卡的兆赫兹开关频率PMSM控制算法的开发与从上述开发流程中可以看到,通过Speedgoat FPGA板卡与MathWorks公司的HDL Coder工具的结合,电机控制器模型,从离线模型的开发,到基于CPU的在线模型的开发,到最终的基于FPGA的在线模型的开发,其模型的搭建过程和验证过程都是一致的,模型的改动量也非常少,只需要进行少量的拆分和封装,以及接口配置的工作,非常的方便。 https://www.yi-su.cn/newsinfo/694828.html
15.TopazVideoAIv5.5.1/v2.6.4/v1.6.1集成最新在线模型文件视频无损放大软件(ai视频修复软件) Topaz Video AI v5.5.1 集成OFX插件绿色版 + 离线模型包 视频无损放大软件(ai视频修复软件) Topaz Video AI v3.2.9 中文破解版 Topaz Video Enhance AI v2.6.4 / v1.6.1 集成最新在线模型文件完整破解版 (绿色便携版)https://www.4fb.cn/soft/pc/1773.html
16.Xintell智能模型平台北京顶象技术有限公司自动化模型管理 建模全流程组件一键上线 便捷的模型上/下线和管理 模型自动训练以及优化 模型的快速调用和决策 私有化安全部署 平台支持快速私有化部署 支持所有部件弹性扩容 数据与应用的隔离设计 在线升级 核心优势 全面而强大的建模组件 提供上百个建模组件,超过同类型平台2~5倍,以支持全流程的模型开发 https://www.dingxiang-inc.com/business/xintell
17.BDIP协同平台首页BDIP建筑数据集成平台 BDIP系统,全名Building data integrate platform,建筑数据集成平台。该平台是由毕埃慕(上海)建筑数据技术股份有限公司开发的一款基于BIM模型https://www.ruanfujia.com/software/177848/
18.导致项目代码很大,怎么解决51CTO博客使用离线模型放在项目中,导致项目代码很大,怎么解决,将模型文件与代码分离:通过本地路径或环境变量加载模型,避免模型文件与项目代码一起打包。使用Docker:通过https://blog.51cto.com/u_13171517/12298484