鱼C论坛

 找回密码
 立即注册
查看: 445|回复: 17

stackingregression模型融合遇到问题

[复制链接]
发表于 2024-10-22 21:32:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. from mlxtend.regressor import StackingRegressor
  2. from sklearn.metrics import mean_squared_error

  3. # 初始化基模型
  4. models = [LR_model, dt_model, svm_model, rf_model,knn_model]

  5. print('base model')
  6. for model in models:
  7.     model.fit(X_train, y_train)
  8.     pred = model.predict(X_valid)
  9.     print("loss is {}".format(mean_squared_error(y_valid, pred)))
  10. sclf = StackingRegressor(regressors=models, meta_regressor=ridge)
  11. # 训练回归器
  12. sclf.fit(X_train, y_train)
  13. pred = sclf.predict(X_valid)

  14. print('stacking model')
  15. print("loss is {}".format(mean_squared_error(y_valid, pred)))
  16. plt.scatter(np.arange(len(pred)), pred)
  17. plt.plot(np.arange(len(y_valid)), y_valid)
  18. plt.show()
复制代码

以上是模型融合的代码,以下是报错
  1. ---------------------------------------------------------------------------
  2. NameError                                 Traceback (most recent call last)
  3. Cell In[35], line 12
  4.      10     pred = model.predict(X_valid)
  5.      11     print("loss is {}".format(mean_squared_error(y_valid, pred)))
  6. ---> 12 sclf = StackingRegressor(regressors=models, meta_regressor=ridge)
  7.      13 # 训练回归器
  8.      14 sclf.fit(X_train, y_train)

  9. NameError: name 'ridge' is not defined
复制代码

关于该模型的参数如何选择,翻遍外网也没找到meta_regressor是什么意思
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-22 21:32:29 | 显示全部楼层
您遇到的错误是因为变量 `ridge` 未定义。`meta_regressor` 是用于建立最后的评估模型的回归器,即融合不同基模型预测结果的回归器。可以使用常见的回归模型,比如 `Ridge`、`LinearRegression` 或其他你觉得合适的模型。

以下是如何定义 `ridge` 的示例代码:

  1. from sklearn.linear_model import Ridge

  2. # 定义meta_regressor
  3. ridge = Ridge()

  4. # 初始化基模型列表
  5. models = [
  6.     # 例如:
  7.     # LinearRegression(),
  8.     # RandomForestRegressor(),
  9.     # ...
  10. ]

  11. # 之后的代码保持不变
复制代码


选择 `meta_regressor` 时,可以尝试多种回归模型,看看哪个效果更好。一般来说,选择简单稳健的模型作为 `meta_regressor` 是一个不错的起点,如 `Ridge` 或 `LinearRegression`。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-22 22:04:01 | 显示全部楼层
FishC 发表于 2024-10-22 21:32
您遇到的错误是因为变量 `ridge` 未定义。`meta_regressor` 是用于建立最后的评估模型的回归器,即融合不同 ...
  1. from mlxtend.regressor import StackingRegressor
  2. from sklearn.metrics import mean_squared_error

  3. # 初始化基模型
  4. models = [LR_model, dt_model, svm_model, rf_model,knn_model,simple_dnn_model]

  5. print('base model')
  6. for model in models:
  7.     model.fit(X_train, y_train)
  8.     pred = model.predict(X_valid)
  9.     print("loss is {}".format(mean_squared_error(y_valid, pred)))
  10. sclf = StackingRegressor(regressors=models, meta_regressor=LinearRegression)
  11. # 训练回归器
  12. sclf.fit(X_train, y_train)
  13. pred = sclf.predict(X_valid)

  14. print('stacking model')
  15. print("loss is {}".format(mean_squared_error(y_valid, pred)))
  16. plt.scatter(np.arange(len(pred)), pred)
  17. plt.plot(np.arange(len(y_valid)), y_valid)
  18. plt.show()
复制代码


上述代码提示报错未定义simplednnmodel,
  1. --------------------------------------------------------------------------
  2. NameError                                 Traceback (most recent call last)
  3. Cell In[43], line 5
  4.       2 from sklearn.metrics import mean_squared_error
  5.       4 # 初始化基模型
  6. ----> 5 models = [LR_model, dt_model, svm_model, rf_model,knn_model,simple_dnn_model]
  7.       7 print('base model')
  8.       8 for model in models:

  9. NameError: name 'simple_dnn_model' is not defined
复制代码

