我写了一个机器学习脚本,我想从命令行控制它。我已经解析了所有选项,例如--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
我希望有人知道如何做到这一点。 非常感谢你!
答案 0 :(得分:0)
参数总是只是字符串。您需要解析字符串以获得可以调用的函数。
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
的交互方式。)
答案 1 :(得分:0)
也许您可以将输入与功能分开。 首先收集用户的输入,然后根据输入运行用户请求的功能。
例如,如果用户运行:
python script.py -e GradientBoostingRegressor
你会这样做:
if args.estimator == "GradientBoostingRegressor":
do stuff...
答案 2 :(得分:0)
虽然@ 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
返回一个类,产生如下错误:
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')
为了避免这些困难,我建议将参数分离为类映射。这应该更容易理解和扩展:
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个班级之间进行选择,default
和const
:
parser.add_argument('-e', action='store_const', default=Lasso(), const=GradientBoostingRegressor())
但这不能概括为更多。 `NARGS = '?'提供3种方式选择 - 默认,const和提供的用户。但是仍然存在将命令行字符串转换为类对象的问题。
Subparsers https://docs.python.org/3/library/argparse.html#sub-commands显示了set_defaults
如何用于设置函数或类。但要使用它,你必须为每个选择定义一个subparser。
一般来说,最好从简单的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 bug或argparse bug,但用户定义的函数或lambda是一个简单的解决方法。