test-tube icon indicating copy to clipboard operation
test-tube copied to clipboard

TypeError: Unhashable type: 'list'

Open srivathsapv opened this issue 4 years ago • 4 comments

I am trying to extend my existing argparse with the HyperOptArgumentParser class. In my current argparse I have two options which are nargs list.

When I do the following,

parser = HyperOptArgumentParser(stratergy='random_search')

....


parser.add_argument('--input_idx', nargs='+', type=int, help='input indices from data', default=[0, 1])
parser.add_argument('--output_idx', nargs='+', type=int, help='output indices from data', default=[2])

I get this error:

Traceback (most recent call last):
  File "train_process.py", line 11, in <module>
    args = parser.parse_args()
  File "/home/srivathsa/miniconda3/envs/py35gad/lib/python3.6/site-packages/test_tube/argparse_hopt.py", line 237, in parse_args
    results = self.__parse_args(args, namespace)
  File "/home/srivathsa/miniconda3/envs/py35gad/lib/python3.6/site-packages/test_tube/argparse_hopt.py", line 158, in __parse_args
    args, argv = self.__whitelist_cluster_commands(args, argv)
  File "/home/srivathsa/miniconda3/envs/py35gad/lib/python3.6/site-packages/test_tube/argparse_hopt.py", line 196, in __whitelist_cluster_commands
    all_values.add(v)
TypeError: unhashable type: 'list'

How can I fix this?

srivathsapv avatar Oct 18 '19 19:10 srivathsapv

I'm using test tube with pytorch lightning and experienced the same issue. Any thoughts?

rhuang-cbi avatar Jan 09 '20 19:01 rhuang-cbi

Can you use a Tuple instead?

zafarali avatar Feb 08 '20 14:02 zafarali

I ran into this problem and ended up creating a function to convert strings to tuples so when parser.parse_args() is called it passes the tuples onto the __parse_args() and __whitelist_cluster_commands() methods shown in the traceback above.

These are the methods I used (since in my case I needed lists of strings and integers):

def str_to_str_tuple(str_value):
    """Convert string to tuple of strings for HyperOptArgumentParser with multiple inputs"""
    if isinstance(str_value, tuple):
        return str_value
    
    # Remove spaces
    str_value = str_value.replace(' ', '')
    
    # Remove braces/brackets/parenthesis on outside
    str_value = str_value.strip('[](){}')
    
    # Split by comma
    return tuple(str_value.split(','))

def str_to_int_tuple(str_value):
    """Convert string to tuple of ints for HyperOptArgumentParser with multiple inputs"""
    
    # Create a str tuple, then convert to int
    str_tuple = str_to_str_tuple(str_value)
    return tuple([int(str_val) for str_val in str_tuple])

And then using the example in the OP, I called parser.add_argument() like so, passing in something like '[0, 1]' on the command line:

parser.add_argument('--input_idx', type=str_to_int_tuple, help='input indices from data', default='[0, 1]')
parser.add_argument('--output_idx', type=str_to_int_tuple, help='output indices from data', default='[2]')

Ultimately, however, I ended up not using the HyperOptArgumentParser for my project because 1) I only wanted a grid search (to not seem like I was over optimizing in a paper) and 2) I was already reading in a JSON config file, so having another section for a list of arguments to iterate over was easy. Doing it that way on my own, and then using PyTorch-Lightning to handle multi-node/multi-GPU on top of that, led to more readable code than using this class. But I'm sure in other contexts this class is quite useful.

collinmccarthy avatar Feb 23 '20 06:02 collinmccarthy

The problem is that you can't use a list as the key in a dict, since dict keys need to be immutable. This means that when you try to hash an unhashable object it will result an error. For ex. when you use a list as a key in the dictionary , this cannot be done because lists can't be hashed. The standard way to solve this issue is to cast a list to a tuple . TypeError: unhashable type: 'list' usually means that you are trying to use a list as an hash argument. The standard way to solve this issue is to cast a list to tuple.

Though tuples may seem similar to lists, they are often used in different situations and for different purposes. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can’t use lists as key.

linehammer avatar Nov 16 '21 05:11 linehammer