但是前面已经定义并执行了这个函数
  1. #dnn模型(train_test_split)
  2. import torch
  3. import torch.nn as nn
  4. from torch.utils import data
  5. from torch.utils.data import Dataset,DataLoader
  6. from torch import optim

  7. #定义神经网络模型
  8. dropout1, dropout2 = 0.3, 0.6
  9. class SimpleNN(nn.Module):
  10.     def __init__(self):
  11.         super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
  12.         self.dense = nn.Sequential(
  13.             nn.Flatten(),
  14.             nn.Linear(12, 128),
  15.             nn.ReLU(),  
  16.             nn.Dropout(dropout1),
  17.             nn.Linear(128, 256),
  18.             nn.ReLU(),  
  19.             nn.Dropout(dropout2),
  20.             nn.Linear(256, 1),
  21.         )
  22.       
  23.     def forward(self, X):
  24.         x = self.dense(X)
  25.         output = torch.sigmoid(x)
  26.         return output

  27.    
  28. #初始化模型和优化器
  29. simple_dnn_model = SimpleNN()
  30. loss = nn.BCELoss() #定义损失函数
  31. optimizer = optim.Adam(nn_model.parameters(),lr=0.0001) #定义优化器

  32. #初始化列表
  33. acc_list = []
  34. loss_list = []



  35. # 开始训练
  36. batch_size = 99
  37. num_epochs = 1000

  38.    
  39. #创建数据集
  40. train_dataset = data.TensorDataset(X_train, y_train)
  41. valid_dataset = data.TensorDataset(X_valid, y_valid)

  42. # 获取一个数据迭代器
  43. train_iter = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=2)#shuffle=True相当于sampler=RandomSampler(dataset)
  44. valid_iter = DataLoader(dataset=valid_dataset,batch_size=batch_size,shuffle=True,num_workers=2)

  45. #开始迭代
  46. for epoch in range(num_epochs):
  47.     train_loss = 0
  48.     num_right = 0
  49.     for tensor_x, tensor_y in train_iter:#训练集执行梯度更新
  50.         tensor_x = tensor_x.float()
  51.         tensor_y = tensor_y.float().reshape(-1, 1)
  52.         optimizer.zero_grad() #梯度清零
  53.         pre_train = simple_dnn_model(tensor_x)
  54.         train_l = loss(pre_train, tensor_y) #损失应避免与全局变量loss重名
  55.         train_l.backward()#前向传播
  56.         optimizer.step()#梯度下降

  57.         train_loss += train_l.item() * len(tensor_x)#批量损失
  58.         result = [1 if out >= 0.5 else 0 for out in pre_train]
  59.         num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))

  60.         train_loss = train_loss / len(train_iter.dataset)
  61.         train_accuracy = num_right / len(train_iter.dataset)

  62.     if epoch % 200 == 0:
  63.         print('Loss: {} Accuracy: {} Epoch:{}'.format(train_loss, train_accuracy, epoch))

  64.     with torch.no_grad():
  65.         valid_loss = 0
  66.         num_right = 0
  67.         for tensor_x, tensor_y in valid_iter:
  68.             tensor_x = tensor_x.float()
  69.             tensor_y = tensor_y.float().reshape(-1, 1)
  70.             pre_valid = simple_dnn_model(tensor_x)
  71.             valid_l = loss(pre_valid, tensor_y)
  72.             valid_loss += valid_l.item() * len(tensor_x)
  73.             result = [1 if out >= 0.5 else 0 for out in pre_valid]
  74.             num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))

  75.         valid_loss = valid_loss / len(valid_iter.dataset)
  76.         valid_accuracy = num_right / len(valid_iter.dataset)

  77.         if epoch % 200 == 0:
  78.             print('Valid Loss: {} Accuracy: {} Epoch:{}'.format(valid_loss, valid_accuracy, epoch))

  79. #将每次迭代的结果写入列表
  80. loss_list.append(valid_loss)
  81. acc_list.append(valid_accuracy)

  82. print('Training Ended')
  83. print('Average Loss: {} Average Accuracy: {}'.format(np.mean(loss_list), np.mean(acc_list)))
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 22:04:17 | 显示全部楼层
Terence888 发表于 2024-10-22 22:04
from mlxtend.regressor import StackingRegressor
f ...


出现 `NameError`,可能是因为 `simple_dnn_model` 未包含在 `models` 列表中。确保 `models` 列表中包含初始化的模型。以下是一些改进建议:

1. **将模型加入列表:**
   在调用 `StackingRegressor` 之前,确保所有基模型都在 `models` 列表中。

  
  1. from sklearn.linear_model import LinearRegression

  2.    # 初始化基模型列表
  3.    models = [simple_dnn_model, ...]  # 在列表中加入其他基模型
复制代码


2. **导入和实例化 `meta_regressor`:**
   确保 `LinearRegression` 被正确导入和实例化:

  
  1. from sklearn.linear_model import LinearRegression

  2.    # 创建meta_regressor实例
  3.    meta_regressor = LinearRegression()
