AI4Finance-Foundation / FinRL

FinRL: Financial Reinforcement Learning. 🔥
https://ai4finance.org
MIT License
10.19k stars 2.45k forks source link

stable_baselines3 issue: cannot copy sequence with size 292 to array axis with dimension 301 #161

Closed manuel1801 closed 2 years ago

manuel1801 commented 3 years ago

when running python main.py --mode=train i'm getting the following error:

==============Start Feature Engineering===========
Successfully added technical indicators
Successfully added turbulence index
Traceback (most recent call last):
  File "main.py", line 51, in <module>
    main()
  File "main.py", line 38, in main
    finrl.autotrain.training.train_one()
  File "C:\Users\Manuel\Documents\TraidingBot\FinRL-Library\finrl\autotrain\training.py", line 66, in train_one
    env_train, _ = e_train_gym.get_sb_env()
  File "C:\Users\Manuel\Documents\TraidingBot\FinRL-Library\finrl\env\env_stocktrading.py", line 379, in get_sb_env
    obs = e.reset()
  File "C:\Users\Manuel\Documents\TraidingBot\venv\lib\site-packages\stable_baselines3\common\vec_env\dummy_vec_env.py", line 62, in reset
    self._save_obs(env_idx, obs)
  File "C:\Users\Manuel\Documents\TraidingBot\venv\lib\site-packages\stable_baselines3\common\vec_env\dummy_vec_env.py", line 92, in _save_obs
    self.buf_obs[key][env_idx] = obs
ValueError: cannot copy sequence with size 292 to array axis with dimension 301
LegitCodeRed commented 3 years ago

i dont know if this is a good idea, but atleast i got it running:

i put this function into the main class of the dummy_vec_env.py

def _fix_list(self, _list, array):
        for i in range(len(_list), array.size):
            _list.append(0)
        return _list

and in the _save_obs function

def _save_obs(self, env_idx: int, obs: VecEnvObs) -> None:
        for key in self.keys:
            if key is None:
                if(len(obs) != self.buf_obs[key][env_idx].size):
                    obs = self._fix_list(obs, self.buf_obs[key][env_idx])
                if(self.buf_obs[key][env_idx].size != len(obs)):
                    obs = obs[:self.buf_obs[key][env_idx].size-len(obs)]
                self.buf_obs[key][env_idx] = obs
            else:
                self.buf_obs[key][env_idx] = obs[key]
manuel1801 commented 3 years ago

Thanks alot with that it's running for me as well

setar commented 3 years ago

this work for me too, thanks

Mahesha999 commented 3 years ago

well, I am getting this while running this line on my local machine:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-33-9b19b057dbd1> in <module>
----> 1 trained_a2c = agent.train_model(model=model_a2c, 
      2                                 tb_log_name='a2c',
      3                                 total_timesteps=50000)

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\finrl\model\models.py in train_model(self, model, tb_log_name, total_timesteps)
    122 
    123     def train_model(self, model, tb_log_name, total_timesteps=5000):
--> 124         model = model.learn(total_timesteps=total_timesteps, tb_log_name=tb_log_name)
    125         return model
    126 

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\stable_baselines3\a2c\a2c.py in learn(self, total_timesteps, callback, log_interval, eval_env, eval_freq, n_eval_episodes, tb_log_name, eval_log_path, reset_num_timesteps)
    188     ) -> "A2C":
    189 
