我正在使用Python 3.6.4
并构建了一个自定义类,我正在进行计算并更改其中一个内部类变量。我注意到它在运行算法时总是正确运行(例如实例化类等)并且总是第二次失败。即使它是连续两次重复的相同行代码。我已经能够以更简单的形式复制错误。
为什么第一个对象中正在更改的lr_space
传播到第二个实例化对象?
class testing(object):
def __init__(self,
n_iter=5,
n_space=10,
model_type="logistic",
lr_space={
"C":(1e-6, 1.0),
"penalty":["l1", "l2"],
},
lr_kws=dict(max_iter=10000, solver="liblinear"),
):
self.n_iter = n_iter
self.n_space = n_space
# Logistic Regression
self.lr_space = lr_space
self.lr_kws = lr_kws
print("", self, self.lr_space,"", sep="\n\t")
self.model_type = model_type.lower()
self.models = self._test_function()
def _test_function(self):
"""
Internal: Label models
Need to extend this for using different hyperparameters
"""
models = list()
self.param_index = OrderedDict()
# Indexing for hyperparameters and models
a = np.ones(self.n_iter*2)
b = np.arange(a.size)
if self.model_type == "logistic":
self.lr_space["C"] = np.linspace(*self.lr_space["C"], self.n_space)
return models
print("=====Instantiating and running `instance_1`=====")
instance_1 = testing()
print("=====Instantiating and running `instance_2`=====")
instance_2 = testing()
输出:
=====Instantiating and running `instance_1`=====
<__main__.testing object at 0x136154400>
{'C': (1e-06, 1.0), 'penalty': ['l1', 'l2']}
=====Instantiating and running `instance_2`=====
<__main__.testing object at 0x127649390>
{'C': array([ 1.00000000e-06, 1.11112000e-01, 2.22223000e-01,
3.33334000e-01, 4.44445000e-01, 5.55556000e-01,
6.66667000e-01, 7.77778000e-01, 8.88889000e-01,
1.00000000e+00]), 'penalty': ['l1', 'l2']}
错误:
-------------------------------------------------- -------------------------
TypeError Traceback(最近一次调用最后一次)
in()
38 instance_1 = testing()
39打印(“=====实例化并运行instance_2
=====”)
---&GT; 40 instance_2 = testing()
<ipython-input-342-24f241984973> in __init__(self, n_iter, n_space, model_type, lr_space, lr_kws)
17 print("", self, self.lr_space,"", sep="\n\t")
18 self.model_type = model_type.lower()
---> 19 self.models = self._test_function()
20
21 def _test_function(self):
<ipython-input-342-24f241984973> in _test_function(self)
31 b = np.arange(a.size)
32 if self.model_type == "logistic":
---> 33 self.lr_space["C"] = np.linspace(*self.lr_space["C"], self.n_space)
34
35
TypeError: linspace() takes from 2 to 6 positional arguments but 11 were given
答案 0 :(得分:0)
如果在init函数中指定lr_space的默认值,则它可以工作:
from collections import OrderedDict
import numpy as np
class testing(object):
def __init__(self,
n_iter=5,
n_space=10,
model_type="logistic",
lr_space=None,
lr_kws=dict(max_iter=10000, solver="liblinear"),
):
if lr_space is None:
lr_space = {
"C":(1e-6, 1.0),
"penalty":["l1", "l2"],
}
self.n_iter = n_iter
self.n_space = n_space
# Logistic Regression
self.lr_space = lr_space
self.lr_kws = lr_kws
print("", self, self.lr_space,"", sep="\n\t")
self.model_type = model_type.lower()
self.models = self._test_function()
def _test_function(self):
"""
Internal: Label models
Need to extend this for using different hyperparameters
"""
models = list()
self.param_index = OrderedDict()
# Indexing for hyperparameters and models
a = np.ones(self.n_iter*2)
b = np.arange(a.size)
if self.model_type == "logistic":
self.lr_space["C"] = np.linspace(*self.lr_space["C"], self.n_space)
return models
print("=====Instantiating and running `instance_1`=====")
instance_1 = testing()
print("=====Instantiating and running `instance_2`=====")
instance_2 = testing()
当您为def __init__(...)
中的参数指定默认值时,会在新实例存在前指定。使用简单的非可变值(例如5
和"logistic"
)时这并不重要,但是如果使用dict,则在实例外部创建对象,然后将其分配给引用在__init__
电话中。
这是一种你应该避免的危险反模式。您可以在此处详细了解:Using a mutable default value as an argument
创建新实例时,会再次分配引用,但它仍引用同一对象。您上面的代码相当于:
default_dict = {
"C":(1e-6, 1.0),
"penalty":["l1", "l2"],
}
class testing(object):
def __init__(self,
n_iter=5,
n_space=10,
model_type="logistic",
lr_space=default_dict,
lr_kws=dict(max_iter=10000, solver="liblinear"),
):
答案 1 :(得分:0)
我最终做的是使用deepcopy
内置的copy
:
import copy
class testing(object):
def __init__(self,
n_iter=5,
n_space=10,
model_type="logistic",
lr_space={
"C":(1e-6, 1.0),
"penalty":["l1", "l2"],
},
lr_kws=dict(max_iter=10000, solver="liblinear"),
):
self.n_iter = n_iter
self.n_space = n_space
# Logistic Regression
self.lr_space = copy.deepcopy(lr_space)
self.lr_kws = lr_kws
print("", self, self.lr_space,"", sep="\n\t")
self.model_type = model_type.lower()
self.models = self._test_function()
def _test_function(self):
"""
Internal: Label models
Need to extend this for using different hyperparameters
"""
models = list()
self.param_index = OrderedDict()
# Indexing for hyperparameters and models
a = np.ones(self.n_iter*2)
b = np.arange(a.size)
if self.model_type == "logistic":
self.lr_space["C"] = np.linspace(*self.lr_space["C"], self.n_space)
return models