说明
简单归纳一下最近的学习型对象封装,做一个基类,之后可以基于这个基类继续迭代。
内容
1 关于字典的格式
Python的字典格式写起来太麻烦了,所以我定义了一个简单对象,来取代字典。
字典的赋值方式
a_dict ={}
a_dict['abc'] =1
对象的赋值方式
class Naive:
def __init__(self):
pass
def dict(self):
return self.__dict__
b = Naive()
b.abc =1
后者在赋值的时候简洁多了,在输出的时候可以直接 b.dict()
另外,作为对象还可以给Naive增加更多的方法,比较重要的是sync, 这样使得元数据可以随时的同步到远端持久化。
2 基类对象
以下是一个基类对象
# 目的:作为其他学习、变换对象的基类
class BaseLearnPredict:
def __init__(self,name = None):
self.name = name or 'tem'
self.train_data = Naive()
self.predict_data = Naive()
self.meta = Naive()
self.meta.rule_result = {}
self.meta.summary = {}
self.warning = Naive()
self.trace = []
# Setting Data ---
def train_setattr(self):
pass
def predict_setattr(self):
pass
# 类似于Label这样的数据(不是x,在新数据来的时候不会再有)
def train_setref(self):
pass
# Action ---
# 执行学习功能
def learn(self):
rule_name = rule_dict['rule_name']
the_func = getattr(self, rule_name)
res = the_func(**rule_dict)
self.meta.rule_result[rule_name] = res
rule_dict['trace_type'] = 'learn'
self.trace.append(rule_dict)
return True
def train_transform(self, transform_dict):
rule_name =transform_dict['rule_name']
transform_dict['source'] ='train'
the_func = getattr(self, rule_name)
res_dict = the_func(**transform_dict)
for k in res_dict.keys():
setattr(self.train_data, k, res_dict[k])
transform_dict['trace_type'] = 'transform'
self.trace.append(transform_dict)
return True
def predict_transform(self, transform_dict):
rule_name =transform_dict['rule_name']
transform_dict['source'] ='predict'
the_func = getattr(self, rule_name)
res_dict = the_func(**transform_dict)
for k in res_dict.keys():
setattr(self.predict_data, k, res_dict[k])
return True
# Pipeline ---
# 批量执行
def pipeline_predict_transform(self):
for the_dict in self.transform_trace:
self.predict_transform(the_dict)
def pipeline_train_transform(self):
self.train_describe()
for the_dict in self._trace:
print(the_dict)
if the_dict['trace_type']=='learn':
self.learn(the_dict)
else:
self.train_transform(the_dict)
# Save & Load ---
# 持久化
# 分离transform
def seperate_transform_trace(self):
self.transform_trace = []
for the_dict in self.trace:
if the_dict['trace_type'] == 'transform':
self.transform_trace.append(the_dict)
def save(self, name = None, path = './'):
self.seperate_transform_trace()
name = name or self.meta.name
res_dict = {}
res_dict['meta'] = self.meta
res_dict['trace'] = self.trace
res_dict['transform_trace'] = self.transform_trace
to_pickle(res_dict, name, path )
def load_var_meta(self, name = 'None', path = './'):
var_meta_dict = from_pickle(name, path)
self.meta = var_meta_dict['meta']
# 重载时这个参数放到隐藏
self._trace = var_meta_dict['trace']
self.transform_trace = var_meta_dict['transform_trace']
return True
2.1 初始化
1 self.name = name or ‘tem’ 名字应该是要有的,特别在一个大批的处理中,名字可以作为存储和调用时的id。
2 self.train_data = Naive() 训练部分的数据,应该只在学习/训练阶段使用
3 self.predict_data = Naive() 预测部分的数据,在应用模型时使用
4 self.meta = Naive() 这部分是最为重要的数据,而且尺寸也不大。学习到的知识(数据),以及要依据这些知识进行反变换。这部分是学习的结果,也是应用的依赖。
5 self.meta.rule_result = {} 这是按照规则存放的,具体的元数据。
6 self.meta.summary = {} 一些汇总结果。对用户而言,可以看到一些KPI的数据,对于长期训练来说,这个可以保存不同版本/阶段的模型评估参数。
7 self.warning = Naive() 执行过程中产生的一些警告信息
8 self.trace = [] 这部分应该也放到meta中,这是具体的变化轨迹。这个轨迹记录了开发时的具体步骤,在应用时,根据这个进行反变换或者再学习。
2.2 数据传递入口
数据的传入分为训练与预测两个大的模式,考虑有监督的模式,那么就会分为X和y两部分(如果是无监督,那就可以退化为只有X的模式)。
在设置X的时候,使用
train_setattr
和predict_setattr
在设置y的时候,使用
train_setref
2.3 单步执行
在开发过程中,一定是一步步进行的。这个过程可以分为学习(learn)和变换(transform)。变换又按照训练和预测分为两个方法,本质上处理的内容是完全一样的,只是把结果存在train_data
或predict_data
2.4 管道执行
同样的,也分为pipeline_predict_transform
和pipeline_train_transform
, 但是在这里就蕴含两种差异很大的模式。
模式一:复现较长的变换流程。这个很容易理解,毕竟学习的目的就是为了再次使用。主要用在预测流程上。
模式二:采用同样的超参数进行学习。例如有许多变量,其变换方式是类似的(但是会学习到不同的参数结果)。所以,此时可以载入之前的模板方法(可以是之前做好的一个版本),这样就可以越来越专注于做好一个样本,其他的就“依样画葫芦”。
2.5 存储和载入
存储和载入的一个关键点是把学习过程和变换过程区分,如果是载入的参数,trace会变成_trace。