--> 190         return super(A2C, self).learn(
    191             total_timesteps=total_timesteps,
    192             callback=callback,

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\stable_baselines3\common\on_policy_algorithm.py in learn(self, total_timesteps, callback, log_interval, eval_env, eval_freq, n_eval_episodes, tb_log_name, eval_log_path, reset_num_timesteps)
    217         iteration = 0
    218 
--> 219         total_timesteps, callback = self._setup_learn(
    220             total_timesteps, eval_env, callback, eval_freq, n_eval_episodes, eval_log_path, reset_num_timesteps, tb_log_name
    221         )

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\stable_baselines3\common\base_class.py in _setup_learn(self, total_timesteps, eval_env, callback, eval_freq, n_eval_episodes, log_path, reset_num_timesteps, tb_log_name)
    377         # Avoid resetting the environment when calling ``.learn()`` consecutive times
    378         if reset_num_timesteps or self._last_obs is None:
--> 379             self._last_obs = self.env.reset()
    380             self._last_dones = np.zeros((self.env.num_envs,), dtype=bool)
    381             # Retrieve unnormalized observation for saving into the buffer

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\stable_baselines3\common\vec_env\dummy_vec_env.py in reset(self)
     60         for env_idx in range(self.num_envs):
     61             obs = self.envs[env_idx].reset()
---> 62             self._save_obs(env_idx, obs)
     63         return self._obs_from_buf()
     64 

c:\users\usera\.virtualenvs\stocks-pv8ke_ig\lib\site-packages\stable_baselines3\common\vec_env\dummy_vec_env.py in _save_obs(self, env_idx, obs)
     90         for key in self.keys:
     91             if key is None:
---> 92                 self.buf_obs[key][env_idx] = obs
     93             else:
     94                 self.buf_obs[key][env_idx] = obs[key]

ValueError: setting an array element with a sequence. The requested array would exceed the maximum number of dimension of 1.

The only difference is that I removed all technical indicators from the examples. Is this related anyway?

Youbadawy commented 3 years ago

@XiaoYangLiu-FinRL we can merge issue #109 with this one, same error!

jstzwj commented 3 years ago

I solved the problem by padding the state in finrl.env.env_stocktrading.StockTradingEnv._initiate_state and _update_state before return it.

def _initiate_state(self):
    if self.initial:
        # For Initial State
        if len(self.df.tic.unique())>1:
            # for multiple stock
            state = [self.initial_amount] + \
                     self.data.close.values.tolist() + \
                     [0]*self.stock_dim  + \
                     sum([self.data[tech].values.tolist() for tech in self.tech_indicator_list ], [])
        else:
            # for single stock
            state = [self.initial_amount] + \
                    [self.data.close] + \
                    [0]*self.stock_dim  + \
                    sum([[self.data[tech]] for tech in self.tech_indicator_list ], [])
    else:
        #Using Previous State
        if len(self.df.tic.unique())>1:
            # for multiple stock
            state = [self.previous_state[0]] + \
                     self.data.close.values.tolist() + \
                     self.previous_state[(self.stock_dim+1):(self.stock_dim*2+1)]  + \
                     sum([self.data[tech].values.tolist() for tech in self.tech_indicator_list ], [])
        else:
            # for single stock
            state = [self.previous_state[0]] + \
                    [self.data.close] + \
                    self.previous_state[(self.stock_dim+1):(self.stock_dim*2+1)]  + \
                    sum([[self.data[tech]] for tech in self.tech_indicator_list ], [])

    # Pad state length to self.state_space
    if len(state) < self.state_space:
        state += [0] * (self.state_space - len(state))
    return state
def _update_state(self):
    if len(self.df.tic.unique())>1:
        # for multiple stock
        state =  [self.state[0]] + \
                  self.data.close.values.tolist() + \
                  list(self.state[(self.stock_dim+1):(self.stock_dim*2+1)]) + \
                  sum([self.data[tech].values.tolist() for tech in self.tech_indicator_list ], [])

    else:
        # for single stock
        state =  [self.state[0]] + \
                 [self.data.close] + \
                 list(self.state[(self.stock_dim+1):(self.stock_dim*2+1)]) + \
                 sum([[self.data[tech]] for tech in self.tech_indicator_list ], [])

    # Pad state length to self.state_space
    if len(state) < self.state_space:
        state += [0] * (self.state_space - len(state)) 
    return state
Gambitier commented 3 years ago

I resolved the error with select_equal_rows_stock(), which removed stock index with lesser data.

orthosku commented 2 years ago

I resolved the error with select_equal_rows_stock(), which removed stock index with lesser data.

Can't use this anymore unfortunately; not in the master git anymore.