当使用Pythonclasses作为程序配置结构(其中包含继承class属性)时,save/restore有什么好的方法吗?
When using Python classes as program configuration structures (which includes inherited class attributes), a good way to save/restore?
假设我有一个(简化的)class,如下所示。我将它用于程序配置(超参数)。
# config.py
class Config(object): # default configuration
GPU_COUNT = 1
IMAGES_PER_GPU = 2
MAP = {1:2, 2:3}
def display(self):
pass
# experiment1.py
from config import Config as Default
class Config(Default): # some over-written configuration
GPU_COUNT = 2
NAME='2'
# run.py
from experiment1 import Config
cfg = Config()
...
cfg.NAME = 'ABC' # possible runtime over-writing
# Now I would like to save `cfg` at this moment
我想保存此配置并稍后恢复。恢复时一定要注意成员函数。
1.当我尝试泡菜时:
import pickle
with open('cfg.pk', 'rb') as f: cfg = pickle.load(f)
##--> AttributeError: Can't get attribute 'Config' on <module '__main__'>
我看到了使用 Config
的 class_def
的解决方案,但我希望我可以在不知道 class 定义的情况下恢复配置(例如,导出到 dict 并另存为 JSON)
2。我试图将 class 转换为 dict (这样我就可以导出为 JSON)
cfg.__dict__ # {'NAME': 'ABC'}
vars(cfg) # {'NAME': 'ABC'}
在这两种情况下,都很难访问属性。可能吗?
问题的标题是 "how to convert python class to dict",但我怀疑您真的只是在寻找一种表示(超)参数的简单方法。
到目前为止,最简单的解决方案是不使用 classes。我已经在一些机器学习教程中看到它发生了,但我认为这是一个非常丑陋的 hack。它打破了一些关于 classes 与 objects 的语义,而 pickling 的困难就是由此产生的结果。你用一个简单的 class 怎么样:
class Params(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getstate__(self):
return self
def __setstate__(self, state):
self.update(state)
def copy(self, **extra_params):
return Params(**self, **extra_params)
它可以做 class 方法可以做的一切。预定义的配置只是 objects 你应该在编辑之前复制,如下所示:
config = Params(
GPU_COUNT = 2,
NAME='2',
)
other_config = config.copy()
other_config.GPU_COUNT = 4
或者一步完成:
other_config = config.copy(
GPU_COUNT = 4
)
适用于 pickle(尽管您 将 需要在您的源代码中的某处包含 Params
class),并且您也可以轻松编写 load
和 save
方法用于 Params
class 如果你想使用 JSON.
简而言之,不要将 class 用于实际上只是 object 的东西。
谢天谢地,@evertheylen 的回答对我来说很棒。但是,代码returns在p.__class__ = Params
时出错,所以我稍微修改如下。我认为它的工作方式相同。
class Params(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getstate__(self):
return self
def __setstate__(self, state):
self.update(state)
def copy(self, **extra_params):
lhs = Params()
lhs.update(self)
lhs.update(extra_params)
return lhs
你可以做到
config = Params(
GPU_COUNT = 2,
NAME='2',
)
other_config = config.copy()
other_config.GPU_COUNT = 4
假设我有一个(简化的)class,如下所示。我将它用于程序配置(超参数)。
# config.py
class Config(object): # default configuration
GPU_COUNT = 1
IMAGES_PER_GPU = 2
MAP = {1:2, 2:3}
def display(self):
pass
# experiment1.py
from config import Config as Default
class Config(Default): # some over-written configuration
GPU_COUNT = 2
NAME='2'
# run.py
from experiment1 import Config
cfg = Config()
...
cfg.NAME = 'ABC' # possible runtime over-writing
# Now I would like to save `cfg` at this moment
我想保存此配置并稍后恢复。恢复时一定要注意成员函数。
1.当我尝试泡菜时:
import pickle
with open('cfg.pk', 'rb') as f: cfg = pickle.load(f)
##--> AttributeError: Can't get attribute 'Config' on <module '__main__'>
我看到了使用 Config
的 class_def
的解决方案,但我希望我可以在不知道 class 定义的情况下恢复配置(例如,导出到 dict 并另存为 JSON)
2。我试图将 class 转换为 dict (这样我就可以导出为 JSON)
cfg.__dict__ # {'NAME': 'ABC'}
vars(cfg) # {'NAME': 'ABC'}
在这两种情况下,都很难访问属性。可能吗?
问题的标题是 "how to convert python class to dict",但我怀疑您真的只是在寻找一种表示(超)参数的简单方法。
到目前为止,最简单的解决方案是不使用 classes。我已经在一些机器学习教程中看到它发生了,但我认为这是一个非常丑陋的 hack。它打破了一些关于 classes 与 objects 的语义,而 pickling 的困难就是由此产生的结果。你用一个简单的 class 怎么样:
class Params(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getstate__(self):
return self
def __setstate__(self, state):
self.update(state)
def copy(self, **extra_params):
return Params(**self, **extra_params)
它可以做 class 方法可以做的一切。预定义的配置只是 objects 你应该在编辑之前复制,如下所示:
config = Params(
GPU_COUNT = 2,
NAME='2',
)
other_config = config.copy()
other_config.GPU_COUNT = 4
或者一步完成:
other_config = config.copy(
GPU_COUNT = 4
)
适用于 pickle(尽管您 将 需要在您的源代码中的某处包含 Params
class),并且您也可以轻松编写 load
和 save
方法用于 Params
class 如果你想使用 JSON.
简而言之,不要将 class 用于实际上只是 object 的东西。
谢天谢地,@evertheylen 的回答对我来说很棒。但是,代码returns在p.__class__ = Params
时出错,所以我稍微修改如下。我认为它的工作方式相同。
class Params(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getstate__(self):
return self
def __setstate__(self, state):
self.update(state)
def copy(self, **extra_params):
lhs = Params()
lhs.update(self)
lhs.update(extra_params)
return lhs
你可以做到
config = Params(
GPU_COUNT = 2,
NAME='2',
)
other_config = config.copy()
other_config.GPU_COUNT = 4