Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Unhashable type: 'list' #58

Open
srivathsapv opened this issue Oct 18, 2019 · 4 comments
Open

TypeError: Unhashable type: 'list' #58

srivathsapv opened this issue Oct 18, 2019 · 4 comments

Comments

@srivathsapv
Copy link

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?

@rhuang-cbi
Copy link

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

@zafarali
Copy link
Collaborator

zafarali commented Feb 8, 2020

Can you use a Tuple instead?

@collinmccarthy
Copy link

collinmccarthy commented Feb 23, 2020

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.

@linehammer
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants