前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TorchScript | 目标检测部署实战

TorchScript | 目标检测部署实战

作者头像
iResearch666
发布于 2023-11-22 06:35:04
发布于 2023-11-22 06:35:04
50400
代码可运行
举报
运行总次数:0
代码可运行

Inference via TorchScript

简介

TorchScript 是可以由 TorchScript 编译器理解、编译和序列化的 PyTorch 模型的表示形式。从根本上说,TorchScript 本身就是一种编程语言。它是使用 PyTorch APIPython 的子集。

TorchScript 软件栈可以将 Python 代码转换成 C++ 代码。TorchScript 软件栈包括两部分:TorchScript(Python)和 LibTorch(C++)。TorchScript 负责将 Python 代码转成一个模型文件,LibTorch 负责解析运行这个模型文件

原理

TorchScript 保存模型有两种模式:trace 模式和 script 模式。

trace 模式

trace 模式就是跟踪模型的执行,然后将其路径记录下来。在使用 trace 模式时,需要构造一个符合要求的输入,然后使用 TorchScript tracer 运行一遍,整个运行过程就会被记录下来。在 trace 模式中运行时,每执行一个算子,就会往当前的 graph 加入一个 node。所有代码执行完毕,每一步的操作就会以一个计算图里的某个节点的形式被保存下来。PyTorch 导出 ONNX 也是使用了这部分代码,所以理论上能够导出 ONNX 的模型也能够使用 trace 模式导出 torch 模型。

trace 模式有比较大的限制:

  • 不能有 if-else 等控制流
  • 只支持 Tensor 操作

为什么有这种限制:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1. 跟踪出的 graph 是静态的,如果有控制流,那么记录下来的只是当时生成模型时走的那条路;
2. 追踪代码是跟 Tensor 算子绑定在一起的,如果是非 Tensor 的操作,是无法被记录的。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Module_0(torch.nn.Module):
    def __init__(self, N, M):
        super(Module_0, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))
        self.linear = torch.nn.Linear(N, M)

    def forward(self, input: torch.Tensor) -> torch.Tensor:
        output = self.weight.mm(input)
        output = self.linear(output)
        return output


scripted_module = torch.jit.trace(Module_0(2, 3).eval(), (torch.zeros(3, 2)))
scripted_module.save("Module_0.pt")
script 模式

script 模式不仅支持 if-else 等控制流,还支持非 Tensor 操作,如 List、Tuple、Map 等容器操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Module_1(torch.nn.Module):
    def __init__(self, N, M):
        super(Module_1, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))
        self.linear = torch.nn.Linear(N, M)

    def forward(self, input: torch.Tensor, do_linear: bool) -> torch.Tensor:
        output = self.weight.mm(input)
        if do_linear:
            output = self.linear(output)
        return output


scripted_module = torch.jit.script(Module_1(3, 3).eval())
scripted_module.save("Module_1.pt")

混合模式

一个 module 包含控制流,同时也包含一个只有 Tensor 操作的子模型。这种情况下当然可以直接使用 script 模式,但是 script 模式需要对部分变量进行类型标注。对上述子模型进行 trace,整体再进行 script:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Module_2(torch.nn.Module):
    def __init__(self, N, M):
        super(Module_2, self).__init__()
        self.linear = torch.nn.Linear(N, M)
        self.sub_module = torch.jit.trace(Module_0(2, 3).eval(), (torch.zeros(3, 2)))

    def forward(self, input: torch.Tensor, do_linear: bool) -> torch.Tensor:
        output = self.sub_module(input)
        if do_linear:
            output = self.linear(output)
        return output


scripted_module = torch.jit.script(Module_2(2, 3).eval())

libtorch

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <torch/script.h>

int main() {
  // load module
  torch::jit::script::Module torch_module;
  try {
    torch_module = torch::jit::load("my_module.pt");
  } catch (const c10::Error& e) {
    std::cerr << "error loading the module" << std::endl;
    return -1;
  }

  // make inputs
  std::vector<float> vec(9);
  std::vector<torch::jit::IValue> torch_inputs;
  torch::Tensor torch_tensor =
      torch::from_blob(vec.data(), {3, 3}, torch::kFloat32);
  torch_inputs.emplace_back(torch_tensor);
  torch_inputs.emplace_back(false);

  // run module
  torch::jit::IValue torch_outputs;
  try {
    torch_outputs = torch_module.forward(torch_inputs);
  } catch (const c10::Error& e) {
    std::cerr << "error running the module" << std::endl;
    return -1;
  }

  auto outputs_tensor = torch_outputs.toTensor();
}

语法限制

  • 支持的类型有限,这些类型是指在运行(而非初始化)过程中使用的对象或者函数参数
    • A PyTorch tensor of any dtype, dimension, or backend
    • 这其中不包括 set 数据类型,这意味着需要使用 set 的地方就要通过其他的方式绕过,比如先用 list 然后去重
    • 使用 tuple 时需要声明其中的类型,例如 Tuple[int, int, int],这也就意味着 tuple 在运行时长度不能变化,所以要使用 list 代替
    • 创建字典时,只有 int、float、comple、string、torch.Tensor 可以作为 key
  • 不支持 lambda 函数,但是可以通过自定义排序类的方式实现,略微麻烦,但是可以解决
  • 因为 TorchScript 是静态类型语言,运行时不能变换变量类型
  • 因为编码问题,所以对中文字符串进行遍历时会抛异常,所以尽量不要处理中文,如果需要处理中文,则需要将中文切分成字符粒度后再送入模型中进行处理

部署实战

  1. 首先参考yolov5模型,导出时候模型分为2个部分,一个用trace跟踪的traced_script_module(不包括最后一层),一个是最后检测层self.model.model[-1]
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
model = TracedModel(model, device, opt.img_size)
 