复制代码


3. **在 `StackingRegressor` 中使用 `meta_regressor` 实例:**

  
  1. sclf = StackingRegressor(regressors=models, meta_regressor=meta_regressor)
复制代码


4. **检查 `result` 变量的定义:**
   在验证和训练阶段,确保 `result` 有定义,以保存预测的结果。

  
  1. result = (pre_train > 0.5).numpy()  # 对输出进行二值化处理
复制代码


5. **确保数据的类型正确:**
   确保 `X_train` 和 `y_train` 是张量,并且类型正确。

如果你对这些步骤还有疑问,请提供更多上下文以便更好地帮助解决问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-22 22:42:45 | 显示全部楼层
FishC 发表于 2024-10-22 22:04
出现 `NameError`,可能是因为 `simple_dnn_model` 未包含在 `models` 列表中。确保 `models` 列表中包 ...
  1. from mlxtend.regressor import StackingRegressor
  2. from sklearn.metrics import mean_squared_error

  3. # 初始化基模型
  4. models = [LR_model, dt_model, svm_model, rf_model,knn_model,simple_dnn_model]

  5. print('base model')
  6. for model in models:
  7.     model.fit(X_train, y_train)
  8.     pred = model.predict(X_valid)
  9.     print("loss is {}".format(mean_squared_error(y_valid, pred)))
  10. sclf = StackingRegressor(regressors=models, meta_regressor=LR_model)
  11. # 训练回归器
  12. sclf.fit(X_train, y_train)
  13. pred = sclf.predict(X_valid)

  14. print('stacking model')
  15. print("loss is {}".format(mean_squared_error(y_valid, pred)))
  16. plt.scatter(np.arange(len(pred)), pred)
  17. plt.plot(np.arange(len(y_valid)), y_valid)
  18. plt.show()
复制代码


提示错误
  1. ---------------------------------------------------------------------------
  2. AttributeError                            Traceback (most recent call last)
  3. Cell In[72], line 9
  4.       7 print('base model')
  5.       8 for model in models:
  6. ----> 9     model.fit(X_train, y_train)
  7.      10     pred = model.predict(X_valid)
  8.      11     print("loss is {}".format(mean_squared_error(y_valid, pred)))

  9. File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1695, in Module.__getattr__(self, name)
  10.    1693     if name in modules:
  11.    1694         return modules[name]
  12. -> 1695 raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")

  13. AttributeError: 'SimpleNN' object has no attribute 'fit'
复制代码


simple_nn_model是继承自module类自定义的类,
  1. import torch
  2. import torch.nn as nn
  3. from torch.utils import data
  4. from torch.utils.data import Dataset,DataLoader
  5. from torch import optim

  6. #定义神经网络模型
  7. dropout1, dropout2 = 0.3, 0.6
  8. class SimpleNN(nn.Module):
  9.     def __init__(self):
  10.         super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
  11.         self.dense = nn.Sequential(
  12.             nn.Flatten(),
  13.             nn.Linear(12, 128),
  14.             nn.ReLU(),  
  15.             nn.Dropout(dropout1),
  16.             nn.Linear(128, 256),
  17.             nn.ReLU(),  
  18.             nn.Dropout(dropout2),
  19.             nn.Linear(256, 1),
  20.         )
  21.       
  22.     def forward(self, X):
  23.         x = self.dense(X)
  24.         output = torch.sigmoid(x)
  25.         return output

  26.    
  27. #初始化模型和优化器
  28. simple_dnn_model = SimpleNN()
复制代码


这个报错在简单神经网络模型中找不到fit如何解决
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 22:53:08 | 显示全部楼层
Terence888 发表于 2024-10-22 22:42
from mlxtend.regressor import StackingRegressor
f ...


`SimpleNN` 是一个 PyTorch 模型,没有 `fit` 方法。你需要手动训练模型。若要将它与其他模型一起使用,可以尝试以下方法:

### 解决方案

1. **定义一个包装类:**

   创建一个包装类使其行为与 scikit-learn 模型一致:

  
  1. from sklearn.base import BaseEstimator, RegressorMixin

  2.    class SimpleNNWrapper(BaseEstimator, RegressorMixin):
  3.        def __init__(self, model, epochs=10, lr=0.001):
  4.            self.model = model
  5.            self.epochs = epochs
  6.            self.lr = lr
  7.            self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
  8.            self.criterion = nn.BCELoss()
  9.       
  10.        def fit(self, X, y):
  11.            dataset = data.TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
  12.            loader = DataLoader(dataset, batch_size=32, shuffle=True)
  13.            
  14.            for _ in range(self.epochs):
  15.                for batch_X, batch_y in loader:
  16.                    self.optimizer.zero_grad()
  17.                    outputs = self.model(batch_X)
  18.                    loss = self.criterion(outputs, batch_y.view(-1, 1))
  19.                    loss.backward()
  20.                    self.optimizer.step()
  21.            return self
  22.       
  23.        def predict(self, X):
  24.            self.model.eval()
  25.            with torch.no_grad():
  26.                return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()
