Browse Source

Merge pull request 'fix: 模型演化调整数据集的位置' (#70) from dev into master

dev-lhz
cp3hnu 1 year ago
parent
commit
722ae3b6ab
3 changed files with 379 additions and 50 deletions
  1. +338
    -0
      react-ui/mock/model.ts
  2. +1
    -1
      react-ui/package.json
  3. +40
    -49
      react-ui/src/pages/Model/components/ModelEvolution/utils.tsx

+ 338
- 0
react-ui/mock/model.ts View File

@@ -0,0 +1,338 @@
import { defineMock } from 'umi';

export default defineMock({
'POST /api/mmp/modelDependency/queryModelAtlas': {
code: 200,
msg: '操作成功',
data: {
current_model_id: 29,
exp_ins_id: 229,
version: 'v0.2.0',
ref_item: null,
train_task: {
name: '模型训练测试导出0529',
ins_id: 229,
task_id: 'model-train-5d76f002',
},
train_dataset: [
{
dataset_id: 20,
dataset_version: 'v0.1.0',
dataset_name: '手写体识别模型依赖测试训练数据集',
},
],
train_params: ['256', '2'],
train_image: '172.20.32.187/machine-learning/pytorch:pytorch_1.9.1_cuda11.1_detection_aim',
test_dataset: [
{
dataset_id: 20,
dataset_version: 'v0.1.0',
dataset_name: '手写体识别模型依赖测试训练数据集',
},
],
project_dependency: {
url: 'https://openi.pcl.ac.cn/somunslotus/somun202304241505581.git',
name: 'somun202304241505581',
branch: 'train_ci_test',
},
parent_models_map: [
{
model_id: 29,
model_version: 'v0.1.0',
model_name: 'mnist模型演化',
},
],
parent_models: [
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.1.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: null,
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
],
children_models: [
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.3.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.31.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.4.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.6.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.7.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.5.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.10.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
{
current_model_id: 29,
exp_ins_id: null,
version: 'v0.11.0',
ref_item: null,
train_task: {},
train_dataset: [],
train_params: [],
train_image: null,
test_dataset: [],
project_dependency: {},
parent_models_map: [],
parent_models: [],
children_models: [],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
],
workflow_id: null,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl',
file_name: 'mnist_epoch1_0.00.pkl',
file_size: '176.63 KB',
create_by: 'admin',
create_time: '2024-06-12T06:09:56.000+00:00',
},
},
],
workflow_id: 144,
model_version_dependcy_vo: {
name: 'mnist模型演化',
description: '手写体识别模型演化',
available_range: 0,
model_type: '37',
model_tag: '46',
model_type_name: 'PyTorch',
model_tag_name: '图像转文本',
url: 'models/admin/1718172760650/mnist_cnn.pt',
file_name: 'mnist_cnn.pt',
file_size: '176.76 KB',
create_by: 'admin',
create_time: '2024-06-12T06:12:42.000+00:00',
},
},
},
});

+ 1
- 1
react-ui/package.json View File

@@ -33,7 +33,7 @@
"serve": "umi-serve",
"start": "cross-env UMI_ENV=dev max dev",
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev",
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev",
"start:mock": "cross-env REACT_APP_ENV=dev UMI_ENV=dev max dev",
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev",
"start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev",
"test": "jest",


+ 40
- 49
react-ui/src/pages/Model/components/ModelEvolution/utils.tsx View File

@@ -9,8 +9,8 @@ export const vGap = nodeHeight + 20;
export const hGap = nodeHeight + 20;
export const ellipseWidth = nodeWidth;

// 数据集节点矩形数组
const datasetRects: Rect[] = [];
// 数据集节点
const datasetNodes: NodeConfig[] = [];

