Prechádzať zdrojové kódy

docs: 接口测试,提供了更详细的数据和接口结果(重要)

tscRubbish 4 rokov pred
rodič
commit
ba3dc50191

+ 1101 - 0
参考/Java接口文档.md

@@ -0,0 +1,1101 @@
+# 接口文档
+
+
+
+## 1.	Response类
+
+作用:响应客户端请求,对返回的数据做一个封装。
+
+私有成员变量:时间戳和状态码
+
+子类:ErrorRes和NormalRes
+
+```java
+public class Response {
+    private final Long timestamp = System.currentTimeMillis(); //常量,时间戳
+    private int status;//状态码
+
+    public Response(int status) {
+        this.status = status;
+    }
+}
+```
+
+
+
+### ErrorRes
+
+作用:执行请求发生错误或异常时,向客户端返回该对象。
+
+继承来的变量:时间戳和状态码
+
+自身的成员变量:错误码和错误信息。
+
+父类:Response
+
+```java
+public class ErrorRes extends Response{
+    private int errorCode;
+    private String msg;
+
+    public ErrorRes() {
+        super(HttpStatus.BAD_REQUEST.value());
+        this.errorCode = 40000;
+    }
+    /**
+     * 
+     * @param errorCode
+     * @param msg
+     * 40000: Unknown error
+     * 40001: NullPointer exception
+     * 40002: Server error
+     */
+    public ErrorRes(int errorCode, String msg) {
+        this();
+        this.errorCode = errorCode;
+        this.msg = msg;
+    }
+}
+```
+
+### NormalRes
+
+作用:正常执行客户端请求结束后,向客户端返回该对象。
+
+继承来的变量:时间戳和状态码
+
+自身的成员变量:封装为Object类的数据
+
+父类:Response
+
+```java
+public class NormalRes extends Response {
+    private Object data;
+
+    public NormalRes() {
+        super(HttpStatus.OK.value());
+    }
+    
+    public NormalRes(Object data) {
+        super(HttpStatus.OK.value());
+        this.data = data;
+    }
+}
+```
+
+
+
+## 2.	Controller接口
+
+### 2.1 用户登录注册 
+
+### LoginController(/userManage)
+
+
+
+#### GET:/login
+
+###### 参数:
+
+- String:username
+- String:password
+
+###### 返回类型:LoginPojo
+
+- bool:loginStatus
+- String:userId
+- String:jwtToken
+
+###### 说明:
+
+调用loginService.verifyUser进行登录,返回NormalRes或ErrorRes;
+
+如果用户验证不通过,errorCode=40001。
+
+
+
+> 注	LoginPojo中 jwtToken 的作用:
+>
+> JSON Web Token (JWT)是一种基于 token 的认证方案。
+> JWT是一种Token的编码算法,服务器端根据一个密码和算法生成Token,然后发给客户端,客户端负责后面每次请求都在HTTP header里面带上这个Token,服务器负责验证这个Token是不是合法的,有没有过期等,并可以解析出subject和claim里面的数据。
+> ————————————————
+> 原文链接:https://blog.csdn.net/wlddhj/article/details/79726001
+
+
+
+#### POST:/register
+
+###### 参数:
+
+- User:user
+  - String:id
+  - String:username
+  - String:password
+
+###### 说明:
+
+注册,调用loginService.addUser添加新用户
+
+如果添加失败,返回errorCode=40002
+
+
+
+### 2.2 模型配置
+
+### ConfigController(/api/config)
+
+作用:ConfigController的这些接口针对结构化文件,详见学长论文P45—P48。
+
+> Web 层的 ConfigController 定义了对外提供的配置信息新增接口,通过接口调用,可以实现机器学习特征值配置的持久化保存,前端请求 ConfigController 时传递的参数包含用户填写的配置名称、文件名称、模型类别、特征字段等属性的 ConfigVO,ConfigController 依赖 ConfigService 类来实现具体业务逻辑,ConfigService 调用 data 层的 ConfigDao 类实现对前端传递的特征选择的持久化保存。
+
+
+
+#### POST: /add  
+
+**添加机器学习模型**
+
+###### 参数:
+
+- ConfigVO:configVO
+  - String:id
+  - String:fileInfoId           //文件id
+  - String:userId               //用户id
+  - String:modelTypeId   //模型类Id
+  - String:confName        //自定义模型名
+  - List\<String> fieldIds       //选择训练的特征及特征描述
+
+###### 返回类型:String
+
+###### 说明:
+
+调用configService.addConfig,ConfigService 又调用ConfigDao 类,最后为用户添加一个机器学习模型。
+
+添加失败返回ErrorRes(40002)
+
+添加成功返回NormalRes(configId)
+
+
+
+#### GET: /get/all
+
+**获取用户已有的所有机器学习模型**
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<ConfigPojo>
+
+- String:fileId
+- String:fileName
+- String:configId
+- String:modelTypeId
+- String:modelTypeName
+- String:confName
+- List\<HeaderInfo> featureList
+  - int:id
+  - int:fileInfoId                            //文件Id
+  - String:fieldName                    //文件头字段信息
+  - String:aliasName
+  - String:fieldDes                        //文件的描述信息
+  - double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+  - int:conOrDis                           //表示field类型,0离散,1连续,2时间
+  - String:fieldType                     //值类型
+  - String:valueInfo                    //离散值的取值或者连续值的范围
+
+###### 说明:
+
+根据用户ID,调用ConfigService.getAllConfigs,并返回用户已有的所有机器学习配置模型。
+
+返回类型NormalRes(List\<ConfigPojo>)
+
+
+
+#### GET: /get/all_new
+
+**获取用户已有的所有机器学习模型,但比/get/all 返回的数据更精简**
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<_ConfigPojo>
+
+- String:fileId
+- String:fileName
+- String:configId
+- String:confName
+
+###### 说明:
+
+getAllConfig的更新版,同样也是返回该用户的所有机器学习模型设置,但返回的信息更简单,只包含这些模型的名称与Id。
+
+调用ConfigService._getAllConfigs
+
+返回类型NormalRes(List\<_ConfigPojo>)
+
+
+
+
+
+#### GET: /get/one/config
+
+**根据模型Id,获取某个机器学习模型的配置信息**
+
+###### 参数:
+
+- String:configId
+
+###### 返回类型:ConfigDetilePojo
+
+- String:configId
+- String:modelTypeId
+- String:modelTypeName
+- String:modelDes
+- String:modelDetileDes
+- List\<HeaderInfo> featureList
+  - int:id
+  - int:fileInfoId                            //文件Id
+  - String:fieldName                    //文件头字段信息
+  - String:aliasName
+  - String:fieldDes                        //文件的描述信息
+  - double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+  - int:conOrDis                           //表示field类型,0离散,1连续,2时间
+  - String:fieldType                     //值类型
+  - String:valueInfo                    //离散值的取值或者连续值的范围
+- List\<ConfigModelPojo> modelInfos
+  - String:modelName
+  - String:modelDetailName
+  - int:trainedStatus
+
+###### 说明:
+
+获得某个机器学习模型的详细配置信息。
+
+调用ConfigService.getConfigInfoByConfigId()
+
+返回类型NormalRes(ConfigDetilePojo)
+
+
+
+
+
+#### GET: /change
+
+**改变某个机器学习模型的配置信息**
+
+###### 参数
+
+- String:configId
+- String:confName
+- List\<String>:trainFeatureList
+
+###### 返回类型:Response
+
+###### 说明:
+
+改变单个机器学习模型的配置信息
+
+调用ConfigService.changeConfig()
+
+如果保存失败,则返回ErrorRes(40002)
+
+
+
+#### GET: /delete
+
+**删除用户的某个机器学习模型**
+
+###### 参数:
+
+- String:configId
+
+###### 返回类型:Boolean
+
+###### 说明:
+
+根据configId删除某个机器学习模型
+
+调用configService.deleteConfigById()
+
+如果操作失败,则返回ErrorRes(),即默认的ErrorRes对象,错误码为40000。
+
+
+
+#### GET: /get/features
+
+**用户配置机器学习模型时进行自动化特征选择,然后查询这些自动化生成的特征信息**
+
+###### 参数:
+
+- String:fileId
+- String:fieldName
+
+###### 返回类型:List\<HeaderInfo>
+
+- int:id
+- int:fileInfoId                            //文件Id
+- String:fieldName                    //文件头字段信息
+- String:aliasName
+- String:fieldDes                        //文件的描述信息
+- double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+- int:conOrDis                           //表示field类型,0离散,1连续,2时间
+- String:fieldType                     //值类型
+- String:valueInfo                    //离散值的取值或者连续值的范围
+
+###### 说明:
+
+该接口的参与过程参见学长论文P48。
+
+用户配置机器学习模型时进行自动化特征选择,然后查询这些自动化生成的特征信息。
+
+调用configService.getSelectedFeature()
+
+如果操作失败,则返回ErrorRes(),即默认的ErrorRes对象,错误码为40000。
+
+
+
+### 2.3 结构化文件(机器学习)
+
+### FileController(/api/file)
+
+详见学长论文P41—P44页。
+
+> 分析训练模块作为本系统的核心模块,在本系统中起着重要作用。
+>
+> 文件管理模块实现的文件相关功能都是为了通过分析训练模块来进行具体的分析功能和机器学习训练功能,……
+>
+> **(1)数据分析子模块** 
+>
+> 该子模块是负责自动化数据分析和数理函计分析两个功能点的主要模块。 在结构化文件上传之后,该子模块负责对结构化文件内容的字段进行分析,……
+>
+> FileController 为 web 层中的定义的组件接口,用于提供给前端的接口定义。
+
+
+
+#### POST: /upload
+
+**用户上传结构化文件**
+
+###### 参数:
+
+- String:userId
+- MultipartFile:file
+- String:fileName
+
+###### 返回类型:int
+
+###### 说明:
+
+大型文件加载接口,调用FileService.uploadFile()
+
+通过FileHelper获得从MultipartFile获得File类型和fileType
+
+如果fileType等于csv,调用csvLoader,否则调用SASLoader加载
+
+这里调用涉及到的CsvAdapter是scala实现,继承SparkConnect
+
+出现异常可能返回ErrorRes(40000)和ErrorRes(40002)。
+
+
+
+#### POST: /upload/bigfile
+
+**用户上传大型的结构化文件**
+
+###### 参数:
+
+- String:userId
+- String:fileLoc
+- String:fileName
+
+###### 返回类型:int
+
+###### 说明:
+
+大型文件加载接口,直接调用csvAdapter.Csv2Parquet()
+
+
+
+#### GET: /get/all
+
+**获得用户所有已上传的文件信息**
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<FileNamePojo>
+
+- String:fileId
+- String:fileName
+
+###### 说明:
+
+获得用户所有文件列表,包括文件名和文件ID
+
+调用fileService.getAllFiles()
+
+
+
+#### GET:/get/allfileandfunc
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:FileAndFuncInfoPojo
+
+- List\<FileNamePojo>:fileNamePojos;
+  - String:fileId
+  - String:fileName
+- List\<FuncInfo>:funcInfos;
+  - int:id
+  - String:funcDes
+  - String:funcName
+  - int:flagOfType                //0:String,1:trucDouble,2:all
+  - int:flagOfConorDis        //0离散,1连续,2:all
+
+###### 说明:
+
+作用见学长论文P42.
+
+获取所有文件名列表和FuncInfo列表
+
+调用fileService.getAllFilesAndFunc()
+
+
+
+#### GET:/get/detail
+
+**获取文件详细信息**
+
+###### 参数:
+
+- String:fileId
+
+###### 返回类型:FileDetailPojo
+
+- String:fileName
+- Date:createTime
+- HashMap<String,String>:fileStrucInfo
+- List\<HeaderInfo>:headerInfos
+  - int:id
+  - int:fileInfoId                            //文件Id
+  - String:fieldName                    //文件头字段信息
+  - String:aliasName
+  - String:fieldDes                        //文件的描述信息
+  - double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+  - int:conOrDis                           //表示field类型,0离散,1连续,2时间
+  - String:fieldType                     //值类型
+  - String:valueInfo                    //离散值的取值或者连续值的范围
+
+###### 说明:
+
+获取文件详细信息
+
+调用FileService.getFileDetailInfo()
+
+getFileDetailInfo()调用包括fileInfoDao.findById()和headerInfoDao.findByFileInfoId()
+
+```java
+val fileInfo = fileInfoDao.findById(fileId);
+val headerInfos = headerInfoDao.findByFileInfoId(fileId);
+return new FileDetailPojo(fileInfo.getFilename(), fileInfo.getUploadTime(), new Json2Object().Json2HashMap(fileInfo.getFileStrucInfo()), headerInfos);
+```
+
+
+
+
+
+#### GET:/analysis
+
+###### 方法名:analysis
+
+###### 参数:
+
+- String:fileId
+
+###### 返回类型:FileDetailPojo
+
+- String:fileName
+- Date:createTime
+- HashMap<String,String>:fileStrucInfo
+- List\<HeaderInfo>:headerInfos
+  - int:id
+  - int:fileInfoId                            //文件Id
+  - String:fieldName                    //文件头字段信息
+  - String:aliasName
+  - String:fieldDes                        //文件的描述信息
+  - double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+  - int:conOrDis                           //表示field类型,0离散,1连续,2时间
+  - String:fieldType                     //值类型
+  - String:valueInfo                    //离散值的取值或者连续值的范围
+
+###### 说明:
+
+调用fileService.analysis()进行文件分析
+
+调用fileService.getFileDetailInfo()返回文件数据
+
+fileService.analysis()调用FileAnalysis.fileAnalysis()
+
+FileAnalysis由Scala实现,继承SparkConnect
+
+
+
+#### GET:/analysis/fields1
+
+###### 方法名:analysisOfFields
+
+###### 参数:
+
+- String[]:fieldIds
+
+###### 返回类型:HashMap<String, HashMap<String, Object>>
+
+###### 说明:
+
+for test 数据分布
+
+调用FileService.getFieldDistribution()进行文件数据分布分析
+
+FileService.getFieldDistribution()调用FileAnalysis.getFieldDistribution()
+
+FileAnalysis由Scala实现,继承SparkConnect
+
+
+
+#### GET:/analysis/fields
+
+###### 方法名:analysisOfFields1
+
+###### 参数:
+
+- String[]:fieldIds
+- String:funcId
+
+###### 返回值:Object
+
+| 数据分布       | getFieldDistribution        |
+| -------------- | --------------------------- |
+| 散点图         | getFieldScatterDiagram      |
+| 数据统计       | getFieldDescription         |
+| 偏度峰度       | getFieldSkewnessAndKurtosis |
+| 皮尔森相关系数 | getFieldCorr                |
+
+###### 说明:
+
+调用FileService.getFieldAnalysis()进行字段分析
+
+根据funcId查询函数信息,获得funcName
+
+funcName包括:数据分布,散点图,数据统计,偏度峰度,皮尔森相关系数
+
+
+
+#### GET:/delete
+
+**删除上传的文件**
+
+###### 方法名:delete
+
+###### 参数:
+
+- String:fileId
+
+###### 返回值:Boolean
+
+###### 说明:
+
+调用fileService.deleteFileById(),通过fileInfoDao查询并删除
+
+返回删除结果
+
+
+
+#### POST:/update
+
+**更新上传的文件信息**
+
+###### 方法名:updateFileInfo
+
+###### 参数:
+
+- HeaderInfoUpdatedPojo:headerInfoUpdatedPojo
+  - List\<InnerHeaderInfo>:headerInfo
+    - String:id
+    - String:fileInfoId                            //文件Id
+    - String:fieldName                    //文件头字段信息
+    - String:aliasName
+    - String:fieldDes                        //文件的描述信息
+    - double:nullsRatio                  //field的空值比例,为百分比 如10.00%
+    - String:fieldType                     //值类型
+    - String:valueInfo                    //离散值的取值或者连续值的范围
+    - Boolean:aliasNameEditable
+    - Boolean:fieldDesEditable
+  - List\<Integer>:headerNeedUpdate
+
+###### 返回类型:Boolean
+
+###### 说明:
+
+调用fileService.updateAllHeaders(List\<InnerHeaderInfo> innerHeaderInfos, List\<Integer> headerToUpdate)
+
+在updateAllHeaders中对每个innerheaderInfo调用updateHeaderInfo,进行更新
+
+如果更新失败,返回false
+
+
+
+### 2.4 图片文件(深度学习)
+
+### PicController(/api/picture)
+
+#### POST:/upload
+
+**上传图片**
+
+###### 方法名:fileLoader
+
+###### 参数:
+
+- String:userId
+- MutipartFile:file
+- String:fileName
+
+###### 返回参数:NormalRes&ErrorRes
+
+###### 说明:
+
+调用pictureService.uploadPic(userId,file,filename)
+
+pictureService.uploadPic()中会创建BufferedOutputStream对象
+
+会异步创建MyThread线程,执行parseZipFile(fileAbsolutePath, userId, picAbsolutePath);
+
+如果加载失败则返回ErrorRes(40002)6
+
+
+
+
+
+#### GET:/get/all/proj
+
+**获取该用户所有图片列表,但图片信息只包括图片ID和图片名**
+
+###### 方法名:getAllProj
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<PicFilePojo>
+
+- String:fileId
+- String:fileName
+
+###### 说明:
+
+调用PictureService.getAllProj()获取该用户所有PicFile列表
+
+PictureService.getAllProj()通过PictureFileDao获得userId的List\<PicFile>,然后转化为List\<PicFilePojo>
+
+
+
+#### GET:/get/one/proj
+
+**根据图片ID,获取该图片的分类信息(图片类别名、类别ID)**
+
+###### 方法名:getOneProj
+
+###### 参数:
+
+- String:picFileId
+
+###### 返回类型:List\<PicCategoryPojo>
+
+- String:categoryId
+- String:categoryName
+
+###### 说明:
+
+调用PictureService.getOneProj(picFileId)
+
+PictureService.getOneProj()通过PictureCategoryDao获得picFileId的List\<PicCategory>,然后转化为List\<PicCategoryPojo>
+
+
+
+#### GET:/get/pics
+
+**根据图片分类(标签),获取该类所有图片的信息**
+
+###### 方法名:getPicInfos
+
+###### 参数:
+
+- String:picTag
+
+###### 返回类型:List\<PicInfoPojo>
+
+- String:picId
+- String:picName
+- String:picLoc
+
+###### 说明:
+
+根据picTag,调用PictureService.getAllPicAddr()
+
+通过PictureInfoDao.findByCategoryId获得PicInfoPojo的
+
+
+
+#### GET:/update/picinfo
+
+**更新图片信息**
+
+###### 方法名:updateFileInfo
+
+###### 参数:
+
+- String:picId
+- String:picCategory
+- String:picTag
+
+###### 返回类型:NormalRes&ErrorRes
+
+###### 说明:
+
+调用PictureService.updatePicInfo进行更新
+
+如果更新失败,则返回ErrorRes(40002)
+
+
+
+### 2.5 模型相关ModelController(/api/model)
+
+> 学长论文P47
+>
+> ModelController 向外提供的服务可以实现对机器学习和深度学习的模型信息的持久化保存。ModelController 类的业务逻辑的实现依赖于 ModelService,ModelService 分别调用 ModelDao 和 DLModelDao 的服务将两种 模型信息持久化保存在数据库中。
+
+
+
+#### POST:/add
+
+**添加机器学习模型**
+
+###### 方法名:addModel
+
+###### 参数:
+
+- ModelVO:model
+  - String:id
+  - String:modelTypeId                 //模型类别
+  - String:configId                          //文件配置ID
+  - String:fileInfoId                        //文件信息ID
+  - String:modelName                  //自定义训练模型名
+  - Boolean:isTrained                   //是否训练
+  - String:modelPath                    //具体训练出的model
+  - HashMap<String,String>:resOfModel    //模型训练的result
+  - HashMap<String,String>:arguments      //模型的具体参数取值
+
+###### 返回类型:NormalRes(int)&ErrorRes
+
+###### 说明:
+
+调用ModelService.addModel(model)
+
+如果添加失败,则返回ErrorRes(40002)
+
+如果添加成功,则返回模型ID=Model.getId()
+
+
+
+
+
+#### GET:/get/all
+
+**获得某个用户的所有(机器学习)模型**
+
+###### 方法名:getAllModel
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<ModelPojo>
+
+- String:configid
+- String:configName                   //文件配置名
+- String:modelTypeId                 //模型类别
+- String:modelTypeName               
+- String:modelDetailName
+- String:modelDetailDes  
+- String:modelDes
+- String:modelId            
+- String:modelName                  //自定义训练模型名
+- int:trainedStatus                      //是否训练
+- HashMap<String,String>:arguments      //模型的具体参数取值
+- HashMap<String,String>:resOfModel    //模型训练的result
+
+###### 说明:
+
+调用modelService.getAllModelByUserId(userId)
+
+返回该用户所有Model信息列表
+
+
+
+
+
+#### GET:/get/all/dl
+
+**获得所有深度学习模型**
+
+###### 方法名:getAllDLModel
+
+###### 参数:
+
+- String:userId
+
+###### 返回类型:List\<DLGeneralModelPojo>
+
+- String:modelId
+- String:modelName
+- String:fileId
+- String:fileName
+- boolean:isTrain
+- boolean:hasResult
+
+###### 说明:
+
+调用ModelService.getAllGeneralModelByUserId(userId)获得所有DL深度学习Model信息
+
+ModelService.getAllGeneralModelByUserId中,枚举userId的所有PicFile,DLModel
+
+通过MapReduce生成DLGeneralModelPojo
+
+
+
+
+
+#### GET:/get/detail/dl
+
+**根据模型ID,获得某个深度学习模型的详细信息**
+
+###### 方法名:getDLDetaiModel
+
+###### 参数:
+
+- String:modelId
+
+###### 返回类型:DLModelPojo
+
+- String:modelTypeId                 //模型类别
+- String:picFileId                          //文件信息ID
+- String:configName                   //文件配置名        
+- String:modelName                  //自定义训练模型名
+- boolean:isTrained                      //是否训练
+- String:modelPath    
+- HashMap<String,String>:resOfModel    //模型训练的result
+- HashMap<String,String>:arguments      //模型的具体参数取值
+
+###### 说明:
+
+调用ModelService.getDLModelDetailById,返回具体的DL深度学习模型信息
+
+
+
+#### POST:/add/dl
+
+**添加深度学习模型**
+
+###### 方法名:addDLModel
+
+###### 参数:
+
+- DLModelVO:model
+  - String:id
+  - String:modelTypeId                 //模型类别
+  - String:configId                          //文件配置ID
+  - String:fileInfoId                        //文件信息ID
+  - String:modelName                  //自定义训练模型名
+  - Boolean:isTrained                   //是否训练
+  - String:modelPath                    //具体训练出的model
+  - HashMap<String,String>:resOfModel    //模型训练的result
+  - HashMap<String,String>:arguments      //模型的具体参数取值
+
+###### 返回类型:NormalRes(int)&ErrorRes
+
+###### 说明:
+
+调用ModelService.addDlModel(model)添加DL模型
+
+如果添加失败,则返回ErrorRes(40002)
+
+如果添加成功,则返回模型ID=Model.getId()
+
+
+
+#### GET:/change
+
+**改变模型名称和类型**
+
+###### 方法名:changeModel
+
+###### 参数:
+
+- String:modelId
+- String:modelName
+- String:modelTypeId
+
+###### 返回类型:NormalRes&ErrorRes
+
+###### 说明:
+
+调用ModelService.changeModel(modelId,modelName,modelTypeId),对Model信息进行修改
+
+用modelId获得现有Model,修改modelName和modelTypeId,然后保存
+
+根据修改结果返回NormalRes或ErrorRes
+
+
+
+#### GET:/get/models
+
+**获得某个模型类型的名称**
+
+###### 方法名:getModelType
+
+###### 参数:
+
+- String:modelTypeName
+
+###### 返回类型:List\<ModelType>
+
+- int:id
+- String:modelTypeName
+- String:modelDetailName
+- String:arguments
+- String:modelDetailDes
+- String:modelDes
+
+###### 说明:
+
+调用ModelService.getModelTypeByModelTypeName()获得ModelType类型信息
+
+ModelService.getModelTypeByModelTypeName()中,通过modelTypeDao通过TypeName查询
+
+
+
+
+
+#### GET:/train
+
+**使用机器学习模型进行训练,并返回训练结果**
+
+###### 方法名:trainModel
+
+###### 参数:
+
+- String:modelId
+
+###### 返回类型:boolean
+
+###### 说明:
+
+调用modelService.trainTheModel()对模型进行训练
+
+modelService.trainTheModel()中,首先修改model的TrainedStatus
+
+根据modelDetailName,包含如下的模型训练类型:
+
+- LogisticRegression:逻辑回归
+- DecisionTree:决策树
+- RandomForest:随机森林
+- GBDT
+- K-means
+- MultilayerPerceptronClassifier:(MLPC)多层感知器分类器
+- NaiveBayes:朴素贝叶斯
+- RandomForestRegression:随机森林回归
+
+boolean返回类型返回训练结果
+
+
+
+#### GET:/delete
+
+**通过模型ID删除某个机器学习/深度学习模型**
+
+###### 方法名:deleteModelByModelId
+
+###### 参数:
+
+- String:modelId
+
+###### 返回类型:boolean
+
+###### 说明:
+
+调用ModelService.deleteModel(),删除modelId对应的Model
+
+ModelService.deleteModel()通过ModelDao进行查找和删除
+
+返回删除结果
+
+
+
+#### POST:/use/upload
+
+**上传模型需要的测试文件**
+
+###### 方法名:uploadTestFile
+
+###### 参数:
+
+- String:userId
+- MultipartFile:file
+- String:fileName
+
+###### 返回类型:TestFileValuePojo
+
+- String:fileId
+- List<Map<String, String>>:values
+
+###### 说明:
+
+调用**FileService**.uploadTestFile(),上传测试文件
+
+fileService.uploadTestFile()中,先调用FileService.uoloadFile上传文件。再通过返回值FileId,通过FileInfoDao获取文件位置。
+
+然后调用csvAdapter.parquetFileReader获取文件内容values,创建TestFileValuePojo类型返回值
+
+
+
+#### GET:/use
+
+**使用模型进行预测**
+
+> 学长论文P51—P52
+>
+> ModelController 组件调用 ModelService 接口来实现模型预测的业务逻辑,ModelService 依赖于 FitTestData 进行具体的模型预测,FitTestData 对测试数据的读取需要调用 FileInfoDAO 组件,对模型的加载需要调用到 ModelDAO 组件。
+
+###### 方法名:useModel
+
+###### 参数:
+
+- String:fileId
+- String:ModelId
+
+###### 返回类型:List<Map<String, String>>
+
+###### 说明:
+
+调用modelService.useModel(),使用模型对文件进行处理
+
+modelService.useModel()中调用FitTestData.transformData
+
+FitTestData由Scala实现,继承SparkConnect
+
+不过数据转换后,会删除fileId对应的源文件
+

