【问题标题】:Python Object List UpdatePython 对象列表更新
【发布时间】:2021-08-18 20:35:12
【问题描述】:

我有一个结构类似于:

models = [{
  'name': 'Model 1',
  'errors': {
    'mse': None,
    'rmse': None
  }
},
{
  'name': 'Model 2',
  'errors': {
    'mse': None,
    'rmse': None
  }
}]

现在我想遍历对象并改变一些东西,所以我尝试使用这样的东西:

for index, model in enumerate(models):
  # Carry out model performance and update the respective errors
  model['errors']['mse'] = metrics.mean_squared_error(...)

models 列表中的所有对象都会更新为最后一个元素的值。我也尝试过使用它(它也没有工作):

for index in range(len(models)):
  # Carry out model performance and update the respective errors
  models[index]['errors']['mse'] = metrics.mean_squared_error(...)

如果我写models[0]['errors']['mse'] = 10,所有其他索引也会更新。谁能帮我解决这个问题?

(如果您能提出一个解决方案,我可以在循环遍历列表时进行更新,那就太好了)

实际代码

import importlib

class Models:
    
    # Model structure
    model = {
        'base': None,
        'name': None,
        'model': None,
        'config': {},
        'errors': {
            'mae': None,
            'mse': None,
            'rmse': None,
        },
        'scores': {
            'r2': None,
            'accuracy_score': None
        }
    }
    
    # Prints Looping Progress
    def progress(self, index):
        return '(' + str(index+1) + '/' + str(self.models.__len__()) + ')'
    
    # Import Models
    def import_models(self):
        for model in self.models:
            model['model'] = getattr(importlib.import_module(model['base']), model['name'])(**model['config'])
    
    # Restructure Models Object
    def restructure_models(self, models):
        restructured_models = []
        for model in models:
            restructured_model = {**self.model, **model}
            restructured_models.append(restructured_model)
        return restructured_models
    
    # Constructor
    def __init__(self, models):
        self.models = self.restructure_models(models)
        self.import_models()
    
    # Train Models
    def fit(self, X_train, y_train):
        for index, model in enumerate(self.models):
            print('Training ' + self.progress(index) + ': ', model['name'])
            model['model'].fit(X_train, y_train)
        print('\n')
        
    # Predict Values
    def predict(self, X_test):
        all_predictions = []
        for index, model in enumerate(self.models):
            print('Running ' + self.progress(index) + ': ', model['name'])
            # Predict
            predictions = model['model'].predict(X_test)
            all_predictions.append({
                'model': model['name'],
                'predictions': predictions
            })
        print('\n')
        return all_predictions
            
    # Evaluate Trained Models
    def test(self, X_test, y_test):
        from sklearn import metrics
        all_predictions = []
        for index, model in enumerate(self.models):
            print('Evaluating ' + self.progress(index) + ': ', model['name'])
            # Predict
            predictions = model['model'].predict(X_test)
            # Errors
            model['errors']['mae'] = metrics.mean_absolute_error(y_test, predictions)
            model['errors']['mse'] = metrics.mean_squared_error(y_test, predictions)
            model['errors']['rmse'] = np.sqrt(model['errors']['mse'])
            # Scores
            model['scores']['r2'] = metrics.r2_score(y_test, predictions)
            model['scores']['accuracy_score'] = metrics.r2_score(y_true = y_test, y_pred = predictions)
            all_predictions.append({
                'model': model['name'],
                'predictions': predictions
            })
        print('\n')
        return all_predictions
    
    # Evaluated Performance Metrics
    def results(self):
        for model in self.models:
            print('Model: ', model['name'])
            print('MAE: ', model['errors']['mae'])
            print('MSE: ', model['errors']['mse'])
            print('RMSE: ', model['errors']['rmse'])
            print('R2: ', model['scores']['r2'])
            print('Accuracy Score: ', model['scores']['accuracy_score'])
            print('\n')

调用和使用类:

selected_models = [
    {
        'base': 'sklearn.linear_model',
        'name': 'LinearRegression'
    },
    {
        'base': 'sklearn.ensemble',
        'name': 'RandomForestRegressor',
                'config': {
                        'n_estimators': 50
                }
    }
]
models = Models(models = selected_models)
predictions = models.test(X_test = X_test_scaled, y_test = y_test)

问题在于test 函数错误地更新了self.models(所有列表项都根据最后一个元素更改)

【问题讨论】:

  • 请发布实际演示问题的代码 - 或尝试使用您提供的示例代码重现问题,其中每个列表元素都是独立声明的 dict(您会发现它的行为不同)。
  • 我用实际代码更新了问题

标签: python arrays python-3.x list loops


【解决方案1】:

问题出在这里:

restructured_model = {**self.model, **model}

您正在创建一个新的dict,但它引用了单例Models.model

我认为你的意思是:

import copy

copy_model = copy.deepcopy(self.model)
restructured_model = {**copy_model, **model}

【讨论】:

  • 哇,这真是个魅力!非常感谢您的帮助!
【解决方案2】:

你可以试试这个调试吗?

for index, model in enumerate(models):
  # Carry out model performance and update the respective errors
  set_value = metrics.mean_squared_error(...)
  print('setting value to ' + str(set_value))
  model['errors']['mse'] = set_value

【讨论】:

  • 我加了,结果还是一样。在循环内打印时,它给出了正确的值,但是在我打印整个对象时运行循环后,所有项目都使用最后一个元素的值进行更新。
猜你喜欢
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多