为什么使用scipy.nnls和sklearn.linear_models.LinearRegression会产生不同的结果?超级学习者问题

wb1gzix0  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(210)

我正在尝试用python实现我自己的超级学习者版本。下面是代码:

  1. from sklearn.base import BaseEstimator, RegressorMixin
  2. from sklearn.utils.validation import check_X_y, check_array, check_is_fitted
  3. from sklearn.utils.estimator_checks import check_estimator
  4. from sklearn.model_selection import KFold
  5. from sklearn.pipeline import make_pipeline
  6. from sklearn.preprocessing import StandardScaler
  7. from sklearn import linear_model
  8. from sklearn import neighbors
  9. from sklearn import datasets
  10. import matplotlib.pyplot as plt
  11. from scipy import optimize
  12. from pandas.plotting import scatter_matrix
  13. import numpy as np
  14. import pandas as pd
  15. class SuperLearner(BaseEstimator, RegressorMixin):
  16. def __init__(self, base_estimators):
  17. self.base_estimators = base_estimators
  18. self.meta_learner = linear_model.LinearRegression(positive=True)
  19. self.weights = None
  20. def rss(self, weights, X, y):
  21. y_pred = np.dot(X, weights)
  22. return np.sum((y - y_pred)**2)
  23. def constraint(self, weights):
  24. return np.sum(weights) - 1
  25. def fit(self, X, y):
  26. X, y = check_X_y(X, y)
  27. meta_predictions = np.zeros((X.shape[0], len(self.base_estimators)), dtype=np.float64)
  28. #TODO: modify the number of folds depending on the number of base estimators and the size of the dataset
  29. kf = KFold(n_splits=5)
  30. for i, (tran_idx, val_idx) in enumerate(kf.split(X)):
  31. X_train, X_val = X[tran_idx], X[val_idx]
  32. y_train, y_val = y[tran_idx], y[val_idx]
  33. for j, estimator in enumerate(self.base_estimators):
  34. estimator.fit(X_train, y_train)
  35. meta_predictions[val_idx, j] = estimator.predict(X_val)
  36. guess = np.empty(len(self.base_estimators))
  37. bounds = [(0,1)] * len(self.base_estimators)
  38. result = optimize.minimize(self.rss, guess, args=(meta_predictions, y), method='SLSQP', bounds=bounds, constraints={'type':'eq', 'fun':self.constraint})
  39. print(result.x, np.sum(result.x))
  40. result = optimize.nnls(meta_predictions, y)
  41. print(result[0], np.sum(result[0]))
  42. self.meta_learner.fit(meta_predictions, y)
  43. self.weights= self.meta_learner.coef_
  44. self.weights= self.weights / np.sum(self.weights)
  45. print(self.weights, np.sum(self.weights))
  46. return self
  47. def predict(self, X):
  48. check_is_fitted(self, 'meta_learner')
  49. X = check_array(X)
  50. base_predictions = np.zeros((X.shape[0], len(self.base_estimators)), dtype=np.float64)
  51. for i, estimator in enumerate(self.base_estimators):
  52. base_predictions[:, i] = estimator.predict(X)
  53. return np.dot(base_predictions, self.weights)
  54. def main():
  55. np.random.seed(100)
  56. X, y = datasets.make_friedman1(1000)
  57. ols = linear_model.LinearRegression()
  58. elastic = linear_model.ElasticNetCV()
  59. ridge = linear_model.RidgeCV()
  60. lars = linear_model.LarsCV()
  61. lasso = linear_model.LassoCV()
  62. knn = neighbors.KNeighborsRegressor()
  63. superLeaner = SuperLearner([ols, elastic, ridge, lars, lasso, knn])
  64. superLeaner.fit(X, y)
  65. y_pred = superLeaner.predict(X)
  66. print("MSE: ", np.mean((y_pred - y)**2))
  67. if __name__ == "__main__":
  68. main()

字符串
我使用三种不同的方法来评估每个模型在最终预测中应该具有的权重。虽然scipy.nnls和我使用scipy.minimize实现的优化方法产生了类似的结果,但sklearn的LinearRegression产生的结果完全不同。我甚至在GitHub上查看了LinearRegression的代码,它似乎调用了相同的scipy函数(scipy.nnls)当正参数被设置为true时,就像在这种情况下一样。有人知道为什么吗?

j2datikz

j2datikz1#

try LinearRegression(positive=True,fit_intercept=False)cause fit_intercept default True

相关问题