鱼C论坛

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

stackingregression模型融合遇到问题

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

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

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

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

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

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

print('stacking model')
print("loss is {}".format(mean_squared_error(y_valid, pred)))
plt.scatter(np.arange(len(pred)), pred)
plt.plot(np.arange(len(y_valid)), y_valid)
plt.show()
以上是模型融合的代码,以下是报错
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[35], line 12
     10     pred = model.predict(X_valid)
     11     print("loss is {}".format(mean_squared_error(y_valid, pred)))
---> 12 sclf = StackingRegressor(regressors=models, meta_regressor=ridge)
     13 # 训练回归器
     14 sclf.fit(X_train, y_train)

NameError: name 'ridge' is not defined
关于该模型的参数如何选择,翻遍外网也没找到meta_regressor是什么意思
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

以下是如何定义 `ridge` 的示例代码:
from sklearn.linear_model import Ridge

# 定义meta_regressor
ridge = Ridge()

# 初始化基模型列表
models = [
    # 例如:
    # LinearRegression(), 
    # RandomForestRegressor(),
    # ...
]

# 之后的代码保持不变

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

print('stacking model')
print("loss is {}".format(mean_squared_error(y_valid, pred)))
plt.scatter(np.arange(len(pred)), pred)
plt.plot(np.arange(len(y_valid)), y_valid)
plt.show()

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

NameError: name 'simple_dnn_model' is not defined
但是前面已经定义并执行了这个函数
#dnn模型(train_test_split)
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import Dataset,DataLoader
from torch import optim

#定义神经网络模型
dropout1, dropout2 = 0.3, 0.6
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(dropout1),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(dropout2),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        output = torch.sigmoid(x)
        return output

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

#初始化列表
acc_list = []
loss_list = []



# 开始训练
batch_size = 99
num_epochs = 1000

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

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

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

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

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

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

    with torch.no_grad():
        valid_loss = 0
        num_right = 0
        for tensor_x, tensor_y in valid_iter:
            tensor_x = tensor_x.float()
            tensor_y = tensor_y.float().reshape(-1, 1)
            pre_valid = simple_dnn_model(tensor_x)
            valid_l = loss(pre_valid, tensor_y)
            valid_loss += valid_l.item() * len(tensor_x)
            result = [1 if out >= 0.5 else 0 for out in pre_valid]
            num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))

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

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

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