复制代码


2. **使用包装类:**

   使用该包装类代替原始模型:

  
  1. models = [SimpleNNWrapper(SimpleNN()), other_model1, other_model2]  # 在此添加其他基模型
复制代码


3. **确保 `X_train` 和 `y_train` 是 numpy 数组:**

   确保输入数据是 numpy 数组,便于使用 PyTorch 数据集和 DataLoader。

这将允许你在 `StackingRegressor` 中使用自定义的 PyTorch 模型。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-23 19:32:46 | 显示全部楼层
Terence888 发表于 2024-10-22 22:42
提示错误

simple_nn_model是继承自module类自定义的类,
  1. from mlxtend.regressor import StackingRegressor
  2. from sklearn.metrics import mean_squared_error

  3. # 初始化基模型
  4. models = [LR_model, dt_model, svm_model, rf_model,knn_model,simple_dnn_model]

  5. print('base model')
  6. for model in models:
  7.     model.fit(X_train, y_train)
  8.     pred = model.predict(X_valid)
  9.     print("loss is {}".format(mean_squared_error(y_valid, pred)))
  10. sclf = StackingRegressor(regressors=models, meta_regressor=LR_model)
  11. # 训练回归器
  12. sclf.fit(X_train, y_train)
  13. pred = sclf.predict(X_valid)

  14. print('stacking model')
  15. print("loss is {}".format(mean_squared_error(y_valid, pred)))
  16. plt.scatter(np.arange(len(pred)), pred)
  17. plt.plot(np.arange(len(y_valid)), y_valid)
  18. plt.show()
复制代码


报错
  1. ---------------------------------------------------------------------------
  2. AttributeError                            Traceback (most recent call last)
  3. Cell In[25], line 9
  4.       7 print('base model')
  5.       8 for model in models:
  6. ----> 9     model.fit(X_train, y_train)
  7.      10     pred = model.predict(X_valid)
  8.      11     print("loss is {}".format(mean_squared_error(y_valid, pred)))

  9. File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1695, in Module.__getattr__(self, name)
  10.    1693     if name in modules:
  11.    1694         return modules[name]
  12. -> 1695 raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")

  13. AttributeError: 'SimpleNN' object has no attribute 'fit'
复制代码

如何修改自定义simplenn的代码?该类代码如下
  1. #dnn模型(train_test_split)
  2. import torch
  3. import torch.nn as nn
  4. from torch.utils import data
  5. from torch.utils.data import Dataset,DataLoader
  6. from torch import optim

  7. #定义神经网络模型
  8. dropout1, dropout2 = 0.3, 0.6
  9. class SimpleNN(nn.Module):
  10.     def __init__(self):
  11.         super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
  12.         self.dense = nn.Sequential(
  13.             nn.Flatten(),
  14.             nn.Linear(12, 128),
  15.             nn.ReLU(),  
  16.             nn.Dropout(dropout1),
  17.             nn.Linear(128, 256),
  18.             nn.ReLU(),  
  19.             nn.Dropout(dropout2),
  20.             nn.Linear(256, 1),
  21.         )
  22.       
  23.     def forward(self, X):
  24.         x = self.dense(X)
  25.         output = torch.sigmoid(x)
  26.         return output
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-23 19:32:59 | 显示全部楼层
Terence888 发表于 2024-10-23 19:32
from mlxtend.regressor import StackingRegressor
f ...