class TracedModel(nn.Module):
 
 def __init__(self, model=None, device=None, img_size=(640,640)): 
  super(TracedModel, self).__init__()
  # model:导入的模型
  # device: cpu、gpu
  # img_size: 输入图像大小
  print(" Convert model to Traced-model... ") 
  self.stride = model.stride # 8., 16., 32
  self.names = model.names # 每个类别的标签名
  self.model = model
 
  self.model = revert_sync_batchnorm(self.model)
  self.model.to('cpu')
  self.model.eval() # 切换为 eval 模式,不计算梯度
 
  self.detect_layer = self.model.model[-1] # 得到最后的检测层
  self.model.traced = True # False 修改为 True
  # 随机制造一个 bs=1 输入 tensor
  rand_example = torch.rand(1, 3, img_size, img_size)
 
  traced_script_module = torch.jit.trace(self.model, rand_example, strict=False)
  #traced_script_module = torch.jit.script(self.model)
  traced_script_module.save("traced_model.pt")
  print(" traced_script_module saved! ")
  self.model = traced_script_module
  self.model.to(device)
  self.detect_layer.to(device)
  print(" model is traced! \n") 
 
 def forward(self, x, augment=False, profile=False):
  out = self.model(x)
  out = self.detect_layer(out)
  return out
  1. 最好将检测层一起导出,model.model[-1].export = True
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
model.model[-1].export = True
img = torch.zeros(opt.batch_size, 3, *opt.img_size).to(device) 
ts = torch.jit.trace(model, img, strict=False)
ts.save(f)
  1. 成功导出torchscript格式后,可用Netro打开,即可验证是否成功

image-20231117175744016

  1. yolov5输出return x if self.training else torch.cat(z, 1)推理输出和训练不同
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class IDetect(nn.Module):
    stride = None  # strides computed during build
    export = False  # onnx export

    def __init__(self, nc=80, anchors=(), ch=()):  # detection layer
        super(IDetect, self).__init__()
        self.nc = nc  # number of classes
        self.no = nc + 5  # number of outputs per anchor
        self.nl = len(anchors)  # number of detection layers
        self.na = len(anchors[0]) // 2  # number of anchors
        self.grid = [torch.zeros(1)] * self.nl  # init grid
        a = torch.tensor(anchors).float().view(self.nl, -1, 2)
        self.register_buffer('anchors', a)  # shape(nl,na,2)
        self.register_buffer('anchor_grid', a.clone().view(self.nl, 1, -1, 1, 1, 2))  # shape(nl,1,na,1,1,2)
        self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch)  # output conv
        
        self.ia = nn.ModuleList(ImplicitA(x) for x in ch)
        self.im = nn.ModuleList(ImplicitM(self.no * self.na) for _ in ch)

    def forward(self, x):
        # x = x.copy()  # for profiling
        z = []  # inference output
        self.training |= self.export
        for i in range(self.nl):
            x[i] = self.m[i](self.ia[i](x[i]))  # conv
            x[i] = self.im[i](x[i])
            bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
            # 转ONNX时修改,避免scatterND结点
            # x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
            #替换为:
            x[i] = x[i].view(-1, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()

            if not self.training:  # inference
                if self.grid[i].shape[2:4] != x[i].shape[2:4]:
                    self.grid[i] = self._make_grid(nx, ny).to(x[i].device)
                # 转ONNX时修改,避免scatterND结点
                y = x[i].sigmoid()
                # y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * 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))
                # 替换为:
                xy = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i]
                wh = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i].view(1,self.na,1,1,2)
                y = torch.cat((xy,wh,y[..., 4:]),-1)
                z.append(y.view(-1,int(y.size(1) * y.size(2) * y.size(3)) , self.no))
        # 替换掉不必要的return
        # return x if self.training else (torch.cat(z, 1), x)
        #替换为:
        return x if self.training else torch.cat(z, 1)


    @staticmethod
    def _make_grid(nx=20, ny=20):
        yv, xv = torch.meshgrid([torch.arange(ny), torch.arange(nx)])
        return torch.stack((xv, yv), 2).view((1, 1, ny, nx, 2)).float()
  1. Detect层是YOLOv5最后一层,包含三个输出,分别是下降stride(见stribe属性,8,16,32)倍的网格。

25200=(80∗80+40∗40+20∗20)∗3 按照stride来划分,以640 × 640像素图像为例,stride分别是8,16,32 640 / 8 = 80,这层网格大小是80 × 80 640 / 16 = 40,这层网格大小是40 × 40 640 / 32 = 20,这层网格大小是20 × 20

  1. 后处理代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def numpy_sigmoid(x):
    return 1/(1+np.exp(-x))

def make_grid(nx=20, ny=20):
    xv,yv = np.meshgrid(np.arange(nx), np.arange(ny))
    res = np.stack((xv,yv), 2).reshape(1,1,nx,ny,2).astype(np.float32)
    return res
  
def numpy_detect(x, nc=None, bs=1):
    anchor_grid = [10.0, 13.0, 16.0, 30.0, 33.0, 23.0, 30.0, 61.0, 62.0, 45.0, 59.0, 119.0, 116.0, 90.0, 156.0, 198.0, 373.0, 326.0]
    anchor_grid = np.array(anchor_grid).reshape(3,1,-1,1,1,2)
    stride = np.array([8, 16, 32])
    grid = [make_grid(80,80), make_grid(40,40), make_grid(20,20)]
    z = []
    for i in range(3):
        y = numpy_sigmoid(x[i])
        y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + grid[i]) * stride[i]  # xy
        y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * anchor_grid[i]  # wh
        z.append(y.reshape(bs, -1, nc + 5))
    res = np.concatenate(z, 1)
    return res
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
model_script = torch.jit.load('torchscript.pt')
model_script = model_script.to('cuda')
for file in files:
 img_path = os.path.join(test_path,file)
    img0 = cv2.imread(img_path) 
    img = letterbox(img0,new_shape=(640, 640), color=(114, 114, 114), auto=False, scaleFill=False, scaleup=True, stride=32)[0]
    print(f'[img.shape] {img.shape}')
    # 640 448
    # # Convert
    img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416
    img = np.ascontiguousarray(img)

    img = torch.from_numpy(img).to(device)
    img = img.half() if half else img.float()  # uint8 to fp16/32
    img /= 255.0  # 0 - 255 to 0.0 - 1.0
    if img.ndimension() == 3:
        img = img.unsqueeze(0)
 
    # ! export torchscript
    pred = model_script(img) 
    pred = [x.data.cpu().numpy() for x in pred]
    pred = numpy_detect(pred, 11)
    pred = torch.tensor(pred).to('cuda')
    
    # Apply NMS
    # (center x, center y, width, height) 
    pred = non_max_suppression(pred, conf_thres=conf_thres, iou_thres=iou_thres, classes=None, agnostic=False)
  • 注意 letterbox 中 auto=False 保持固定尺寸