print('Training Ended')
print('Average Loss: {} Average Accuracy: {}'.format(np.mean(loss_list), np.mean(acc_list)))
想知道小甲鱼最近在做啥?请访问 -> 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` 列表中。

from sklearn.linear_model import LinearRegression

   # 初始化基模型列表
   models = [simple_dnn_model, ...]  # 在列表中加入其他基模型

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

from sklearn.linear_model import LinearRegression

   # 创建meta_regressor实例
   meta_regressor = LinearRegression()

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

sclf = StackingRegressor(regressors=models, meta_regressor=meta_regressor)

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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

print('stacking model')
print("loss is {}".format(mean_squared_error(y_valid, pred)))
plt.scatter(np.arange(len(pred)), pred)
plt.plot(np.arange(len(y_valid)), y_valid)
plt.show()

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

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

AttributeError: 'SimpleNN' object has no attribute 'fit'

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

#定义神经网络模型
dropout1, dropout2 = 0.3, 0.6
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(dropout1),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(dropout2),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        output = torch.sigmoid(x)
        return output

    
#初始化模型和优化器
simple_dnn_model = SimpleNN()

这个报错在简单神经网络模型中找不到fit如何解决
想知道小甲鱼最近在做啥?请访问 -> 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 模型一致:

from sklearn.base import BaseEstimator, RegressorMixin

   class SimpleNNWrapper(BaseEstimator, RegressorMixin):
       def __init__(self, model, epochs=10, lr=0.001):
           self.model = model
           self.epochs = epochs
           self.lr = lr
           self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
           self.criterion = nn.BCELoss()
       
       def fit(self, X, y):
           dataset = data.TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
           loader = DataLoader(dataset, batch_size=32, shuffle=True)
           
           for _ in range(self.epochs):
               for batch_X, batch_y in loader:
                   self.optimizer.zero_grad()
                   outputs = self.model(batch_X)
                   loss = self.criterion(outputs, batch_y.view(-1, 1))
                   loss.backward()
                   self.optimizer.step()
           return self
       
       def predict(self, X):
           self.model.eval()
           with torch.no_grad():
               return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()

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

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

models = [SimpleNNWrapper(SimpleNN()), other_model1, other_model2]  # 在此添加其他基模型

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

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

print('stacking model')
print("loss is {}".format(mean_squared_error(y_valid, pred)))
plt.scatter(np.arange(len(pred)), pred)
plt.plot(np.arange(len(y_valid)), y_valid)
plt.show()

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

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

AttributeError: 'SimpleNN' object has no attribute 'fit'
如何修改自定义simplenn的代码?该类代码如下
#dnn模型(train_test_split)
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import Dataset,DataLoader
from torch import optim

#定义神经网络模型
dropout1, dropout2 = 0.3, 0.6
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(dropout1),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(dropout2),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        output = torch.sigmoid(x)
        return output
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


您需要为 `SimpleNN` 创建一个包装类,使其与 scikit-learn 的模型兼容。以下是如何实现的:
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, TensorDataset
from torch import optim
from sklearn.base import BaseEstimator, RegressorMixin

# 定义神经网络模型
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(0.3),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(0.6),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        output = torch.sigmoid(x)
        return output

# 包装类
class SimpleNNWrapper(BaseEstimator, RegressorMixin):
    def __init__(self, epochs=10, lr=0.001):
        self.epochs = epochs
        self.lr = lr
        self.model = SimpleNN()
        self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
        self.criterion = nn.BCELoss()
       
    def fit(self, X, y):
        # 转换数据为 PyTorch tensor
        dataset = TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
        loader = DataLoader(dataset, batch_size=32, shuffle=True)
        
        self.model.train()
        for _ in range(self.epochs):
            for batch_X, batch_y in loader:
                self.optimizer.zero_grad()
                outputs = self.model(batch_X)
                loss = self.criterion(outputs, batch_y.view(-1, 1))
                loss.backward()
                self.optimizer.step()
        return self
   
    def predict(self, X):
        self.model.eval()
        with torch.no_grad():
            return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()

### 使用方法:
models = [SimpleNNWrapper(),  # 其他基模型]

# 将 SimpleNNWrapper 包含在基模型列表中

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

使用道具 举报

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


其他代码完成示例如下:
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt

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

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

# 初始化基模型
models = [
    LinearRegression(),
    RandomForestRegressor(n_estimators=100, random_state=42)
]

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

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

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

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

# 可视化结果
plt.scatter(np.arange(len(pred)), pred, color='red', label='Predictions')
plt.plot(np.arange(len(y_valid)), y_valid, color='blue', label='True Values')
plt.legend()
plt.show()

### 关键步骤:

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

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

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

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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

基模型中可以使用神经网络模型吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

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

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

以下是一个如何包装 PyTorch 神经网络模型的示例:
from sklearn.base import BaseEstimator, RegressorMixin
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
from torch import optim

# 定义神经网络模型
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(0.3),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(0.6),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        return x

# 包装类
class SimpleNNWrapper(BaseEstimator, RegressorMixin):
    def __init__(self, epochs=1000, lr=0.001):
        self.epochs = epochs
        self.lr = lr
        self.model = SimpleNN()
        self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)
        self.criterion = nn.MSELoss()  # 对于回归任务,使用均方误差损失
       
    def fit(self, X, y):
        dataset = TensorDataset(torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32))
        loader = DataLoader(dataset, batch_size=32, shuffle=True)
        
        self.model.train()
        for _ in range(self.epochs):
            for batch_X, batch_y in loader:
                self.optimizer.zero_grad()
                outputs = self.model(batch_X)
                loss = self.criterion(outputs, batch_y.view(-1, 1))
                loss.backward()
                self.optimizer.step()
        return self
   
    def predict(self, X):
        self.model.eval()
        with torch.no_grad():
            return self.model(torch.tensor(X, dtype=torch.float32)).numpy().flatten()

# 使用方法
nn_model = SimpleNNWrapper()

### 关键步骤:

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

报错
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but LogisticRegression was fitted without feature names
  warnings.warn(
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[23], line 3
      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)

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

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

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

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

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

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

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

ValueError: X has 3 features, but LogisticRegression is expecting 12 features as input.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

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

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

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

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

   
test_np = test.values  # 将 DataFrame 转换为 numpy 数组
     predictions = sclf.predict(test_np)

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

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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

报错如上

代码如下
#对age、fare进行归一化
test_scaler = preprocessing.StandardScaler()
Age_scaled_test = np.array(df_test['Age']).reshape(-1, 1)
df_test['Age_scaled'] = test_scaler.fit_transform(Age_scaled_test)
Fare_scaled_test = np.array(df_test['Fare']).reshape(-1, 1)
df_test['Fare_scaled'] = test_scaler.fit_transform(Fare_scaled_test)
想知道小甲鱼最近在做啥?请访问 -> 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` 的处理应分别进行,以便不覆盖数据:
from sklearn import preprocessing

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

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

# 对 'Fare' 进行归一化
df_test['Fare'] = test_scaler.fit_transform(df_test[['Fare']])

### 注意事项

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

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

结果如下
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but LogisticRegression was fitted without feature names
  warnings.warn(
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but DecisionTreeClassifier was fitted without feature names
  warnings.warn(
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but SVC was fitted without feature names
  warnings.warn(
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but RandomForestClassifier was fitted without feature names
  warnings.warn(
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but KNeighborsClassifier was fitted without feature names
  warnings.warn(
PassengerId        Survived
0        892        0
1        893        0
2        894        0
3        895        1
4        896        0
...        ...        ...
326        1301        1
327        1303        1
328        1304        1
329        1306        1
330        1307        0
331 rows × 2 columns

出现这些warnings如何修改
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

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

在训练和预测阶段,将数据转为 numpy 数组:
X_train_np = X.values  # 训练数据
y_train_np = y.values  # 标签
X_test_np = X_test.values  # 测试数据

2. **训练和预测时使用 numpy 数组:**
sclf.fit(X_train_np, y_train_np)
predictions = sclf.predict(X_test_np)

3. **创建结果 DataFrame:**
result = pd.DataFrame({'PassengerId': data_test['PassengerId'].values, 'Survived': predictions})

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 19:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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