class_docstr: A general model arch for mapping from state to ActorOutput,
  which contains an action tensor and log probabilities (optional).
  
  The model arch is often used to implement the actor in actor-critic algorithms.
code: def forward(self, state: rlt.FeatureData) -> rlt.ActorOutput:
      action = self.fc(state.float_features)
      batch_size = action.shape[0]
      assert action.shape == (
          batch_size,
          self.action_dim,
      ), f"{action.shape} != ({batch_size}, {self.action_dim})"
  
      if self.exploration_variance is None:
          log_prob = (
              torch.zeros(batch_size)
              .to(action.device)
              .float()
              .view(-1, 1)
          )
          return rlt.ActorOutput(action=action, log_prob=log_prob)
  
      noise = self.noise_dist.sample((batch_size,))
      # TODO: log prob is affected by clamping, how to handle that?
      log_prob = (
          self.noise_dist.log_prob(noise)
          .to(action.device)
          .sum(dim=1)
          .view(-1, 1)
      ).clamp(LOG_PROB_MIN, LOG_PROB_MAX)
      action = (action + noise.to(action.device)).clamp(
          *CONTINUOUS_TRAINING_ACTION_RANGE
      )
      return rlt.ActorOutput(action=action, log_prob=log_prob)
  
imports: import math
  from typing import List, Optional
  import torch
  from reagent.core import types
  from reagent.core.parameters import CONTINUOUS_TRAINING_ACTION_RANGE
  from reagent.core.tensorboardX import SummaryWriterContext
  from reagent.models.base import ModelBase
  from reagent.models.fully_connected_network import FullyConnectedNetwork
  from torch.distributions import Dirichlet
  from torch.distributions.normal import Normal
label_desc: Use image node_id 3 for calling the FullyConnectedActor obj's underlying member method code with example usage: obj.forward(state) and returns: rlt, rlt