LightGBM
AttributeError: Can\'t pickle local object \'_objective_function_wrapper.<locals>.inner

LightGBM models are normally picklable, but when using a custom objective (and I assume eval_function etc.) they are not picklable.

```
import lightgbm as lgb
import _pickle as pickle
import numpy as np
def custom_asymmetric_objective(y_true, y_pred):
residual = (y_true - y_pred).astype("float")
grad = np.where(residual < 0, -2 * 10.0 * residual, -2 * residual)
hess = np.where(residual < 0, 2 * 10.0, 2.0)
return grad, hess
params = {}
params['objective'] = custom_asymmetric_objective
model = lgb.LGBMRegressor(**params)
X = np.array([[1,2,3,4], [2,3,4,5]]).transpose()
y = np.array([1,2,3,3])
model.fit(X, y)
preds = model.predict(X)
pickle.dump(model, open("model.pkl", "wb"))
print("Done")
```

Leads to:

```
Traceback (most recent call last):
File "lgbm.py", line 22, in <module>
pickle.dump(model, open("model.pkl", "wb"))
AttributeError: Can't pickle local object '_objective_function_wrapper.<locals>.inner'
jon@pseudotensor:~$
```

The problem is the def inside def way of defining the function: https://github.com/microsoft/LightGBM/blob/master/python-package/lightgbm/sklearn.py#L18-L78

The solution is to either:

- remove such def inside def uses and just directly make the function.
- If using a decorator, then you need to use the standard way that allows them to be pickleable via
`functools.wraps`

http://gael-varoquaux.info/programming/decoration-in-python-done-right-decorating-and-pickling.html

That's a useful answer

Without any help

```
import _pickle as pickle
import numpy as np
def custom_asymmetric_objective(y_true, y_pred):
residual = (y_true - y_pred).astype("float")
grad = np.where(residual < 0, -2 * 10.0 * residual, -2 * residual)
hess = np.where(residual < 0, 2 * 10.0, 2.0)
return grad, hess
pickle.dump(custom_asymmetric_objective, open("func.pkl", "wb"))
print("Done")
```

But this still works, so it's still some kind of problem inside LightGBM.