您需要为 `SimpleNN` 创建一个包装类,使其与 scikit-learn 的模型兼容。以下是如何实现的:

  1. import torch
  2. import torch.nn as nn
  3. import numpy as np
  4. from torch.utils.data import DataLoader, TensorDataset
  5. from torch import optim
  6. from sklearn.base import BaseEstimator, RegressorMixin

  7. # 定义神经网络模型
  8. class SimpleNN(nn.Module):
  9.     def __init__(self):
  10.         super(SimpleNN, self).__init__()
  11.         self.dense = nn.Sequential(
  12.             nn.Flatten(),
  13.             nn.Linear(12, 128),
  14.             nn.ReLU(),  
  15.             nn.Dropout(0.3),
  16.             nn.Linear(128, 256),
  17.             nn.ReLU(),  
  18.             nn.Dropout(0.6),
  19.             nn.Linear(256, 1),
  20.         )
  21.       
  22.     def forward(self, X):
  23.         x = self.dense(X)
  24.         output = torch.sigmoid(x)
  25.         return output

  26. # 包装类
  27. class SimpleNNWrapper(BaseEstimator, RegressorMixin):
  28.     def __init__(self, epochs=10, lr=0.001):
  29.         self.epochs = epochs
  30.         self.lr = lr
  31.         self.model = SimpleNN()
  32.         self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
  33.         self.criterion = nn.BCELoss()
  34.       
  35.     def fit(self, X, y):
  36.         # 转换数据为 PyTorch tensor
  37.         dataset = TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
  38.         loader = DataLoader(dataset, batch_size=32, shuffle=True)
  39.         
  40.         self.model.train()
  41.         for _ in range(self.epochs):
  42.             for batch_X, batch_y in loader:
  43.                 self.optimizer.zero_grad()
  44.                 outputs = self.model(batch_X)
  45.                 loss = self.criterion(outputs, batch_y.view(-1, 1))
  46.                 loss.backward()
  47.                 self.optimizer.step()
  48.         return self
  49.    
  50.     def predict(self, X):
  51.         self.model.eval()
  52.         with torch.no_grad():
  53.             return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()
复制代码


### 使用方法:

  1. models = [SimpleNNWrapper(),  # 其他基模型]

  2. # 将 SimpleNNWrapper 包含在基模型列表中
复制代码


这样,`SimpleNNWrapper` 将会与 scikit-learn 的其他模型兼容,并可以用于 `StackingRegressor`。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-23 19:39:41 | 显示全部楼层
FishC 发表于 2024-10-23 19:32
您需要为 `SimpleNN` 创建一个包装类,使其与 scikit-learn 的模型兼容。以下是如何实现的:
  1. stacking方法的其他代码
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-23 19:39:57 | 显示全部楼层
Terence888 发表于 2024-10-23 19:39
stacking方法的其他代码


其他代码完成示例如下:

  1. from sklearn.linear_model import LinearRegression
  2. from sklearn.ensemble import RandomForestRegressor
  3. from sklearn.datasets import load_boston
  4. from sklearn.model_selection import train_test_split
  5. import numpy as np
  6. import matplotlib.pyplot as plt

  7. # 加载数据
  8. data = load_boston()
  9. X, y = data.data, data.target

  10. # 划分数据集
  11. X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42)

  12. # 初始化基模型
  13. models = [
  14.     LinearRegression(),
  15.     RandomForestRegressor(n_estimators=100, random_state=42)
  16. ]

  17. print('Base model results:')
  18. for model in models:
  19.     model.fit(X_train, y_train)
  20.     pred = model.predict(X_valid)
  21.     print("Loss is {}".format(mean_squared_error(y_valid, pred)))

  22. # 定义堆叠回归器
  23. meta_regressor = LinearRegression()
  24. sclf = StackingRegressor(regressors=models, meta_regressor=meta_regressor)

  25. # 训练堆叠回归器
  26. sclf.fit(X_train, y_train)
  27. pred = sclf.predict(X_valid)

  28. print('Stacking model result:')
  29. print("Loss is {}".format(mean_squared_error(y_valid, pred)))

  30. # 可视化结果
  31. plt.scatter(np.arange(len(pred)), pred, color='red', label='Predictions')
  32. plt.plot(np.arange(len(y_valid)), y_valid, color='blue', label='True Values')
  33. plt.legend()
  34. plt.show()
复制代码


### 关键步骤:

1. **加载数据并划分训练和验证集:**
   使用 `train_test_split` 划分数据。

2. **初始化基模型:**
   使用常见模型,如 `LinearRegression` 和 `RandomForestRegressor`。

3. **评估基模型性能:**
   使用 `mean_squared_error` 计算损失。

4. **定义堆叠模型:**
   使用 `StackingRegressor` 来结合基模型的预测。

5. **训练和预测:**
   训练堆叠模型并计算其在验证集上的损失。

6. **可视化结果:**
   使用 `matplotlib` 展示预测值和实际值对比。

这样就能完整实现一个基本的堆叠模型示例。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-23 20:57:57 | 显示全部楼层
FishC 发表于 2024-10-23 19:39
其他代码完成示例如下:

基模型中可以使用神经网络模型吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-23 20:58:23 | 显示全部楼层
Terence888 发表于 2024-10-23 20:57
基模型中可以使用神经网络模型吗


可以在基模型中使用神经网络模型,但需要进行一些调整:

1. **包装神经网络模型:**
   创建一个包装类,使其遵循 scikit-learn API。

2. **自定义训练和预测:**
   在 `fit` 方法中定义训练过程,在 `predict` 方法中处理预测输出。

