code: def test_train(self):
      estimator = Estimator.from_torch(
          model=model_creator,
          optimizer=optimizer_creator,
          loss=nn.MSELoss(),
          scheduler_creator=scheduler_creator,
          config={
              "lr": 1e-2,  # used in optimizer_creator
              "hidden_size": 1,  # used in model_creator
          },
          backend="horovod",
          workers_per_node=2,
      )
      stats1 = estimator.fit(train_data_creator, batch_size=4, epochs=5)
      train_loss1 = stats1[-1]["train_loss"]
      validation_loss1 = estimator.evaluate(validation_data_creator)[
          "val_loss"
      ]
  
      stats2 = estimator.fit(train_data_creator, batch_size=4, epochs=3)
      train_loss2 = stats2[-1]["train_loss"]
      validation_loss2 = estimator.evaluate(validation_data_creator)[
          "val_loss"
      ]
  
      # Verify syncing weights, i.e. the two workers have the same weights after training
      import ray
      import numpy as np
  
      remote_workers = estimator.estimator.remote_workers
      state_dicts = ray.get(
          [worker.state_dict.remote() for worker in remote_workers]
      )
      weights = [state["models"] for state in state_dicts]
      worker1_weights = weights[0][0]
      worker2_weights = weights[1][0]
      for layer in list(worker1_weights.keys()):
          assert np.allclose(
              worker1_weights[layer].numpy(),
              worker2_weights[layer].numpy(),
          )
  
      assert train_loss2 <= train_loss1, (train_loss2, train_loss1)
      # todo this test maybe too strict, need to further check
      # assert validation_loss2 <= validation_loss1, (validation_loss2,
      #                                               validation_loss1)
      estimator.shutdown()
  
file_path: analytics-zoo/pyzoo/test/zoo/orca/learn/ray/pytorch/test_estimator_horovod_backend.py
imports: from zoo.examples.orca.learn.horovod.pytorch_estimator import model_creator, optimizer_creator, scheduler_creator, train_data_creator, validation_data_creator
  from zoo.orca.learn.pytorch import Estimator
  from unittest import TestCase
  import pytest
  import torch
  import torch.nn
  import os
  from tempfile import TemporaryDirectory
label_desc: Use image node_id 1 for calling the TestPyTorchEstimator obj's underlying member method code with example usage: obj.test_train() without return types