export enum NodeType {
current = 'current',
@@ -22,8 +22,8 @@ export enum NodeType {
}

export type Rect = {
x: number;
y: number;
x: number; // 矩形中心的 x 坐标
y: number; // 矩形中心的 y 坐标
width: number;
height: number;
};
@@ -142,14 +142,6 @@ export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData {
normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`;
normalizedData.label = getLabel(normalizedData);
normalizedData.style = getStyle(NodeType.current);
// let first1 = { ...normalizedData.children[0] };
// let first2 = { ...normalizedData.children[0] };
// let first3 = { ...normalizedData.children[0] };
// first1.current_model_id = 202020;
// first2.current_model_id = 202021;
// first3.current_model_id = 202022;
// normalizedData.children.push(first1, first2, first3);

normalizeChildren(normalizedData.children as ModelDepsData[]);

// 将 parent_models 转换成树形结构
@@ -191,14 +183,12 @@ export function getGraphData(data: ModelDepsData): GraphData {
const edges: EdgeConfig[] = [];
Util.traverseTree(treeLayoutData, (node: NodeConfig, parent: NodeConfig) => {
const data = node.data as ModelDepsData;
console.log('data', data);

// 当前模型显示数据集和项目
if (data.model_type === NodeType.current) {
addDatasetDependency(data, node, nodes, edges);
addProjectDependency(data, node, nodes, edges);
} else if (data.model_type === NodeType.children) {
adjustChildrenPosition(node);
adjustDatasetPosition(node);
}
nodes.push({
...data,
@@ -224,17 +214,17 @@ const addDatasetDependency = (
) => {
const { train_dataset, test_dataset } = data;
train_dataset.forEach((item) => {
item.id = `$DTrain_${item.dataset_id}`;
item.id = `$DTrain_${item.dataset_id}_${item.dataset_version}`;
item.model_type = NodeType.trainDataset;
item.style = getStyle(NodeType.trainDataset);
});
test_dataset.forEach((item) => {
item.id = `$DTest_${item.dataset_id}`;
item.id = `$DTest_${item.dataset_id}_${item.dataset_version}`;
item.model_type = NodeType.testDataset;
item.style = getStyle(NodeType.testDataset);
});

datasetRects.length = 0;
datasetNodes.length = 0;
const len = train_dataset.length + test_dataset.length;
[...train_dataset, ...test_dataset].forEach((item, index) => {
const node = { ...item };
@@ -246,9 +236,10 @@ const addDatasetDependency = (
fittingString(node.dataset_version, ellipseWidth - 12, 8);

const half = len / 2 - 0.5;
node.x = currentNode.x! - (half - index) * (ellipseWidth + hGap);
node.x = currentNode.x! - (half - index) * (ellipseWidth + hGap / 2);
node.y = currentNode.y! - nodeHeight - vGap;
nodes.push(node);
datasetNodes.push(node);
edges.push({
source: currentNode.id,
target: node.id,
@@ -256,12 +247,6 @@ const addDatasetDependency = (
targetAnchor: 3,
type: 'cubic-vertical',
});
datasetRects.push({
x: node.x - ellipseWidth / 2,
y: node.y - nodeHeight / 2,
width: ellipseWidth,
height: nodeHeight,
});
});
};

@@ -275,7 +260,7 @@ const addProjectDependency = (
const { project_dependency } = data;
if (project_dependency?.url) {
const node = { ...project_dependency };
node.id = `$P_${node.url}`;
node.id = `$P_${node.url}_${node.branch}`;
node.model_type = NodeType.project;
node.type = 'rect';
node.label = fittingString(node.name, nodeWidth - 12, 8);
@@ -296,42 +281,48 @@ const addProjectDependency = (
};

// 判断两个矩形是否相交
function isRectanglesIntersect(rect1: Rect, rect2: Rect) {
return !(
rect1.x + rect1.width < rect2.x ||
rect1.x > rect2.x + rect2.width ||
rect1.y + rect1.height < rect2.y ||
rect1.y > rect2.y + rect2.height
);
function isRectanglesOverlap(rect1: Rect, rect2: Rect) {
const a2x = rect1.x + rect1.width / 2;
const a2y = rect1.y + rect1.height / 2;
const b1x = rect2.x - rect2.width / 2;
const b1y = rect2.y - rect2.height / 2;
return b1y <= a2y && b1x <= a2x;
}

// 判断子节点是否与数据集节点重叠
function isChildrenIntersectDataset(rects: Rect[], childrenRect: Rect) {
for (const r of rects) {
if (isRectanglesIntersect(r, childrenRect)) {
return r;
function isChildrenOverlapDataset(nodes: NodeConfig[], childrenRect: Rect) {
for (const node of nodes) {
const rect = { x: node.x!, y: node.y!, width: nodeWidth, height: nodeHeight };
if (isRectanglesOverlap(rect, childrenRect)) {
return childrenRect;
}
}

return null;
}

// 计算子节点位置
function adjustChildrenPosition(node: NodeConfig) {
// 调整数据集位置
function adjustDatasetPosition(node: NodeConfig) {
const nodeRect = {
x: node.x! - nodeWidth / 2,
y: node.y! - nodeHeight / 2,
x: node.x!,
y: node.y!,
width: nodeWidth,
height: nodeHeight,
};
const overlapRect = isChildrenIntersectDataset(datasetRects, nodeRect);
const overlapRect = isChildrenOverlapDataset(datasetNodes, nodeRect);
if (overlapRect) {
const offsetY = nodeRect.y - overlapRect.y;
const space = 10; //(vGap + Math.abs(offsetY) - nodeHeight) / 2;
if (offsetY >= 0) {
node.y = node.y! + (nodeHeight - offsetY + space);
} else {
node.y = node.y! - (nodeHeight - Math.abs(offsetY) + space);
}
console.log(node);

const adjustRect = {
x: overlapRect.x - nodeWidth - hGap / 2,
y: overlapRect.y,
width: overlapRect.width,
height: overlapRect.height,
};
const lastNode = datasetNodes[datasetNodes.length - 1] as NodeConfig;
const distance = lastNode.x! - adjustRect.x;
datasetNodes.forEach((item) => {
item.x = item.x! - distance;
});
}
}

Loading…
Cancel
Save