+ 246 - 0
参考/Python接口文档.md

@@ -0,0 +1,246 @@
+# Python接口文档
+
+### Response
+
+```
+def response(data={}, code=200):
+    resp = {
+        "timestamp": int(round(time.time() * 1000)),
+        "status": code,
+        "data": data
+    }
+    response = make_response(jd(resp))
+    response.headers['Status Code'] = resp['status']
+    response.headers['Content-Type'] = "application/json"
+    return response
+```
+
+### Controller
+
+#### GET:/get/file
+
+###### 方法名:application.hello()
+
+###### 参数:
+
+- 文件Id:fileId
+
+###### 实现:
+
+```
+@app.route('/get/file', methods=['GET'])
+def hello():
+    value = request.args
+    app.logger.info('value: %s', value)
+    try:
+        return response(fileInfoDao.getFileInfoById(value.get('fileId')))
+    except Exception as error:
+        return response({}, 400)
+```
+
+其中fileInfoDao是FileInfo类的实例,用于获得文件信息
+
+否则返回status code=400
+
+#### GET:/api/model/dl/train
+
+###### 方法名:application.train()
+
+###### 参数:
+
+- 模型Id:modelId
+
+###### 实现:
+
+深度学习模型训练
+
+```python
+@app.route('/api/model/dl/train', methods=['GET'])
+def train():
+    value = request.args
+    app.logger.info('value: %s', value)
+    try:
+        # args
+        modelId = value.get('modelId')
+        modelEntity = dlModelDao.getModelById(modelId)
+        print("model: ", modelEntity)
+        # pic entity
+        print(modelEntity[2])
+        picEntity = picFileDao.getPicFileById(str(modelEntity[2]))
+        print("pic: ", picEntity)
+        # model entity
+        modelTypeEntity = modelTypeDao.getModelTypeById(str(modelEntity[1]))
+        print("modelType: ", modelTypeEntity)
+        # args
+        modelArgs = json.loads(modelEntity[7])
+        epochs = int(modelArgs['epochs'])
+        steps_per_epoch = int(modelArgs['steps_per_epoch'])
+        valid_steps = int(modelArgs['valid_steps'])
+        # train location
+        trainLoc = picEntity[3]
+        modelDetailName = modelTypeEntity[2]
+        trainGen = picHelper.trainGen(trainLoc)
+        # calculate time
+        startTime = datetime.datetime.now()
+        if modelDetailName == 'CNN':
+            base = Cnn.Cnn(trainGen, epochs, steps_per_epoch, valid_steps)
+            accs, model = base.train()
+        elif modelDetailName == 'VGG':
+            base = Vgg.Vgg(trainGen, epochs, steps_per_epoch, valid_steps)
+            accs, model = base.train()
+        elif modelDetailName == 'HirRnn':
+            base = HirRnn.HirRnn(trainGen, epochs, steps_per_epoch, valid_steps)
+            accs, model = base.train()
+        else:
+            raise Exception
+        endTime = datetime.datetime.now()
+        #path = hdfsHelper.saveToHDFS(model,modelEntity[3])
+        path = "/Users/cyz/Documents/idea_workspace/Desktop/glaucus/glaucus/python/src/model/"+modelId+".h5"
+        model.save(path)
+        # print(model)
+        # payload = {'model': model, 'modelId': 4,'dlOrNot':1}
+        # r = requests.get('http://localhost:8080/api/model/savemodel', params=payload)
+        # r.encoding = 'utf-8'
+        # content = r.text
+        # print(content)
+        dlModelDao.setModelPath(modelId,path)
+        dlModelDao.setModelResult(modelId, accs, (endTime-startTime).seconds)
+        dlModelDao.setModelTrained(modelId, True)
+        return response(True)
+    except Exception as error:
+        print(error)
+        return response({}, 400)
+```
+
+从DlModelDAo通过modelId获得模型信息modelEntity,然后根据modelEntity获得图片信息picEntity和模型类型信息modelTypeEntity。
+
+提取出相关训练信息,比如路径。根据模型细节:CNN、VGG、HirRnn进行深度学习,然后对结果模型进行保存,并通过DLModelDao的更改数据库信息
+
+#### GET:/api/config/get/features
+
+###### 方法名:application.featureSelection()
+
+###### 参数:
+
+- String:fileId
+- String:fieldName
+- String:methodId
+
+###### 返回数据:array
+
+- fieldName
+- value
+- id
+
+###### 实现:
+
+特征选择获取
+
+```
+@app.route('/api/config/get/features', methods=['GET'])
+def featureSelection():
+    value = request.args
+    app.logger.info('value: %s', value)
+    try:
+        fileId = value.get('fileId')
+        fieldName = value.get('fieldName')
+        methodId = value.get('methodId')
+        fileEntity = fileInfoDao.getFileInfoById(fileId)
+        print(fileEntity)
+        fileLoc = fileEntity[1]
+        # read parquet file
+        processor = FileProcessor(fileLoc)
+        (x, y, names) = processor.processor(fieldName)
+        featureSelector = FeatureSelector(x, y, names)
+        # train the feature
+        if methodId == 'RL':
+            res = featureSelector.selectWithRandomizedLasso()
+        elif methodId == 'RF':
+            res = featureSelector.selectWithRandomForest()
+        else:
+            raise Exception()
+        print(res)
+        resData = list(map(lambda pair: {
+            'fieldName': str(pair[1]),
+            'value': pair[0],
+            'id': str(headerInfoDao.getByFileIdAndFieldName(fileId, str(pair[1]))[0])
+        }, res))
+        size = len(resData)
+        return response(resData[:int(size * 0.2)])
+    except Exception as error:
+        print(error)
+        return response({}, 400)
+```
+
+fileInfoDao是FileInfo类的实例,用于通过fileId获得文件信息,同时获取文件位置fileLoc等参数
+
+这里通过preprocess目录下的类FileProcess对FileLoc下的文件进行处理
+
+FileProcess.\__init__()通过Spark对文件进行读取
+
+FileProcess.process()用fieldName对文件进行处理,返回的三元组(x,y,name)用于特征选择类FeatureSelector的初始化参数
+
+然后根据methodId的值:RL(随机罗森)、RF(随机森林)分别调用FeatureSelector的selectWithRandomizedLasso()和selectWithRandomForest()
+
+最后选择前20%的特征,返回其数组列表
+
+#### GET:/api/automl
+
+###### 方法名:application.autoMl()
+
+###### 参数:
+
+- String:fileId
+- String:fieldId
+- String:modelId
+
+###### 实现:
+
+自动化机器学习
+
+```
+@app.route('/api/automl', methods=['GET'])
+def autoMl():
+    value = request.args
+    app.logger.info('value: %s', value)
+    try:
+        fileId = value.get('fileId')
+        modelId = value.get('modelId')
+        fieldId = value.get('fieldId')
+        headerEntity = headerInfoDao.getHeaderInfoById(fieldId)
+        fileEntity = fileInfoDao.getFileInfoById(fileId)
+        file_loc = fileEntity[1]
+        traget_feature = headerEntity[2]
+        # get files
+        dc = DataCleaning.DataCleaning(file_loc, traget_feature)
+        X, y, is_classification = dc.dataTrans()
+        if is_classification:
+            classifier = Classification.AutoClassification(X, y)
+            score, time = classifier.fit()
+        else:
+            regressor = Regression.AutoRegression(X, y)
+            score, time = regressor.fit()
+
+        print("Accuracy score: ", score)
+        print("Cost time: ", time)
+        modelDao.setModelTrained(modelId, True)
+        modelDao.setModelResult(modelId, score, other_key='CostTime', other_value=time.total_seconds())
+        return response()
+    except Exception as error:
+        print(error)
+        return response({}, 400)
+```
+
+headInfoDao是HeadInfo类的实例,其他Dao类似
+
+headInfoDao通过fieldId获得headerEntity头部信息,提取出目标特征
+
+fileInfoDao通过fileId获得fileEntity头部信息,提取出文件位置
+
+创建DataCleaning实例,dataTrans()对数据进行清洗和转化
+
+如果分类任务,则调用Classification.AutoClassification
+
+否则为回归任务,调用Regression.AutoRegression
+
+然后通过modelDao对model模型信息进行修改,标记为已训练,保存训练结果