以下是一个如何包装 PyTorch 神经网络模型的示例:

  1. from sklearn.base import BaseEstimator, RegressorMixin
  2. import torch
  3. import torch.nn as nn
  4. from torch.utils.data import DataLoader, TensorDataset
  5. from torch import optim

  6. # 定义神经网络模型
  7. class SimpleNN(nn.Module):
  8.     def __init__(self):
  9.         super(SimpleNN, self).__init__()
  10.         self.dense = nn.Sequential(
  11.             nn.Flatten(),
  12.             nn.Linear(12, 128),
  13.             nn.ReLU(),  
  14.             nn.Dropout(0.3),
  15.             nn.Linear(128, 256),
  16.             nn.ReLU(),  
  17.             nn.Dropout(0.6),
  18.             nn.Linear(256, 1),
  19.         )
  20.       
  21.     def forward(self, X):
  22.         x = self.dense(X)
  23.         return x

  24. # 包装类
  25. class SimpleNNWrapper(BaseEstimator, RegressorMixin):
  26.     def __init__(self, epochs=1000, lr=0.001):
  27.         self.epochs = epochs
  28.         self.lr = lr
  29.         self.model = SimpleNN()
  30.         self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
  31.         self.criterion = nn.MSELoss()  # 对于回归任务,使用均方误差损失
  32.       
  33.     def fit(self, X, y):
  34.         dataset = TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
  35.         loader = DataLoader(dataset, batch_size=32, shuffle=True)
  36.         
  37.         self.model.train()
  38.         for _ in range(self.epochs):
  39.             for batch_X, batch_y in loader:
  40.                 self.optimizer.zero_grad()
  41.                 outputs = self.model(batch_X)
  42.                 loss = self.criterion(outputs, batch_y.view(-1, 1))
  43.                 loss.backward()
  44.                 self.optimizer.step()
  45.         return self
  46.    
  47.     def predict(self, X):
  48.         self.model.eval()
  49.         with torch.no_grad():
  50.             return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()

  51. # 使用方法
  52. nn_model = SimpleNNWrapper()
复制代码


### 关键步骤:

- **创建包装类:** 包装类继承 `BaseEstimator` 和 `RegressorMixin` 。
- **定义训练过程:** 在 `fit` 方法中实现,使用 PyTorch 的 DataLoader 和优化器。
- **定义预测过程:** 在 `predict` 方法中,将 PyTorch 模型输出转换为 numpy 格式以便使用。

这样,你就可以将神经网络模型作为基模型,与其他 scikit-learn 模型一起使用。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-23 22:45:04 | 显示全部楼层
FishC 发表于 2024-10-23 20:58
可以在基模型中使用神经网络模型,但需要进行一些调整:

1. **包装神经网络模型:**

提交预测结果代码
  1. data_test = pd.read_csv('/kaggle/input/titanic-files/train.csv')
  2. test = data_test.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Embarked_.*|Sex_.*|Pclass_.*')
  3. predictions = sclf.predict(test)
  4. result = pd.DataFrame({'PassengerId':data_test['PassengerId'].values,'Survived':predictions.values})
  5. result.to_csv('/kaggle/working/submission.csv',index=False)
复制代码


