Trusted-AI / adversarial-robustness-toolbox

Adversarial Robustness Toolbox (ART) - Python Library for Machine Learning Security - Evasion, Poisoning, Extraction, Inference - Red and Blue Teams
https://adversarial-robustness-toolbox.readthedocs.io/en/latest/
MIT License
4.75k stars 1.15k forks source link

Incomplete EstimatorError when initializing attack on PyTorchRegressor #2228

Open KandBM opened 1 year ago

KandBM commented 1 year ago

Describe the bug Initializing an attack on a PyTorchRegressor throws an EstimatorError with missing words in the message: EstimatorError: AutoProjectedGradientDescent requires an estimator derived from and and , the provided classifier is an instance of and is derived from (, ).

To Reproduce EDIT: I'm adding some new code for clarity, and changed it so the regressor has only one output. Sorry for the weird layout, I'm copying cells from a notebook.

from stable_baselines3.sac import SAC
from citylearn.citylearn import CityLearnEnv
from citylearn.wrappers import NormalizedObservationWrapper, StableBaselines3Wrapper
from citylearn.data import DataSet
from typing import List

dataset_name = 'baeda_3dem'
schema = DataSet.get_schema(dataset_name)
def set_active_actions(
    schema: dict, active_actions: List[str]
) -> dict:
    """Set the actions that will be part of the environment's 
    observation space that is provided to the control agent.

    Parameters
    ----------
    schema: dict
        CityLearn dataset mapping used to construct environment.
    active_actions: List[str]
        Names of actions to set active to be passed to control agent.

    Returns
    -------
    schema: dict
        CityLearn dataset mapping with active actions set.
    """

    active_count = 0

    for o in schema['actions']:
        if o in active_actions:
            schema['actions'][o]['active'] = True
            active_count += 1
        else:
            schema['actions'][o]['active'] = False

    valid_actions = list(schema['actions'].keys())
    assert active_count == len(active_actions),\
        'the provided actions are not all valid actions.'\
          f' Valid actionss in CityLearn are: {valid_actions}'

    return schema

schema = set_active_actions(schema, ['cooling_storage'])

def del_buildings(
schema: dict, buildings_to_del: List[str]
) -> dict:
        """removes buildings from a CityLeanr Schema.

    Parameters
    ----------
    schema: dict
        CityLearn dataset mapping used to construct environment.
    buildings_to_del: List[str]
        Names of buildings to be removed from the environment.

    Returns
    -------
    schema: dict
        CityLearn dataset mapping with buildings removed.
    """

        print('Buildings in original schema: ', list(schema['buildings'].keys()))
        schema['buildings'] = {key: value for key, value in schema['buildings'].items() if key not in buildings_to_del}
        print('Buildings in new schema: ', list(schema['buildings'].keys()))

        return schema

schema = del_buildings(schema, ['Building_2', 'Building_3', 'Building_4'])

env = CityLearnEnv(schema, central_agent=True, simulation_end_time_step=1000) #https://www.citylearn.net/api/citylearn.citylearn.html
env = NormalizedObservationWrapper(env)
env = StableBaselines3Wrapper(env)
agent = SAC('MlpPolicy', env)

from copy import deepcopy
policy_net = deepcopy(agent.actor.latent_pi) #copies shared net rather than referencing/changing the agent
policy_net.add_module('4', agent.actor.mu)

from art.estimators.regression import PyTorchRegressor as regressor
from torch.nn import MSELoss

victim_policy = regressor(
    model=policy_net,
    loss=MSELoss(), #most common func for regression
    input_shape=agent.observation_space.shape,
    device_type='gpu'
    )

from art.attacks.evasion import AutoProjectedGradientDescent as APGD
from art.attacks.evasion import AutoConjugateGradient as ACG

#errors below
APGDatk = APGD(estimator=victim_policy)
ACGatk = ACG(estimator=victim_policy)

The environment can be reproduced with the following commands:

conda create -n CityLearnART python=3.10 setuptools==66 wheel<0.40 numpy pytorch==1.12.0 torchvision==0.13.0 torchaudio==0.12.0 cudatoolkit=11.6 ipywidgets -c pytorch -c conda-forge

conda activate CityLearnART

pip install adversarial-robustness-toolbox[pytorch]==1.15.0 citylearn==2.0b3 stable-baselines3==1.8.0

Expected behavior Attack should be initialized with the regression model as the estimator.

System information (please complete the following information):

beat-buesser commented 1 year ago

Hi @KandBM Please apologise the delayed response and thank you for opening this issue. I can see multiple issues here.

KandBM commented 1 year ago

Thanks @beat-buesser ! I half expected the regression was the issue, so I'll give your suggestion a shot (sorry for the late reply, I was on vacation without internet).