{"action":"created","issue":{"url":"https://api.github.com/repos/fchollet/keras/issues/2559","repository_url":"https://api.github.com/repos/fchollet/keras","labels_url":"https://api.github.com/repos/fchollet/keras/issues/2559/labels{/name}","comments_url":"https://api.github.com/repos/fchollet/keras/issues/2559/comments","events_url":"https://api.github.com/repos/fchollet/keras/issues/2559/events","html_url":"https://github.com/fchollet/keras/issues/2559","id":151974893,"number":2559,"title":"ImageDataGenerator samplewise_center standardize method subtracting mean over image channels","user":{"login":"Liyang90","id":17171233,"avatar_url":"https://avatars.githubusercontent.com/u/17171233?v=3","gravatar_id":"","url":"https://api.github.com/users/Liyang90","html_url":"https://github.com/Liyang90","followers_url":"https://api.github.com/users/Liyang90/followers","following_url":"https://api.github.com/users/Liyang90/following{/other_user}","gists_url":"https://api.github.com/users/Liyang90/gists{/gist_id}","starred_url":"https://api.github.com/users/Liyang90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Liyang90/subscriptions","organizations_url":"https://api.github.com/users/Liyang90/orgs","repos_url":"https://api.github.com/users/Liyang90/repos","events_url":"https://api.github.com/users/Liyang90/events{/privacy}","received_events_url":"https://api.github.com/users/Liyang90/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2016-04-29T21:44:00Z","updated_at":"2016-10-25T15:35:41Z","closed_at":null,"body":"In the standardize method of ImageDataGenerator:\r\n\r\n```python\r\ndef standardize(self, x):\r\n        # x is a single image, so it doesn't have image number at index 0\r\n        img_channel_index = self.channel_index - 1\r\n        if self.samplewise_center:\r\n            x -= np.mean(x, axis=img_channel_index, keepdims=True)\r\n        if self.samplewise_std_normalization:\r\n            x /= (np.std(x, axis=img_channel_index, keepdims=True) + 1e-7)\r\n...\r\n...\r\n```\r\n\r\nThe mean for samplewise_center and std for samplewise_std_normalization are calculated only over the image channel axis instead of the whole image (all pixels and all channels).\r\n\r\nAs an example (test code attached), if the input image has only one channel (gray scale image), after performing\r\nx -= np.mean(x, axis=img_channel_index, keepdims=True)\r\nThe image will be all 0!\r\n\r\nAccording to the definition of \r\nsamplewise_center: set each sample mean to 0.\r\nsamplewise_std_normalization: divide each input by its std.\r\nI think calculating mean and std over the whole input image (Global Contrast Normalization), by removing \"axis=img_channel_index, \" would make more sense.\r\n\r\nTest code:\r\n```python\r\n# test the ImageDataGenerator\r\n\r\nfrom keras.datasets import cifar10\r\nfrom keras.preprocessing.image import ImageDataGenerator\r\nimport matplotlib.pyplot as plt\r\nfrom keras.utils import np_utils\r\nimport numpy as np\r\n\r\nnb_classes = 10\r\n\r\n(X_train, y_train), (X_test, y_test) = cifar10.load_data()\r\nprint('X_train shape:', X_train.shape)\r\nprint(X_train.shape[0], 'train samples')\r\nprint(X_test.shape[0], 'test samples')\r\n\r\n# convert class vectors to binary class matrices\r\nY_train = np_utils.to_categorical(y_train, nb_classes)\r\nY_test = np_utils.to_categorical(y_test, nb_classes)\r\n\r\nX_train = X_train.astype('float32')\r\nX_test = X_test.astype('float32')\r\nX_train /= 255\r\nX_test /= 255\r\n\r\n# change RGB image to 1-channel gray scale image\r\nX_train = np.mean(X_train, axis=1, keepdims=True) \r\n\r\ndatagen_GCN = ImageDataGenerator(\r\n        featurewise_center=False, \r\n        samplewise_center=True,  # set each sample mean to 0\r\n        featurewise_std_normalization=False,  \r\n        samplewise_std_normalization=False,  \r\n        zca_whitening=False) \r\n\r\ndatagen_GCN.fit(X_train) \r\n\r\nbatch_count = 0\r\nfor X_batch1, Y_batch1 in datagen_GCN.flow(X_train, Y_train, batch_size=20):\r\n    batch_count += 1\r\n    \r\n    if batch_count >= 1:\r\n\r\n        break\r\n\r\n# the images in X_batch1 are all 0!!!\r\n```\r\n\r\nPlease make sure that the boxes below are checked before you submit your issue. Thank you!\r\n\r\n- [x] Check that you are up-to-date with the master branch of Keras. You can update with:\r\npip install git+git://github.com/fchollet/keras.git --upgrade --no-deps\r\n\r\n- [x] If running on Theano, check that you are up-to-date with the master branch of Theano. You can update with:\r\npip install git+git://github.com/Theano/Theano.git --upgrade --no-deps\r\n\r\n- [x] Provide a link to a GitHub Gist of a Python script that can reproduce your issue (or just copy the script here if it is short)."},"comment":{"url":"https://api.github.com/repos/fchollet/keras/issues/comments/256071581","html_url":"https://github.com/fchollet/keras/issues/2559#issuecomment-256071581","issue_url":"https://api.github.com/repos/fchollet/keras/issues/2559","id":256071581,"user":{"login":"eyaler","id":4436747,"avatar_url":"https://avatars.githubusercontent.com/u/4436747?v=3","gravatar_id":"","url":"https://api.github.com/users/eyaler","html_url":"https://github.com/eyaler","followers_url":"https://api.github.com/users/eyaler/followers","following_url":"https://api.github.com/users/eyaler/following{/other_user}","gists_url":"https://api.github.com/users/eyaler/gists{/gist_id}","starred_url":"https://api.github.com/users/eyaler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eyaler/subscriptions","organizations_url":"https://api.github.com/users/eyaler/orgs","repos_url":"https://api.github.com/users/eyaler/repos","events_url":"https://api.github.com/users/eyaler/events{/privacy}","received_events_url":"https://api.github.com/users/eyaler/received_events","type":"User","site_admin":false},"created_at":"2016-10-25T15:35:41Z","updated_at":"2016-10-25T15:35:41Z","body":"https://github.com/fchollet/keras/issues/3422"}}
{"actor":{"display_login":"eyaler"}}