使用 argparser 解析的 类 初始化对象
Initialize Objects with classes parsed with argparser
我写了一个机器学习脚本,我想从命令行控制它。我已经解析了所有选项,例如 --optimize 400,以在 RandomizedSearchCV 网格上执行 400 次迭代。
但是,我正在努力解决一件事:我想从命令行选择我的估算器,例如 GradientBoostingRegressor() 或 Lasso()。我尝试了两件事:
def cli()
p = arg.ArgumentParser(description="Perform ML regression.")
p.add_argument("-e","--estimator",default=Lasso(), help="Choose between Lasso() and GradientBoostingRegressor()")
return p.parse_args()
args = cli()
estimator = args.estimator
但是当我尝试打开程序时:
python script.py -e GradientBoostingRegressor()
我收到错误,因为有“()”,也没有 (),因为它被解释为字符串。
我尝试的另一件事是:
def cli()
p = arg.ArgumentParser(description="Perform ML regression.")
group = p.add_mutually_exclusive_group()
group.add_argument("-SVR", nargs='?', default = SVR(),
help="Choose Suppor Vector Regression")
group.add_argument("-GBR", nargs='?', default = GradientBoostingRegressor())
return p.parse_args()
args = cli()
但现在我不知道如何访问估算器,而且当我这样调用程序时似乎也是这样:
python script.py -SVR
命名空间"args"持有SVR=None和GBR=GradientBoostingRegressor(default_GBR_options),这与我想要的正好相反
理想情况下,我可以在命令行中在 -SVR 和 -GBR 之间进行选择,解析器会像我的其他选项一样传递它,我可以像这样初始化一个对象:
estimator = args.estimator
我希望任何人都知道如何做到这一点。
非常感谢!
参数始终只是字符串。您需要解析字符串以获得可以调用的函数。
import argparse
def Lasso():
print("Lasso!")
def GradientBoostingRegressor():
print("GradientBoostingRegressor!")
class GetEstimator(argparse.Action):
estimators = {
"Lasso": Lasso,
"GBR": GradientBoostingRegressor,
}
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.estimators[values])
p = argparse.ArgumentParser()
p.add_argument( "-e", "--estimator", action=GetEstimator, default=Lasso, choices=GetEstimaor.estimators.keys())
args = p.parse_args()
args.estimator()
(这取代了之前使用 type
参数将字符串参数映射到函数的答案。我误解了 type
和 choices
的交互方式。)
也许您可以将输入与功能分开。
首先收集用户的输入,然后根据输入运行用户请求的功能。
例如,如果用户 运行:
python script.py -e GradientBoostingRegressor
你会做:
if args.estimator == "GradientBoostingRegressor":
do stuff...
虽然@chepner 对 type
的使用是对 argparse
的一种很好的使用,但这种方法可能很难正确理解。
正如所写,它在 add_argument
方法中引发错误:
Traceback (most recent call last):
File "stack50799294.py", line 18, in <module>
p.add_argument("-e", "--estimator", type=estimators.get, default=Lasso, choices=estimators.keys())
File "/usr/lib/python3.6/argparse.py", line 1346, in add_argument
type_func = self._registry_get('type', action.type, action.type)
File "/usr/lib/python3.6/argparse.py", line 1288, in _registry_get
return self._registries[registry_name].get(value, default)
TypeError: unhashable type: 'dict'
它正在测试 type
参数是 registry
中的一个项目,还是一个有效的函数。我不确定为什么会引发此错误。
def mytype(astr):
return estimators.get(astr)
在 type=mytype
中效果更好。但还有更进一步的难度 - choices
是 keys()
,字符串。但是 mytype
returns 一个 class,产生如下错误:
0942:~/mypy$ python3 stack50799294.py -e GBR
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: <class '__main__.GradientBoostingRegressor'> (choose from 'Lasso', 'GBR')
为了避免这些困难,我建议将参数分离到 class 映射。这样应该更容易理解和展开:
import argparse
class Lasso():pass
class GradientBoostingRegressor():pass
# Map an easy-to-type string to each function
estimators = {
'Lasso': Lasso,
'GBR': GradientBoostingRegressor
}
p = argparse.ArgumentParser(description="Perform ML regression.")
p.add_argument("-e", "--estimator", default='Lasso', choices=estimators.keys())
args = p.parse_args()
print(args)
estimator = estimators.get(args.estimator, None)
if estimator is not None:
print(type(estimator()))
样本:
0946:~/mypy$ python3 stack50799294.py -e GBR
Namespace(estimator='GBR')
<class '__main__.GradientBoostingRegressor'>
0946:~/mypy$ python3 stack50799294.py
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e Lasso
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e lasso
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: 'lasso' (choose from 'Lasso', 'GBR')
const
参数
您可以使用 store_const
在 2 个 class、一个 default
和一个 const
之间进行选择:
parser.add_argument('-e', action='store_const', default=Lasso(), const=GradientBoostingRegressor())
但这不能推广到更多。 `nargs='?'提供 3 种方式选择 - 默认、const 和用户提供。但是仍然存在将命令行字符串转换为 class 对象的问题。
Subparsers,https://docs.python.org/3/library/argparse.html#sub-commands,展示了如何使用 set_defaults
来设置函数或 classes。但是要使用它,您必须为每个选择定义一个子解析器。
一般来说,最好从简单的 argparse
方法开始,接受字符串和字符串选择,然后进行映射。使用更多 argparse
功能可以稍后使用。
get
错误
@chepner's
错误与 Python 如何查看 d.get
方法有关。尽管它看起来像一个方法,但它以某种方式看到了 dict
而不是方法:
In [444]: d = {}
In [445]: d.get(d.get)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-445-c6d679ba4e8d> in <module>()
----> 1 d.get(d.get)
TypeError: unhashable type: 'dict'
In [446]: def foo(astr):
...: return d.get(astr)
...:
...:
In [447]: d.get(foo)
这可以被视为基本 python 错误或 argparse 错误,但用户定义的函数或 lambda 很容易解决。
我写了一个机器学习脚本,我想从命令行控制它。我已经解析了所有选项,例如 --optimize 400,以在 RandomizedSearchCV 网格上执行 400 次迭代。 但是,我正在努力解决一件事:我想从命令行选择我的估算器,例如 GradientBoostingRegressor() 或 Lasso()。我尝试了两件事:
def cli()
p = arg.ArgumentParser(description="Perform ML regression.")
p.add_argument("-e","--estimator",default=Lasso(), help="Choose between Lasso() and GradientBoostingRegressor()")
return p.parse_args()
args = cli()
estimator = args.estimator
但是当我尝试打开程序时:
python script.py -e GradientBoostingRegressor()
我收到错误,因为有“()”,也没有 (),因为它被解释为字符串。
我尝试的另一件事是:
def cli()
p = arg.ArgumentParser(description="Perform ML regression.")
group = p.add_mutually_exclusive_group()
group.add_argument("-SVR", nargs='?', default = SVR(),
help="Choose Suppor Vector Regression")
group.add_argument("-GBR", nargs='?', default = GradientBoostingRegressor())
return p.parse_args()
args = cli()
但现在我不知道如何访问估算器,而且当我这样调用程序时似乎也是这样:
python script.py -SVR
命名空间"args"持有SVR=None和GBR=GradientBoostingRegressor(default_GBR_options),这与我想要的正好相反
理想情况下,我可以在命令行中在 -SVR 和 -GBR 之间进行选择,解析器会像我的其他选项一样传递它,我可以像这样初始化一个对象:
estimator = args.estimator
我希望任何人都知道如何做到这一点。 非常感谢!
参数始终只是字符串。您需要解析字符串以获得可以调用的函数。
import argparse
def Lasso():
print("Lasso!")
def GradientBoostingRegressor():
print("GradientBoostingRegressor!")
class GetEstimator(argparse.Action):
estimators = {
"Lasso": Lasso,
"GBR": GradientBoostingRegressor,
}
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.estimators[values])
p = argparse.ArgumentParser()
p.add_argument( "-e", "--estimator", action=GetEstimator, default=Lasso, choices=GetEstimaor.estimators.keys())
args = p.parse_args()
args.estimator()
(这取代了之前使用 type
参数将字符串参数映射到函数的答案。我误解了 type
和 choices
的交互方式。)
也许您可以将输入与功能分开。 首先收集用户的输入,然后根据输入运行用户请求的功能。
例如,如果用户 运行:
python script.py -e GradientBoostingRegressor
你会做:
if args.estimator == "GradientBoostingRegressor":
do stuff...
虽然@chepner 对 type
的使用是对 argparse
的一种很好的使用,但这种方法可能很难正确理解。
正如所写,它在 add_argument
方法中引发错误:
Traceback (most recent call last):
File "stack50799294.py", line 18, in <module>
p.add_argument("-e", "--estimator", type=estimators.get, default=Lasso, choices=estimators.keys())
File "/usr/lib/python3.6/argparse.py", line 1346, in add_argument
type_func = self._registry_get('type', action.type, action.type)
File "/usr/lib/python3.6/argparse.py", line 1288, in _registry_get
return self._registries[registry_name].get(value, default)
TypeError: unhashable type: 'dict'
它正在测试 type
参数是 registry
中的一个项目,还是一个有效的函数。我不确定为什么会引发此错误。
def mytype(astr):
return estimators.get(astr)
在 type=mytype
中效果更好。但还有更进一步的难度 - choices
是 keys()
,字符串。但是 mytype
returns 一个 class,产生如下错误:
0942:~/mypy$ python3 stack50799294.py -e GBR
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: <class '__main__.GradientBoostingRegressor'> (choose from 'Lasso', 'GBR')
为了避免这些困难,我建议将参数分离到 class 映射。这样应该更容易理解和展开:
import argparse
class Lasso():pass
class GradientBoostingRegressor():pass
# Map an easy-to-type string to each function
estimators = {
'Lasso': Lasso,
'GBR': GradientBoostingRegressor
}
p = argparse.ArgumentParser(description="Perform ML regression.")
p.add_argument("-e", "--estimator", default='Lasso', choices=estimators.keys())
args = p.parse_args()
print(args)
estimator = estimators.get(args.estimator, None)
if estimator is not None:
print(type(estimator()))
样本:
0946:~/mypy$ python3 stack50799294.py -e GBR
Namespace(estimator='GBR')
<class '__main__.GradientBoostingRegressor'>
0946:~/mypy$ python3 stack50799294.py
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e Lasso
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e lasso
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: 'lasso' (choose from 'Lasso', 'GBR')
const
参数
您可以使用 store_const
在 2 个 class、一个 default
和一个 const
之间进行选择:
parser.add_argument('-e', action='store_const', default=Lasso(), const=GradientBoostingRegressor())
但这不能推广到更多。 `nargs='?'提供 3 种方式选择 - 默认、const 和用户提供。但是仍然存在将命令行字符串转换为 class 对象的问题。
Subparsers,https://docs.python.org/3/library/argparse.html#sub-commands,展示了如何使用 set_defaults
来设置函数或 classes。但是要使用它,您必须为每个选择定义一个子解析器。
一般来说,最好从简单的 argparse
方法开始,接受字符串和字符串选择,然后进行映射。使用更多 argparse
功能可以稍后使用。
get
错误
@chepner's
错误与 Python 如何查看 d.get
方法有关。尽管它看起来像一个方法,但它以某种方式看到了 dict
而不是方法:
In [444]: d = {}
In [445]: d.get(d.get)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-445-c6d679ba4e8d> in <module>()
----> 1 d.get(d.get)
TypeError: unhashable type: 'dict'
In [446]: def foo(astr):
...: return d.get(astr)
...:
...:
In [447]: d.get(foo)
这可以被视为基本 python 错误或 argparse 错误,但用户定义的函数或 lambda 很容易解决。