BIN
参考/接口测试md/接口调用测试&说明.assets/hdfs文件查看.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件getDetail.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件getall.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件上传.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件上传2.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件字段分布2.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件字段分析.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/文件数理函数分析.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/用户注册.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/用户登录.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/皮尔森相关系数分析.jpg


BIN
参考/接口测试md/接口调用测试&说明.assets/自动化特征选择.jpg


+ 92 - 65
参考/接口调用测试与说明.md → 参考/接口测试md/接口调用测试与说明.md

@@ -14,9 +14,9 @@
 
 登录成功后,会返回userId,需要本地缓存,用于其他接口
 
-<img src="E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\用户注册.jpg" alt="用户注册" style="zoom:50%;" />
+![用户注册](./接口调用测试&说明.assets/用户注册.jpg)
 
-<img src="E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\用户登录.jpg" alt="用户登录" style="zoom:50%;" />
+![用户登录](./接口调用测试&说明.assets/用户登录.jpg)
 
 #### 文件上传
 
@@ -24,7 +24,7 @@
 
 如果要重新上传,先用hdfs命令删除
 
-<img src="E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\文件上传2.jpg" alt="文件上传2" style="zoom:50%;" />
+![文件上传2](./接口调用测试&说明.assets/文件上传2.jpg)
 
 在postman里,点击file右侧可以选择text类型或file类型,file类型可以选择文件
 