报错
  1. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but LogisticRegression was fitted without feature names
  2.   warnings.warn(
  3. ---------------------------------------------------------------------------
  4. ValueError                                Traceback (most recent call last)
  5. Cell In[23], line 3
  6.       1 data_test = pd.read_csv('/kaggle/input/titanic-files/train.csv')
  7.       2 test = data_test.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Embarked_.*|Sex_.*|Pclass_.*')
  8. ----> 3 predictions = sclf.predict(test)
  9.       4 result = pd.DataFrame({'PassengerId':data_test['PassengerId'].values,'Survived':predictions.values})
  10.       5 result.to_csv('/kaggle/working/submission.csv',index=False)

  11. File /opt/conda/lib/python3.10/site-packages/mlxtend/regressor/stacking_regression.py:261, in StackingRegressor.predict(self, X)
  12.     247 """Predict target values for X.
  13.     248
  14.     249 Parameters
  15.    (...)
  16.     258     Predicted target values.
  17.     259 """
  18.     260 check_is_fitted(self, "regr_")
  19. --> 261 meta_features = self.predict_meta_features(X)
  20.     263 if not self.use_features_in_secondary:
  21.     264     return self.meta_regr_.predict(meta_features)

  22. File /opt/conda/lib/python3.10/site-packages/mlxtend/regressor/stacking_regression.py:244, in StackingRegressor.predict_meta_features(self, X)
  23.     226 """Get meta-features of test-data.
  24.     227
  25.     228 Parameters
  26.    (...)
  27.     241
  28.     242 """
  29.     243 check_is_fitted(self, "regr_")
  30. --> 244 return np.column_stack([r.predict(X) for r in self.regr_])

  31. File /opt/conda/lib/python3.10/site-packages/mlxtend/regressor/stacking_regression.py:244, in <listcomp>(.0)
  32.     226 """Get meta-features of test-data.
  33.     227
  34.     228 Parameters
  35.    (...)
  36.     241
  37.     242 """
  38.     243 check_is_fitted(self, "regr_")
  39. --> 244 return np.column_stack([r.predict(X) for r in self.regr_])

  40. File /opt/conda/lib/python3.10/site-packages/sklearn/linear_model/_base.py:419, in LinearClassifierMixin.predict(self, X)
  41.     405 """
  42.     406 Predict class labels for samples in X.
  43.     407
  44.    (...)
  45.     416     Vector containing the class labels for each sample.
  46.     417 """
  47.     418 xp, _ = get_namespace(X)
  48. --> 419 scores = self.decision_function(X)
  49.     420 if len(scores.shape) == 1:
  50.     421     indices = xp.astype(scores > 0, int)

  51. File /opt/conda/lib/python3.10/site-packages/sklearn/linear_model/_base.py:400, in LinearClassifierMixin.decision_function(self, X)
  52.     397 check_is_fitted(self)
  53.     398 xp, _ = get_namespace(X)
  54. --> 400 X = self._validate_data(X, accept_sparse="csr", reset=False)
  55.     401 scores = safe_sparse_dot(X, self.coef_.T, dense_output=True) + self.intercept_
  56.     402 return xp.reshape(scores, -1) if scores.shape[1] == 1 else scores

  57. File /opt/conda/lib/python3.10/site-packages/sklearn/base.py:588, in BaseEstimator._validate_data(self, X, y, reset, validate_separately, **check_params)
  58.     585     out = X, y
  59.     587 if not no_val_X and check_params.get("ensure_2d", True):
  60. --> 588     self._check_n_features(X, reset=reset)
  61.     590 return out

  62. File /opt/conda/lib/python3.10/site-packages/sklearn/base.py:389, in BaseEstimator._check_n_features(self, X, reset)
  63.     386     return
  64.     388 if n_features != self.n_features_in_:
  65. --> 389     raise ValueError(
  66.     390         f"X has {n_features} features, but {self.__class__.__name__} "
  67.     391         f"is expecting {self.n_features_in_} features as input."
  68.     392     )

  69. ValueError: X has 3 features, but LogisticRegression is expecting 12 features as input.
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-23 22:45:20 | 显示全部楼层
Terence888 发表于 2024-10-23 22:45
提交预测结果代码
data_test = pd.read_csv('/kaggle ...


这个错误是因为测试集的特征数与训练集不一致,或者模型在训练时不支持带有特征名称的输入。可以尝试以下方法解决这个问题:

1. **确保特征数一致:**

   - 确认训练和测试数据的特征列相同,并按相同顺序排列。

2. **去掉特征名警告:**

   - 在将数据传入模型之前,转换为不包含特征名称的格式:

   
  1. test_np = test.values  # 将 DataFrame 转换为 numpy 数组
  2.      predictions = sclf.predict(test_np)
复制代码


3. **检查训练阶段特征处理:**

   - 确保 `X_train` 中也使用类似的列过滤方式。如果在训练时对数据进行了预处理(例如特征缩放),请在测试数据上应用相同的预处理流程。

4. **使用相同的预处理:**

   - 确保所有数据(训练和测试)都经过相同的预处理步骤(例如标准化、编码等)。

这样可以确保模型在相同格式和数量的特征上进行训练和预测。如果继续出现问题,请检查训练时特征的选择和生成过程,以保证训练和预测阶段的一致性。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-23 23:19:34 | 显示全部楼层
FishC 发表于 2024-10-23 22:45
这个错误是因为测试集的特征数与训练集不一致,或者模型在训练时不支持带有特征名称的输入。可以尝试以 ...
  1. /tmp/ipykernel_33/493586368.py:4: SettingWithCopyWarning:
  2. A value is trying to be set on a copy of a slice from a DataFrame.
  3. Try using .loc[row_indexer,col_indexer] = value instead

  4. See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  5.   df_test['Age_scaled'] = test_scaler.fit_transform(Age_scaled_test)
  6. /tmp/ipykernel_33/493586368.py:6: SettingWithCopyWarning:
  7. A value is trying to be set on a copy of a slice from a DataFrame.
  8. Try using .loc[row_indexer,col_indexer] = value instead

  9. See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  10.   df_test['Fare_scaled'] = test_scaler.fit_transform(Fare_scaled_test)
复制代码


报错如上

代码如下
  1. #对age、fare进行归一化
  2. test_scaler = preprocessing.StandardScaler()
  3. Age_scaled_test = np.array(df_test['Age']).reshape(-1, 1)
  4. df_test['Age_scaled'] = test_scaler.fit_transform(Age_scaled_test)
  5. Fare_scaled_test = np.array(df_test['Fare']).reshape(-1, 1)
  6. df_test['Fare_scaled'] = test_scaler.fit_transform(Fare_scaled_test)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-23 23:19:45 | 显示全部楼层
Terence888 发表于 2024-10-23 23:19
/tmp/ipykernel_33/493586368.py:4: SettingWithCopyW ...


`SettingWithCopyWarning` 是因为在 DataFrame 的切片上直接进行赋值操作。可以通过 `.loc` 明确指定进行修改。下面是修正代码:

1. 对 `Age` 和 `Fare` 的处理应分别进行,以便不覆盖数据:

  1. from sklearn import preprocessing

  2. # 对 'Age' 进行归一化
  3. test_scaler = preprocessing.StandardScaler()

  4. # 假设 df_test 是你的 DataFrame
  5. df_test['Age'] = test_scaler.fit_transform(df_test[['Age']])

  6. # 对 'Fare' 进行归一化
  7. df_test['Fare'] = test_scaler.fit_transform(df_test[['Fare']])
复制代码


### 注意事项

- 确保 `df_test` 中确实存在 `'Age'` 和 `'Fare'` 列。
- 使用 `[['column']]` 而非 `[column]` 来确保 DataFrame 格式。
- 通过 `df_test.loc[:, 'Age'] = ...` 来避免警告,但上面的方法也有效。

这样能够避免 `SettingWithCopyWarning`,同时保证数据的正确预处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-24 20:54:54 | 显示全部楼层
FishC 发表于 2024-10-23 23:19
`SettingWithCopyWarning` 是因为在 DataFrame 的切片上直接进行赋值操作。可以通过 `.loc` 明确指定进 ...
  1. from mlxtend.regressor import StackingRegressor
  2. from sklearn.metrics import mean_squared_error

  3. #加载test数据集
  4. X_test = df_test.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Embarked_.*|Sex_.*|Pclass_.*')

  5. # 初始化基模型
  6. models = [LR_model, dt_model, svm_model, rf_model,knn_model]
  7. sclf = StackingRegressor(regressors=models, meta_regressor=LR_model)

  8. # 训练并预测回归器
  9. sclf.fit(X, y)
  10. predictions = sclf.predict(X_test)
  11. #print(type(predictions))
  12. result = pd.DataFrame({'PassengerId':data_test['PassengerId'].values,'Survived':predictions})
  13. #result.to_csv('/kaggle/working/submission.csv',index=False)
  14. result

复制代码


结果如下
  1. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but LogisticRegression was fitted without feature names
  2.   warnings.warn(
  3. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but DecisionTreeClassifier was fitted without feature names
  4.   warnings.warn(
  5. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but SVC was fitted without feature names
  6.   warnings.warn(
  7. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but RandomForestClassifier was fitted without feature names
  8.   warnings.warn(
  9. /opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but KNeighborsClassifier was fitted without feature names
  10.   warnings.warn(
  11. PassengerId        Survived
  12. 0        892        0
  13. 1        893        0
  14. 2        894        0
  15. 3        895        1
  16. 4        896        0
  17. ...        ...        ...
  18. 326        1301        1
  19. 327        1303        1
  20. 328        1304        1
  21. 329        1306        1
  22. 330        1307        0
  23. 331 rows × 2 columns
复制代码


出现这些warnings如何修改
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-24 21:01:22 | 显示全部楼层
Terence888 发表于 2024-10-24 20:54
from mlxtend.regressor import StackingRegressor
f ...


为了去除这些警告,你可以在模型训练和预测时使用没有特征名称的输入。以下是解决方法:

1. **将 DataFrame 转为 numpy 数组:**

在训练和预测阶段,将数据转为 numpy 数组:

  1. X_train_np = X.values  # 训练数据
  2. y_train_np = y.values  # 标签
  3. X_test_np = X_test.values  # 测试数据
复制代码


2. **训练和预测时使用 numpy 数组:**

  1. sclf.fit(X_train_np, y_train_np)
  2. predictions = sclf.predict(X_test_np)
复制代码


3. **创建结果 DataFrame:**

  1. result = pd.DataFrame({'PassengerId': data_test['PassengerId'].values, 'Survived': predictions})
复制代码


这样,模型在训练和预测时就不会包含特征名称,从而消除警告。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-19 16:55

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表