结果演示

  • 以上仅以yolov5为例,实际并非yolov5

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-11-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iResearch666 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
[答疑]监控系统 保安在监视间里面看 这个保安算执行者吗
比如监控系统 保安在监视间里面看 这个保安算执行者吗 睡鱼(61***11) 17:02:53 单如果不算执行者 这个系统的功能怎么考虑 Aadm(949***29) 17:03:26 考虑这种有悖论的话题有意思吗 lihongwei(6273***07) 17:03:37 如果系统感知不到保安的存在,保安和系统不进行交互,那他不是执行者 睡鱼(61***11) 17:03:52 显示监视画面 就是用例啊 而且就是给保安设计的啊 Aadm(949***29) 17:04:03 监视器提供监视功能,保安查看画面 Aadm(949***29) 17:04:38 虽然名义上没用手动,但实际上用这个来完成工作 lihongwei(6273***07) 17:06:20 保安看不看,干不干事,系统都不知道 Aadm(949***29) 17:06:21 潘老师说系统对外提供的是价值 Aadm(949***29) 17:06:45 如果只看名义上的有什么用 Aadm(949***29) 17:07:31 一款产品没人用,生产出来也是多余的,也根本不应该在你的设计里面 Aadm(949***29) 17:07:54 不然只能说是你考虑的不周全 睡鱼(61***11) 17:08:44 应该算 睡鱼(61***11) 17:08:56 不过这个用例不好描述了 睡鱼(61***11) 17:09:14 电视通电 睡鱼(61***11) 17:09:35 电视查看频道数据 睡鱼(61***11) 17:09:46 电视显示画面 睡鱼(61***11) 17:09:52 没保安什么事 潘加宇(3504847) 7:41:53 如果保安不需要和监控系统有交互,也就是说系统不需要保安提供的输入才能执行用例,那么保安不算执行者 保安是涉众的一种,另外的涉众还有被拍的人,单位领导,政府等,在地面放个摄像头拍女生裙子里的东西, 也许保安喜欢看,但被拍的人不喜欢,政府也不允许。 参见《软件方法》第5章,5.1节关于执行者、涉众的描述 在未来,人类可能会越来越多扮演观众(涉众)的角色,台上的事情由机器对机器来表演。
用户6288414
2022/04/11
2130
[答疑]业务序列图推导出系统的三个用例注册SIM卡、申请激活、审核激活申请
勤瘦(216***56) 10:29:41 从业务序列图推导出系统的三个用例注册SIM卡、申请激活、审核激活申请
用户6288414
2021/04/22
6010
[答疑]有业务流程还好,如果某项业务连业务流程都没有
海纳百川(5******5) 9:24:24 有业务流程还好,如果某项业务连业务流程都没有,需要业务分析师去推动,而各个部门都有自己的利益,很难达成一致,这就困难了,潘老师有什么好建议? 潘加宇(3504847) 9:26:18 怎么可能没有流程,流程无处不在,去观察,如实画出来就是 潘加宇(3504847) 9:27:28 就算制订了规范,实际中不是这样做,又有什么用 海纳百川(5******5) 9:27:28 确实没有的,每个大类相同业务根据不同业务细分,产生的流程都是不同的 海纳百川(5******5) 9:27:39 关键现在就是没有规范 潘加宇(3504847) 9:27:51 "每个大类相同业务根据不同业务细分,产生的流程都是不同的" 这不还是有吗 海纳百川(5******5) 9:28:11 这些都是按照每个Case临时做的 潘加宇(3504847) 9:28:15 没有业务流程怎么做事?上厕所都可以描述出业务流程,不要说做有价值的事 海纳百川(5******5) 9:28:59 现在就是要总结抽象出具体的规范和流程,以在系统中实现 潘加宇(3504847) 9:29:04 所以,你要去认真观察,那些人大脑里怎么想的,为什么这个事情要这样做,那个事情要那样做 佟太丰(安捷睿达)(318***73) 9:29:13 有时候客户会说,先这样做,以后再修改成什么什么,这让人比较头疼 海纳百川(5******5) 9:29:27 现在这类业务非常复杂,没人梳理,如碰到,每个都是独立的个案 潘加宇(3504847) 9:29:41 如实把它画出来,找到改进点,用你的系统来改进。这就是你的系统的价值所在 潘加宇(3504847) 9:30:03 如果人家没病,找你这个医生干什么? 海纳百川(5******5) 9:30:07 是啊,但是现在就是需要将这些前后端给整体梳理清楚 潘加宇(3504847) 9:30:33 作为一个老鸟,不要像菜鸟一样哀叹,要有办法做事情 潘加宇(3504847) 9:31:26 可以再阅读软件方法第四章 海纳百川(5******5) 9:31:35 现在就是在想各种办法进行前后端统一搞定 深圳_吴刚(45***4231) 9:33:07 潘加宇(3504847) 9:30:03 如果人家没病,找你这个医生干什么? 深圳_吴刚(45***4231) 9:33:18 这句话很重要。 潘加宇(3504847) 9:33:31 如何改进,往哪个方向改进,还是要看业务部门老大的意思啊。"统一"不一定是老大看重的方向,即使是,度在哪里也要搞清楚。 深圳_吴刚(45***4231) 9:34:25 现在有些的项目管理者都不去想能不能给企业带来价值,那还做项目干什么 京张秋松 (183***140) 9:35:42 "中国特色"也很重要 海纳百川(5******5) 9:39:03 有些事不是项目管理者能够立刻推动的,而是需要锲而不舍的精神逐步去影响,去达成平衡的,因为项目管理者头上的老大太多了,有时候是需要逐步或长期推动,在诸多部门之间的利益之间达成平衡 kevin(3075***97) 9:55:52 项目管理者木前在中国就是个打杂的 深圳_吴刚(45***4231) 10:09:04 要有英雄先死的气慨,哈哈 云龙九现(274***752) 10:16:00 这总比以前没有项目管理者要强,相信会逐步规范起来。
用户6288414
2021/04/22
3020
[答疑]合同联签流程
有谁能帮我分析一下一个流程。 合同联签流程。 经办人提出申请->部门经理审核->按所选择的多部门进行联审->副总经理审核->总经理审批->总部财务部审核->总助确认。 有一张合同联签单流转。 潘加宇 (3504847) 2012-07-13 20:31:54 你说得挺清楚啊,困惑在哪里? ♂爪哇岛语 (427***398) 2012-07-13 20:32:24 这个流程是我这次项目中的一条。 ♂爪哇岛语 (427***398) 2012-07-13 20:32:35 这次项目中有N条流程。 ♂爪哇岛语 (427***398) 2012-07-13 20:32:53 属于日常办公业务范围。 ♂爪哇岛语 (427***398) 2012-07-13 20:33:14 我把流程这一块分为业务。 ♂爪哇岛语 (427***398) 2012-07-13 20:33:22 另外加对应的管理 ♂爪哇岛语 (427***398) 2012-07-13 20:33:31 我这样分对吗? 潘加宇 (3504847) 2012-07-13 20:35:17 实事求是来就是了 一个业务用例下面可以分许多个场景(所谓流程) ♂爪哇岛语 (427***398) 2012-07-13 20:35:56 我就是把这些流程主在一起作为业务边界。 ♂爪哇岛语 (427***398) 2012-07-13 20:36:05 一个流程就是一个业务用例。 潘加宇 (3504847) 2012-07-13 20:36:14 "业务边界"的意思是? ♂爪哇岛语 (427***398) 2012-07-13 20:36:36 针对单位内全有部门。 ♂爪哇岛语 (427***398) 2012-07-13 20:36:40 所有 ♂爪哇岛语 (427***398) 2012-07-13 20:36:50 提供审批服务的业务边界。 潘加宇 (3504847) 2012-07-13 20:37:21 "流程"是业务用例的一种实现方式,不是用例本身 潘加宇 (3504847) 2012-07-13 20:37:41 你可以看看我写的《软件方法》,这样比较难讨论 ♂爪哇岛语 (427***398) 2012-07-13 20:37:59 那我这个怎么搞呢。 潘加宇 (3504847) 2012-07-13 20:38:08 你的困惑是什么? ♂爪哇岛语 (427***398) 2012-07-13 20:38:14 合同审批 ♂爪哇岛语 (427***398) 2012-07-13 20:38:37 业务用例查得不对? ♂爪哇岛语 (427***398) 2012-07-13 20:38:39 找得 潘加宇 (3504847) 2012-07-13 20:38:53 你照着实事求是画若干张"业务流程图",有什么困难吗 ♂爪哇岛语 (427***398) 2012-07-13 20:39:27 没有困难 潘加宇 (3504847) 2012-07-13 20:39:30 业务用例查得不对? --也无法讨论,因为你的研究对象没有给出来 ♂爪哇岛语 (427***398) 2012-07-13 20:39:43 研究对象? ♂爪哇岛语 (427***398) 2012-07-13 20:39:48 做一个OA呀。 ♂爪哇岛语 (427***398) 2012-07-13 20:40:11 你说的研究对象是什么? 潘加宇 (3504847) 2012-07-13 20:41:22 研究对象--你要改进的组织。业务建模业务建模,你总得说是对什么组织的业务建模吧,肯定不是针对整个宇宙 ♂爪哇岛语 (427***398) 2012-07-13 20:42:01 做OA呀。 ♂爪哇岛语 (427***398) 2012-07-13 20:42:07 还能有什么组织 ♂爪哇岛语 (427***398) 2012-07-13 20:42:10 一个单位 ♂爪哇岛语 (427***398) 2012-07-13 20:42:14 公司 潘加宇 (3504847) 2012-07-13 20:43:03 那你的图呢 潘加宇 (3504847) 2012-07-13 20:43:09 我看看 ♂爪哇岛语 (427***398) 2012-07-13 20:44:03 我是先画的业务视图,用活动图画的。 ♂爪哇岛语 (427***398) 2012-07-13 20:44:27 活动就是按刚刚的那个流程图来的。 ♂爪哇岛语 (427***398) 2012-07-13 20:45:03 比如:合同审批。 潘加宇 (3504847) 2012-07-13 20:45:07 既然已经画了活动图里,就往下走吧,不要再想业务用例的事情了 ♂爪哇岛语 (427***398) 2012-07-13 20:45:1
用户6288414
2021/04/22
1.6K0
[答疑]财务公司吸收成员单位的存款,并根据吸收的存款开展贷款业务
LionKing(425***36) 11:11:26 潘老师,请教一下,业务建模的时候,发现有类需求不是组织外涉众对于组织要求的服务,而是组织自身的要求 LionKing(425***36) 11:11:54 比如说银行出于头寸调拨的需要,有向同业市场进行资金拆借的需求 LionKing(425***36) 11:12:23 这类需求在用例图中如何表示呢?与之相关的业务执行者是? LionKing(425***36) 11:16:52 感觉可以把其他商业银行当成辅助执行者,但是主执行者呢? LionKing(425***36) 11:38:18 潘老师,本次调研的业务用例,请帮看看有没问题 LionKing(425***36) 11:39:22
用户6288414
2021/04/22
7260
[答疑]如果要把系统划分成若干个子系统,在作系统用例的时候,是否要确定好子系统边界
潘老师,请教个问题, 如果要把系统划分成若干个子系统,在作系统用例的时候,是否要确定好子系统边界,并把相关的用例归入到子系统中? JinPJ(270***96)11:26:48 感觉应该先分析用例,在做系统拆分。这样才能靠近高内聚,低耦合 西門(313***50)11:27:47 我已经把用例作好了,现在要按业务线及技术线把系统切成不同子系统 西門(313***50)11:29:53 把这个系统用例放一起,有几十个,再加上一些关系,成蜘蛛网了 广李福财(74***11)11:30:21 子系统是不是取名为用例包好一点呢? 潘加宇(3504847)11:31:17 子系统按照类划分,和用例无关。复习第一章,图1-1 潘加宇(3504847)11:32:12 第5章,5.5.3 错误:玩弄"子系统" 潘加宇(3504847)11:32:30 @广李福财(74***11) 你掌握得很好 西門(313***50)11:33:35 就是在作用例时候不考虑子系统这样的问题? 广李福财(74***11)11:37:04 也遇到过这种按业务线或者技术线的,我比较偏向于对业务所涉及的组织(某单位的不同业务部门)单独作为要改进的组织来进行切分分析。 如果只是作为一个整体来,感觉越整越复杂。 @潘老师,不知道这种方式是否合适? 西門(313***50)11:37:15 执行者有很多,系统用例间还有些包含,继承关系,所以就变蜘蛛网了 西門(313***50)11:39:44 我再复习一下第五章 潘加宇(3504847)11:44:04 怎么会越整越复杂? 例如,客户说要一个闹钟,这个功能,那个功能。照实写需求就是了。结果偏偏把闹钟的零件单独一个个写"需求"?其实,你是卖闹钟的,不是卖零件的。零件可以买,可以用现成的,零件的选择和组装也是灵活的,可以随便改的 归根结底,还是没有学会从卖的角度看需求。 潘加宇(3504847)11:45:31 把每行代码当成需求更简单 潘加宇(3504847)11:45:49 复习5-6章 潘加宇(3504847)11:47:06 第五章:背后可能隐藏着这样的问题:开发人员的设计能力太弱。做设计时只是把需求直通通地映射,缺乏抽象能力,当然会害怕用例变多了。开发人员没有掌握有序、系统地抽象的能力,当发现"此处似乎可以抽象"时,迫不及待想露一手,因为他害怕此时不露一手,没准以后露一手的能力和机会就消失了。这和小孩刚学习一个新东西,什么地方都想表现一下是类似的。
用户6288414
2022/04/11
1780
[答疑]系统监听MQ队列自动发送邮件是什么用例
白开水<czmo***q.com> 2016/7/11 10:27:33 UML中自动执行的用例怎么画,比如,系统自动发送邮件 潘加宇(3504847) 17:15:07 "系统发送邮件"是步骤,看这个步骤是哪个用例里面的步骤了。"自动""手动"等词语尽量不用。 白开水<czmo***q.com> 22:38:38 系统自动发送邮件,是这样的。我们系统采用的MQ进行交互。系统监听MQ队列中的消息。如果有消息进来的话,自动通知相关的人员进行处理。另外,潘老师,我想问一下怎么区分用来,还是用例中的步骤?比如系统发送邮件,可以理解为执行者为系统,可以原来是属于人肉系统执行的, 只是被系统自动做了 潘加宇(3504847) 22:51:56 根据你的描述,用例应该是:时间→监听MQ队列消息。发邮件是里面的步骤。 后面你说的几句话,说明你需要再认真看《软件方法》复习一下 白开水<czmo***q.com> 23:00:29 好的。谢谢老师。我再仔细看看 李俊杰(705***85) 23:05:02 "系统采用的MQ进行交互。系统监听MQ队列中的消息。如果有消息进来的话,自动通知相关的人员进行处理。" 如果只把要实现的功能用这段自然的语言描述出来,开发会看发不出吗?为什么一定要纠结于用例怎么写呢? 李俊杰(705***85) 23:10:18 写成timer-监听mq队列或写成system-发邮件不都得说明吗?会让开发人员开发错吗?如果遇到开发人员和发问的兄弟对用例的理解差不多时,他是不是更能理解他需要实现什么呢?这些在哪些方面影响工作呢? 白开水<czmo***q.com> 23:12:21 其实这里讲的就是到底用例有没有个粒度标准 李俊杰(705***85) 23:18:00 依赖于会把用例拿来做什么吧?如果要做成本估算或进行工作量估算可能得定定个颗粒度标准,见过为了绩效考核和缺陷计量而制定用例颗粒度标准的,结果写用例写的很痛苦 李俊杰(705***85) 23:19:28 如果只是用来表达需求,能写到可交流,可沟通,可确认就行吧,能有颗粒度的标准吗? 李俊杰(705***85) 23:20:08 毕竟用例也是一种语言,语言能有颗粒度的标准吗? 白开水<czmo***q.com> 23:20:20 也是 潘加宇(3504847) 9:01:46 用例就是教开发人员怎样选择严谨的自然语言描述需求。平时许多开发人员描述的所谓需求,在用例思维的照射之下,就会显得千疮百孔。不信就随便贴一段你们团队写的所谓"需求"来看看。 像上面这一句,"系统采用的MQ进行交互,系统监听MQ队列中的消息",这里就有问题,"采用的MQ进行交互"这是来自开发团队的设计决策,还是涉众的要求?如果是来自开发团队的设计决策,这个需求是不存在的,应该从涉众的角度找用例(系统为涉众提供的价值),例如:时间→检查新订单并提醒,甚至和"定时"没关系! 例如"员工提交申请信息",也可以描述成"员工按下回车键",还可以描述成"Form1上发生Keypress事件",还可以描述成"【定时】逐行扫描键位矩阵,确定闭合键的坐标和按键对应的扫描码"是不是有点像定时**MQ?哪个好,就要看系统的核心域是什么。 假设"采用的MQ进行交互"确实是系统的功能需求,系统的核心域知识确实就是这个领域。"系统监听MQ队列中的消息。如果有消息进来的话,自动通知相关的人员进行处理",监听如何引发,每次监听需要外部执行者来引发吗,还是按照一定时间周期进行?什么叫"有消息进来"?另外,"自动"也是冗余的表达。 潘加宇(3504847) 9:02:42
用户6288414
2021/06/10
4700
[答疑]系统监听MQ队列自动发送邮件是什么用例
[答疑]看了EA官网上的需求跟踪视频,结合目前的状况,提出这个问题
三羊.Lee(183***58)16:36:44 潘老师及各位同学,在使用EA的过程中有几个疑问: 1、EA中的"需求建模"何时使用?是用在项目建模初期与用户沟通需求,搜集需求素材时呢?还是在通过用例及业务模型对需求进行分析后,得到需求规约,管理需求规约时使用呢? 2、在项目开始时期,需要与用户签订技术方案,此方案中需要包含一份需求文档,这份需求文档是给客户看的。而需求分析过程中得出的需求规约是给开发人员使用,这样理解是否正确? 谢谢! 潘加宇(3504847)16:40:26 1. EA里提供了各种各样UML非UML的东西,例如描述业务流程就至少提供了4种图,不是都要用的。那个"需求建模"类似于以前的需求条目,一条条的描述需求,现在,需求已经用用例组织起来,不需要用这个。 潘加宇(3504847)16:41:28 2. 复习需求的视图和模型的区别,交流和开发的区别 潘加宇(3504847)16:41:54 给客户看什么、签什么内容,文档名字叫什么,是很宽松的 潘加宇(3504847)16:42:11 进入到我们软件开发团队内部,要很严格 北京-Y.Lee(183***58)16:44:03 哦,现在的情况是,在与客户交流后,就形成了一份所谓的需求说明书,需求调研相关人员就扔给了开发人员,说这就是需求。 潘加宇(3504847)16:45:26 "形成了一份所谓的需求说明书" 潘加宇(3504847)16:45:32 谁写的 潘加宇(3504847)16:45:56 如果是需求人员很严谨地写的,符合需求标准,没有问题 上王志华(969***87)16:46:52 问题是如何让需求人员能很好的写出"符合标准"的需求文档呢 潘加宇(3504847)16:51:39 厨师不会做菜要上蓝翔去学习,不能让买菜的买到什么食材就直接往锅里扔什么 北京-Y.Lee(183***58)16:52:34 呵呵,这比喻真经典 上王志华(969***87)16:52:58 "如果是需求人员很严谨地写的,符合需求标准,没有问题" 上王志华(969***87)16:53:06 我可能理解他遇到的问题 上王志华(969***87)16:53:20 我们总是认为公司里有一个负责整理需求的人写出来的就OK 上王志华(969***87)16:53:39 开发人员就需要按照这份去文档去开发 上王志华(969***87)16:54:08 但是需求人员的水平参差不齐 上王志华(969***87)16:54:52 需求人员也有一个工作经验积累的问题,他的工作应该有人审核 上王志华(969***87)16:55:12 或者应该经过一套流程然后走向开发人员 上王志华(969***87)16:55:37 但是这套流程是需要根据每个公司自身的情况去制定的 上王志华(969***87)16:56:25 如果没有这个环节那么他提出的问题是得不到很好的解决的 北京-Y.Lee(183***58)16:59:20
用户6288414
2021/05/11
3380
[答疑]看了EA官网上的需求跟踪视频,结合目前的状况,提出这个问题
[答疑]用例规约中像5.中说的保存、修改功能,怎么写合适
627***407(627***407) 10:02:53 像5.中说的保存、修改功能,怎么写合适? 627***407(627***407) 10:04:06 保存的时候,如果之前统计和保存过,则要覆盖 潘加宇(3504847) 12:35:50 基本的道理:需求是描述系统不这样不行(涉众的合理利益会受侵害),不符合这个条件的不要写 潘加宇(3504847) 12:37:01 4步 可能需要在补充约束部分,添加统计的业务规则 潘加宇(3504847) 12:37:22 步骤5 需要在补充约束部分添加 字段列表 潘加宇(3504847) 12:41:34 6 管理人员可以 修改报表 7 管理人员确认 8 系统保存报表 潘加宇(3504847) 12:42:12 6a 管理人员要求修改报表: 6a1. ................. 6a2.. .................... 潘加宇(3504847) 12:43:03 "保存的时候,如果之前统计和保存过,则要覆盖" -----写在字段列表或业务规则里 627***407(627***407) 14:07:09 恩,谢谢潘老师 627***407(627***407) 14:08:31 查看报表的时候可以导出报表,"查看报表"和"导出报表"之间应该是什么关系? 627***407(627***407) 14:11:32 "导出报表"可以单独作为用例吗? 627***407(627***407) 14:11:52 另外,还有"打印报表"也是一样的问题? 潘加宇(3504847) 14:12:12 他们之间没有关系 潘加宇(3504847) 14:12:41 复习一下软件方法第6章,登录的问题 627***407(627***407) 14:13:07 好的 潘加宇(3504847) 14:13:26 以及'扩展不等于链接'
用户6288414
2022/04/11
3840
[答疑]用例规约中像5.中说的保存、修改功能,怎么写合适
[答疑]买家发起退款与买家撤消退款是什么关系
杭大伟(28****23)13:27:26 问个UML用例之间的关系问题:在电商网站中,买家买到东西不满意,于是发起了退款。后来卖家说买家一点补偿。于是买家想撤消退款。 杭大伟(28****23)13:27:42 于是问题是:买家发起退款这个用例, 与买家撤消退款这个用例, 杭大伟(28****23)13:27:45 两者是什么关系? 杭大伟(28****23)13:27:48 扩展? 潘加宇(3504847)13:29:50 你的研究对象是"电商网站"? 杭大伟(28****23)13:30:01 是的。 潘加宇(3504847)13:30:24 就是两个用例嘛 潘加宇(3504847)13:30:27 不用扯上关系 杭大伟(28****23)13:31:06 可是如果 不事先走发起退款这个用例,撤消退款用例这个其实不存在的。 潘加宇(3504847)13:31:35 "不事先走发起退款这个用例,撤消退款用例这个其实不存在的"这个想法是不对的 杭大伟(28****23)13:32:04 为什么呢? 潘加宇(3504847)13:32:58 是否可以使用系统来"撤消退款"用例,判断标准是"存在符合退款条件的订单" 潘加宇(3504847)13:33:41 至于系统如何达到"存在符合退款条件的订单"的状态,不一定和某个特定用例相关 杭大伟(28****23)13:33:50 判断标准是:1,必须有退款(买家已经发过),2, 退款还在退款中。 潘加宇(3504847)13:34:23 这个细微的问题恰好是软件复杂性的关键所在 杭大伟(28****23)13:35:06 嗯,我现在在做系统用例,遇到这个问题,在用例图上如何表现 发起退款, 撤消退款, 杭大伟(28****23)13:35:23 感觉不是那么好表现。用扩展关系,感觉又不像又像。 潘加宇(3504847)13:36:46 两个独立的用例。因为退款结束,执行者就走开了,交互已经完毕。什么时候想用系统来取消,是另一件事情。取消并非退款的分支。 潘加宇(3504847)13:37:19 你如果这样想就麻烦了 潘加宇(3504847)13:37:36 存款是不是取款的扩展啊 潘加宇(3504847)13:38:05 要想取款,是不是先得用系统存款? 杭大伟(28****23)13:38:10 撤消退款是用户主动发起的。 杭大伟(28****23)13:38:19 不是系统来发起的。 杭大伟(28****23)13:38:42 又感觉 撤消退款不能作为一个用例。软件方法里说到,系统用例是用户的一种期望,撤消退款显然也不能作为用户的期望。就像软件方法中的登录,登录不能作为系统用例一样。 潘加宇(3504847)13:38:57 撤销退款和登录不一样 潘加宇(3504847)13:40:03 我刚才讲的 至于系统如何达到"存在符合退款条件的订单"的状态,不一定和某个特定用例相关 你理解没有? 潘加宇(3504847)13:40:14 状态和行为的区别 杭大伟(28****23)13:40:55 但您的意思是,撤消退款就单独做为一个用例么 潘加宇(3504847)13:41:34 拿开饭馆举例,顾客来吃饭,喝茶、打包、办宴会,城管来收管理费,都是用例。 但是"进门坐下"不是 潘加宇(3504847)13:41:46 我上面已经说清楚了 杭大伟(28****23)13:45:38
用户6288414
2021/04/23
5710
[答疑]运维人员的日常巡检过程、重大保障活动是业务用例吗
请教潘老师:运维系统业务建模过程中,,运维人员的日常巡检过程、重大保障活动是业务用例吗?这2个活动是运维的重要客户服务内容,但问题是运维人员是组织内部业务工人,不是组织外的。 梅内.西马尔(124***74) 13:57:10 运维人员是否将发现的问题上报给某某,研究的组织应该是某某。运维人员期望该组织能提供的服务可能是,接收日常巡检信息,异常信息,反馈异常处理结果,跟踪异常处理进程等等 锡山飞狐<la***msn.com> 14:09:38 运维人员通过巡检发现并处理掉潜在的问题,只有无法解决问题时才报告给部门主管或经理;运维保障是比如客户的领导来参观,运维人员确保系统在出现异常时马上应急处理,确保IT系统能继续正常服务。所以运维人员一般不把问题上报。 梅内.西马尔(124***74) 14:13:50 那谁期望这个运维系统改善什么方面的业务问题呢? 梅内.西马尔(124***74) 14:14:15 老大是谁? 锡山飞狐<la***msn.com> 14:16:47 多谢梅兄热心参与讨论。老大就是这个组织(技术服务中心的经理),他希望巡检过程能够规范到位,以便能真正消除隐患,并且过程可追溯。 梅内.西马尔(124***74) 14:18:51 规范到位怎么理解?有什么机制吗? 锡山飞狐<la***msn.com> 14:20:59 比如巡检,必须到真实地去查看每台设备、每个IT系统运行健康指标,而不是不干活,随便填写一个巡检报告单报告没有问题。 梅内.西马尔(124***74) 14:27:19 那如前面所说"一般不上报,遇到问题已处理了。"那么运维人员即使实地查了每台设备,老大也不知道啊,似乎有些矛盾 锡山飞狐<la***msn.com> 14:27:53 "并且过程可追溯" 乐吧(54***762) 14:29:10 图上的业务用例太多了吧?这个组织真的对外提供了这么多有价值的服务吗?建议先找到真正的业务用例,再画时序图,推导出系统用例 梅内.西马尔(124***74) 14:30:13 人家现在就是在找业务用粒来的 锡山飞狐<la***msn.com> 14:32:03 感觉应该还不止这些,现在是不确定"巡检"、"保障"算不算业务用例。这两个业务活动的确是非常重要不可缺少的。 乐吧(543***762) 14:35:50 判断是否是业务用例的标准,应该是它是否对外提供了价值呀,不要将业务过程或某个内部业务流程当作业务用例呀 mousedogpig(511184101) 14:36:08 燕雀安知鸿鹄之智,别把潘老师看扁了 锡山飞狐<la***msn.com> 14:39:18 这两个活动是对外提供了价值,但找不到组织外的直接的业务执行者。 广罗军(120***58) 14:56:18 @锡山飞狐 服务主管领导、客户运维负责人这两个业务执行者是技术服务中心外的吗?怎么感觉是内部部门的主管 锡山飞狐<la***msn.com> 15:10:51 技术服务中心与客户签订合同,然后帮助用户运维他们的IT系统和设备。这个系统的老大是被研究组织的部门经理,服务主管领导是老大的领导;客户运维负责人是被服务的客户方负责人。 广罗军(120***58) 15:11:56 明白了 广罗军(120***58) 15:17:00 @锡山飞狐 是不是还有一个业务用例没有识别?我问个问题:通过日常巡检过程、重大保障活动来对外提供的价值,这个业务用例应该命名为什么?图中目前没有 锡山飞狐<la***msn.com> 15:21:29 问题就是我不知道该怎么画,用例命名可以叫"巡检"、"保障重大活动",但找不到业务执行者。 乐吧(543***762) 15:34:10 @锡山飞狐 从你前面的表述来看,可能只有一个"运维服务"的业务用例,这个才是执行者需要这个组织提供的有价值的服务。而"巡检"只是为了完成这个运维服务,组织Worker需要做的一个重要工作而已,它应该不是业务用例 乐吧(543***762) 15:36:11 至于"保障重大活动",如果客户需要为此付费,我觉得也是业务用例,执行者应该付费客户 锡山飞狐<la***msn.com> 15:51:52 多谢@乐吧 的参与,不是太认同只有一个"运维服务"业务用例,比较认同保障重大活动是业务用例。事实上技术服务中心的上级监管领导需要这个组织提供给他组织运营情况的报表,这一定会是业务用例;客户终极目标是他的IT系统和设备不出问题,安全运行,但为了达到这个目的,需要客服中心提供具体运维服务,并愿意买单,而运维服务包括"定期巡检"、"保障重大活动"、"定期提供IT设备和台账的运行健康状况报表"、"随时提醒异常情况"、"帮助用户临时采购耗材"等等,过程各不相同,客户为了确保服务的质量,也需要有"投诉"、"跟踪查看问题处理过程"等要求。 梅内.西马尔(124***74) 16:00:35 快来买啊
用户6288414
2021/04/22
9920
[答疑]在A业务用例下,有5个业务流程;在B业务用例下,有7个业务流程
第五元素(50***16) 9:08:47 经过仔细思考,原来的老问题还是没有想通。请潘老师指教: 1、在A业务用例下,有5个业务流程;在B业务用例下,有7个业务流程。其中,有4个业务流程是完全相同的。 请问,这四个相同的业务流程,是否可以归纳为"包含"(include)的业务用例?需要在业务用例图中表达出来吗? 2、一个业务用例对应多个业务流程,最后用交互概览图来总括表达。那么同一个业务用例划分为多个业务流程的原则是什么? 比如,A业务用例划分为A1、A2....等业务流程,用交互概览图"串"起来。那么在
用户6288414
2021/10/13
5860
[答疑]茶叶盒的用例
乡下小老鼠(250****30)11:21:08 大家好,学习UML一段时间了,在自己的日常开发中也有了一些应用,各种图和元素的用法也有了一定的掌握,正在沾沾自喜的时候,老大跟我开了一个玩笑,让我写出他随手拿起的茶叶盒的用例,这引起了我的一些思考:1、UML可以对我们日常生活中的各种系统建模,但是能对任意事物(如上面的茶叶盒)进行建模吗?在某一场景下可以用类图表示茶叶盒的一些属性信息,可对于茶叶盒这个没有输入、加工、输出的家伙会有表示他的用例吗?换言之,我认为茶叶盒不是一个系统(我考虑不出它作为系统的场景)
用户6288414
2021/04/22
5970
[答疑]单位公文系统的组织,我定位是综合部文秘处,老大是该处处长
歌者(37***50) 8:31:25 我们单位公文系统的组织,我定位是综合部文秘处,老大是该处处长。愿景是提升公文办理效率,方便员工尤其是领导办理公文。公司各级领导,员工,信息化部,各子公司领导员工信息化部是利益相关方,是涉众。以上差不多是愿景内容吧?涉众每个都要总结愿景写用例? 潘加宇(3504847) 8:34:27 找出度量指标就可以 潘加宇(3504847) 8:36:27 另外,上面的问题把几个工作混在一起了,先复习一下,按课上或书里讲的做 歌者(37***50) 9:04:12 培训是n年前的事情喽。我现在正在看《软件方法》的书将已做完的系统重新分析。 歌者(37***50) 9:55:52
用户6288414
2021/04/22
2920
[答疑]老师用评分系统评分的序列图
潘老师 麻烦您一下 业务建模里的序列图有点思路不太清 单纯な马鹿でありたい(1271***351) 14:02:54
用户6288414
2021/04/22
7280
C#宿舍系统数据库
Source Server : workplace Source Server Version : 50610 Source Host : 127.0.0.1:3306 Source Database : dormdb
张哥编程
2024/12/21
940
主动推理研究机构和主动推理生态系统
这份文件简要调查了主动推理研究所和主动推理生态系统的现状,并概述了我们未来的方向。它将被版本化为一般和局部生态系统的活表示(循环和更新),描述主动推理研究所的过去、现在和未来行动。
CreateAMind
2023/09/28
3830
主动推理研究机构和主动推理生态系统
Android和Linux应用综合对比分析
本文介绍了嵌入式Linux操作系统在工业自动化领域中的应用,包括各种工业设备、通信和数据处理等方面。同时,文章还探讨了基于嵌入式Linux的工业自动化技术的未来发展趋势,包括实时性、远程访问、无线通信等方面。
用户1170933
2018/01/05
4.4K0
Android和Linux应用综合对比分析
软件方法(下)分析和设计第8章分析 之 分析类图——知识篇(20211227更新)
http://www.umlchina.com/book/softmeth08part1.pdf
用户6288414
2022/01/04
1.3K0
软件方法(下)分析和设计第8章分析 之 分析类图——知识篇(20211227更新)
Python简单验证文本的Zipf分布
齐普夫定律是语言学专家Zipf在研究英文单词出现的频率时,发现如果把单词出现的频率按由大到小的顺序排列,则每个单词出现的频率与它的名次的常数次幂存在简单的反比关系,这种分布就称为Zipf定律,它表明在英语单词中,只有极少数的词被经常使用,而绝大多数词很少被使用。实际上,包括汉语在内的许多国家的语言都有这种特点。这个定律后来在很多领域得到了同样的验证,例如著名的28定律。
周小董
2019/03/25
2.8K0
Python简单验证文本的Zipf分布
推荐阅读
相关推荐
[答疑]监控系统 保安在监视间里面看 这个保安算执行者吗
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档