@@ -45,33 +45,33 @@ bin/hdfs dfs -rm -r /data/java_compile/*
 #删除所有文件
 ```
 
-![hdfs文件查看](E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\hdfs文件查看.jpg)
+![hdfs文件查看](./接口调用测试&说明.assets/hdfs文件查看.jpg)
 
 #### 文件查询
 
 getall只需要传入userId,这里传入tsc用户的id
 
-![文件getall](E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\文件getall.jpg)
+![文件getall](./接口调用测试&说明.assets/文件getall.jpg)
 
 getDetail接口传入文件id,这里传入上面upload的event_data.csv的fileId=1
 
-![文件getDetail](E:\大学学习资料\创新创业项目资料\TeamAI-FrontEnd\参考\接口测试md\接口调用测试&说明.assets\文件getDetail.jpg)
+![文件getDetail](./接口调用测试&说明.assets/文件getDetail.jpg)
 
 结果为
 
 ```
 {
-    "timestamp": 1647334283649,
+    "timestamp": 1648474526058,
     "status": 200,
     "data": {
-        "fileName": "event_data",
-        "createTime": "2022-03-15T08:47:52.093+00:00",
+        "fileName": "event",
+        "createTime": "2022-03-15T12:14:20.091+00:00",
         "fileStrucInfo": {
             "totalRows": "754"
         },
         "headerInfos": [
             {
-                "id": 33,
+                "id": 81,
                 "fileInfoId": 1,
                 "fieldName": "frame_index",
                 "aliasName": "",
@@ -82,7 +82,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"79\",\"89992\"]"
             },
             {
-                "id": 34,
+                "id": 82,
                 "fileInfoId": 1,
                 "fieldName": "time",
                 "aliasName": "",
@@ -93,7 +93,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"3.16\",\"3599.68\"]"
             },
             {
-                "id": 35,
+                "id": 83,
                 "fileInfoId": 1,
                 "fieldName": "road",
                 "aliasName": "",
@@ -104,7 +104,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"R\",\"L\"]"
             },
             {
-                "id": 36,
+                "id": 84,
                 "fileInfoId": 1,
                 "fieldName": "lane",
                 "aliasName": "",
@@ -115,7 +115,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"r\",\"m\",\"l\"]"
             },
             {
-                "id": 37,
+                "id": 85,
                 "fileInfoId": 1,
                 "fieldName": "vehicle_class",
                 "aliasName": "",
@@ -126,7 +126,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"car\",\"truck\",\"bus\"]"
             },
             {
-                "id": 38,
+                "id": 86,
                 "fileInfoId": 1,
                 "fieldName": "vehicle_id",
                 "aliasName": "",
@@ -137,7 +137,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"20\",\"46862\"]"
             },
             {
-                "id": 39,
+                "id": 87,
                 "fileInfoId": 1,
                 "fieldName": "event_type",
                 "aliasName": "",
@@ -146,17 +146,6 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "conOrDis": 0,
                 "fieldType": "string",
                 "valueInfo": "[\"cruise\",\"overdrive\"]"
-            },
-            {
-                "id": 40,
-                "fileInfoId": 1,
-                "fieldName": "duration",
-                "aliasName": "",
-                "fieldDes": "",
-                "nullsRatio": 0.0,
-                "conOrDis": 0,
-                "fieldType": "string",
-                "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
             }
         ]
     }
@@ -236,17 +225,17 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
 
 ```
 {
-    "timestamp": 1647335223563,
+    "timestamp": 1648474489138,
     "status": 200,
     "data": {
-        "fileName": "event_data",
-        "createTime": "2022-03-15T09:02:05.093+00:00",
+        "fileName": "event",
+        "createTime": "2022-03-15T12:14:20.091+00:00",
         "fileStrucInfo": {
             "totalRows": "754"
         },
         "headerInfos": [
             {
-                "id": 73,
+                "id": 81,
                 "fileInfoId": 1,
                 "fieldName": "frame_index",
                 "aliasName": "",
@@ -257,7 +246,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"79\",\"89992\"]"
             },
             {
-                "id": 74,
+                "id": 82,
                 "fileInfoId": 1,
                 "fieldName": "time",
                 "aliasName": "",
@@ -268,7 +257,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"3.16\",\"3599.68\"]"
             },
             {
-                "id": 75,
+                "id": 83,
                 "fileInfoId": 1,
                 "fieldName": "road",
                 "aliasName": "",
@@ -279,7 +268,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"R\",\"L\"]"
             },
             {
-                "id": 76,
+                "id": 84,
                 "fileInfoId": 1,
                 "fieldName": "lane",
                 "aliasName": "",
@@ -290,7 +279,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"r\",\"m\",\"l\"]"
             },
             {
-                "id": 77,
+                "id": 85,
                 "fileInfoId": 1,
                 "fieldName": "vehicle_class",
                 "aliasName": "",
@@ -301,7 +290,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"car\",\"truck\",\"bus\"]"
             },
             {
-                "id": 78,
+                "id": 86,
                 "fileInfoId": 1,
                 "fieldName": "vehicle_id",
                 "aliasName": "",
@@ -312,7 +301,7 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "valueInfo": "[\"20\",\"46862\"]"
             },
             {
-                "id": 79,
+                "id": 87,
                 "fileInfoId": 1,
                 "fieldName": "event_type",
                 "aliasName": "",
@@ -321,17 +310,6 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
                 "conOrDis": 0,
                 "fieldType": "string",
                 "valueInfo": "[\"cruise\",\"overdrive\"]"
-            },
-            {
-                "id": 80,
-                "fileInfoId": 1,
-                "fieldName": "duration",
-                "aliasName": "",
-                "fieldDes": "",
-                "nullsRatio": 0.0,
-                "conOrDis": 0,
-                "fieldType": "string",
-                "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
             }
         ]
     }
@@ -348,26 +326,75 @@ getDetail接口传入文件id,这里传入上面upload的event_data.csv的file
 
 参数的含义详见模型类别表model_type
 
-| 类型名                         | 中文名           | 参数列表                           |
-| ------------------------------ | ---------------- | ---------------------------------- |
-| LogisticRegression             | 逻辑回归         | [MaxIter,RegParam,ElasticNetParam] |
-| DecisionTree                   | 决策树           | [Category,TrainingDataSetOccupy]   |
-| RandomForest                   | 随机森林         | [MaxIter,RegParam,ElasticNetParam] |
-| GBDT                           | 梯度提升决策树   | [MaxIter,RegParam,ElasticNetParam] |
-| MultilayerPerceptronClassifier | 多层感知器分类器 | [Category,TrainingDataSetOccupy]   |
-| NaiveBayes                     | 朴素贝叶斯       | [Category,TrainingDataSetOccupy]   |
-| RandomForestRegression         | 随机森林回归     | [Category,TrainingDataSetOccupy]   |
-| K-Means                        | K-均值           | [NumOfCluster,Seed]                |
+| id   | 类型名                         | 中文名           | 参数列表                           |
+| ---- | ------------------------------ | ---------------- | ---------------------------------- |
+|      | LogisticRegression             | 逻辑回归         | [MaxIter,RegParam,ElasticNetParam] |
+|      | DecisionTree                   | 决策树           | [Category,TrainingDataSetOccupy]   |
+|      | RandomForest                   | 随机森林         | [MaxIter,RegParam,ElasticNetParam] |
+|      | GBDT                           | 梯度提升决策树   | [MaxIter,RegParam,ElasticNetParam] |
+|      | MultilayerPerceptronClassifier | 多层感知器分类器 | [Category,TrainingDataSetOccupy]   |
+|      | NaiveBayes                     | 朴素贝叶斯       | [Category,TrainingDataSetOccupy]   |
+|      | RandomForestRegression         | 随机森林回归     | [Category,TrainingDataSetOccupy]   |
+|      | K-Means                        | K-均值           | [NumOfCluster,Seed]                |
 
 #### 分析函数类别
 
 目前分析函数表func_info其他属性意义不明
 
-| 数据分布       |
-| -------------- |
-| 散点图         |
-| 数据统计       |
-| 偏度-峰度      |
-| 皮尔森相关系数 |
-| 平均值         |
+| func_id | 数据分布       |
+| ------- | -------------- |
+|         | 数据分析       |
+|         | 散点图         |
+|         | 数据统计       |
+|         | 偏度-峰度      |
+|         | 皮尔森相关系数 |
+|         | 平均值         |
+
+#### 文件数据分析
+
+这里/analysis/fields1等价于/analysis/fields传入funcId=1
+
+数理函数分析方法与funcId的对应见上**分析函数类别**
+
+数理函数分析需要在int或double字段上计算,否则会报错,需要前端有报错信息
+
+##### GET:/analysis/fields1
+
+调用FileService.getFieldDistribution()进行文件数据分布分析
+
+参数为fieldIds分析字段列表
+
+注意这里是fieldId而不是fileId,容易混淆,同时注意之前的java接口md有误,已更正
+
+**这里的0.0013...应该是字段值的频率**
+
+![文件字段分析](./接口调用测试&说明.assets/文件字段分析.jpg)
+
+第二个更好理解的例子,选用车道占有率(l/m/r)字段
+
+这里distreibution表示车道概率,statistical表示数量统计
+
+![文件字段分布2](.\接口调用测试&说明.assets\文件字段分布2.jpg)
+
+##### GET:/analysis/fields1
+
+调用FileService.getFieldAnalysis()进行字段数理函数分析
+
+这里是散点图分析
+
+![文件数理函数分析](./接口调用测试&说明.assets/文件数理函数分析.jpg)
+
+funcId=5时,即皮尔斯相关系数分析,需要至少两个类型为int或double的字段,否则无结果
+
+![皮尔森相关系数分析](.\接口调用测试&说明.assets\皮尔森相关系数分析.jpg)
+
+#### 模型创建与使用相关
+
+##### GET: /get/features
+
+**用户配置机器学习模型时进行自动化特征选择,然后查询这些自动化生成的特征信息**
+
+这里以高速监控为例,选择分析目标为event_type,返回结果vehicle_class,代表分析车辆类型与事故类型关系
+
+![自动化特征选择](.\接口调用测试&说明.assets\自动化特征选择.jpg)