openGauss源码解析(181)

openGauss源码解析:AI技术(28)

8.6.4 关键源码解析

1. 项目结构

AI Engine侧涉及的主要文件路径为openGauss-server/src/gausskernel/dbmind/tools/predictor,其文件结构如表8-13所示。

表8-13 AI Engine文件结构

文件结构

说明

install

部署所需文件路径

install/ca_ext.txt

证书配置文件

install/requirements-gpu.txt

使用GPU(graphics processing unit,图形处理器)训练依赖库列表

install/requirements.txt

使用CPU训练依赖库列表

install/ssl.sh

证书生成脚本

python

项目代码路径

python/certs.py

加密通信

python/e_log

系统日志路径

python/log

模型训练日志路径

python/log.conf

配置文件

python/model.py

机器学习模型

python/run.py

服务端主函数

python/saved_models

模型训练checkpoint

python/settings.py

工程配置文件

python/uploads

Curl传输的文件存放路径

内核侧主要涉及的文件路径为openGauss-server/src/gausskernel/optimizer/util/learn,其文件结构如表8-14所示。

表8-14 内核端主要文件结构

文件结构

说明

comm.cpp

通信层代码实现

encoding.cpp

数据编码

ml_model.cpp

通用模型调用接口

plan_tree_model.cpp

树状模型调用接口

2. 训练流程

内核侧的模型训练接口通过ModelTrainInternal函数实现,该函数的关键部分如下:

static void ModelTrainInternal(const char* templateName, const char* modelName, ModelAccuracy** mAcc)

{

/* 对于树形模型调用对应的训练接口 */

char* trainResultJson = TreeModelTrain(modelinfo, labels);

/* 解析返回结果 */

ModelTrainInfo* info = GetModelTrainInfo(jsonObj);

cJSON_Delete(jsonObj);

/* 更新模型信息 */

Relation modelRel = heap_open(OptModelRelationId, RowExclusiveLock);

UpdateTrainRes(values, datumsMax, datumsAcc, nLabel, mAcc, info, labels);

HeapTuple modelTuple = SearchSysCache1(OPTMODEL, CStringGetDatum(modelName));

HeapTuple newTuple = heap_modify_tuple(modelTuple, RelationGetDescr(modelRel), values, nulls, replaces);

simple_heap_update(modelRel, &newTuple->t_self, newTuple);

CatalogUpdateIndexes(modelRel, newTuple);

}

内核侧的树状模型训练接口通过TreeModelTrain函数实现,核心代码如下:

char* TreeModelTrain(Form_gs_opt_model modelinfo, char* labels)

{

char* filename = (char*)palloc0(sizeof(char) * MAX_LEN_TEXT);

char* buf = NULL;

/* configure阶段 */

ConfigureModel(modelinfo, labels, &filename);

/* 将编码好的数据写入临时文件 */

SaveDataToFile(filename);

/* Train阶段 */

buf = TrainModel(modelinfo, filename);

return buf;

}

AI Engine侧配置的Web服务的URI是/configure,训练阶段的URI是/train.下面的代码段展示了训练过程。

def fit(self, filename):

keras.backend.clear_session()

set_session(self.session)

with self.graph.as_default():

# 根据模型入参和出参维度变化情况,判断是否需要初始化模型

feature, label, need_init = self.parse(filename)

os.environ['CUDA_VISIBLE_DEVICES'] = '0'

epsilon = self.model_info.make_epsilon()

if need_init: # 冷启动训练

epoch_start = 0

self.model = self._build_model(epsilon)

else: # 增量训练

epoch_start = int(self.model_info.last_epoch)

ratio_error = ratio_error_loss_wrapper(epsilon)

ratio_acc_2 = ratio_error_acc_wrapper(epsilon, 2)

self.model = load_model(self.model_info.model_path,

custom_objects={'ratio_error': ratio_error, 'ratio_acc': ratio_acc_2})

self.model_info.last_epoch = int(self.model_info.max_epoch) + epoch_start

self.model_info.dump_dict()

log_path = os.path.join(settings.PATH_LOG, self.model_info.model_name + '_log.json')

if not os.path.exists(log_path):

os.mknod(log_path, mode=0o600)

# 训练日志记录回调函数

json_logging_callback = LossHistory(log_path, self.model_info.model_name, self.model_info.last_epoch)

# 数据分割

X_train, X_val, y_train, y_val = \

train_test_split(feature, label, test_size=0.1)

# 模型训练

self.model.fit(X_train, y_train, epochs=self.model_info.last_epoch,

batch_size=int(self.model_info.batch_size), validation_data=(X_val, y_val),

verbose=0, initial_epoch=epoch_start, callbacks=[json_logging_callback])

# 记录模型checkpoint

self.model.save(self.model_info.model_path)

val_pred = self.model.predict(X_val)

val_re = get_ratio_errors_general(val_pred, y_val, epsilon)

self.model_logger.debug(val_re)

del self.model

return val_re

posted @ 2024-05-06 10:35  openGauss-bot  阅读(6)  评论(0编辑  收藏  举报