{"action":"opened","issue":{"url":"https://api.github.com/repos/fchollet/keras/issues/4434","repository_url":"https://api.github.com/repos/fchollet/keras","labels_url":"https://api.github.com/repos/fchollet/keras/issues/4434/labels{/name}","comments_url":"https://api.github.com/repos/fchollet/keras/issues/4434/comments","events_url":"https://api.github.com/repos/fchollet/keras/issues/4434/events","html_url":"https://github.com/fchollet/keras/issues/4434","id":190499147,"number":4434,"title":"High order functions in the backend","user":{"login":"angeloskath","id":1242043,"avatar_url":"https://avatars.githubusercontent.com/u/1242043?v=3","gravatar_id":"","url":"https://api.github.com/users/angeloskath","html_url":"https://github.com/angeloskath","followers_url":"https://api.github.com/users/angeloskath/followers","following_url":"https://api.github.com/users/angeloskath/following{/other_user}","gists_url":"https://api.github.com/users/angeloskath/gists{/gist_id}","starred_url":"https://api.github.com/users/angeloskath/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/angeloskath/subscriptions","organizations_url":"https://api.github.com/users/angeloskath/orgs","repos_url":"https://api.github.com/users/angeloskath/repos","events_url":"https://api.github.com/users/angeloskath/events{/privacy}","received_events_url":"https://api.github.com/users/angeloskath/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-11-19T14:29:00Z","updated_at":"2016-11-19T14:29:00Z","closed_at":null,"body":"I am wondering why the Keras backend doesn't expose high order functions like **map** and **fold**. I have also made such an inquiry in the [Google group](https://groups.google.com/forum/#!topic/keras-users/XNC0baemYqg) and got no answers.\r\n\r\nI will be showing here how one would implement the following code in a Keras layer with and without the backend supporting high order functions to make a point of why we need it. I have already implemented it and I could make a pull request but the guidelines suggest I make an issue first so there you have it. (I hope it is not too big a code snippet for including it directly in the issue).\r\n\r\n```python\r\ndef g(x, w):\r\n    pass # Do some non trivial work with x and w\r\n\r\n# Example code implemented with numpy. It might not make much\r\n# sense but bare with me.\r\ndef f_numpy(batch, w):\r\n    s = np.zeros((batch.shape[0], batch.shape[-1]))\r\n    for i, x in enumerate(batch):\r\n        for feature in x:\r\n            s[i] += g(feature, w)\r\n    return s\r\n\r\n# The implementation in pure keras using the proposed changes\r\n# agnostic of g and backend\r\nfrom keras import backend as K\r\ndef f_keras_proposed(batch, w):\r\n    return K.map_fn(\r\n        lambda feature: K.foldl(\r\n            lambda acc, x: acc + g(x, w),\r\n            feature,\r\n            K.zeros_like(feature[0])\r\n        ),\r\n        batch\r\n    )\r\n\r\n# Implementation in Keras agnostic of g and backend with the current API\r\nfrom keras import backend as K\r\ntry:\r\n    import theano as T\r\nexcept ImportError:\r\n    pass\r\ntry:\r\n    import tensorflow as tf\r\nexcept ImportError:\r\n    pass\r\ndef f_keras_now(batch, w):\r\n    if K.backend() == \"theano\":\r\n        # It could also be done with map and sum just making a point here\r\n        return T.map(\r\n            lambda feature: T.foldl(\r\n                lambda x, acc: acc + g(x, w),\r\n                feature,\r\n                T.zeros_like(feature[0])\r\n            )[0],\r\n            batch\r\n        )[0]\r\n    elif K.backend() == \"tensorflow\":\r\n        return tf.map_fn(\r\n            lambda feature: tf.foldl(\r\n                lambda acc, x: acc + g(x, w),\r\n                feature,\r\n                tf.zeros_like(feature[0])\r\n            ),\r\n            batch\r\n        )\r\n    else:\r\n        raise RuntimeError((\"Function not implemented for keras \"\r\n                                         \"backend '%s'\") % (K.backend(),))\r\n```\r\n\r\nFor functionality that the backends disagree on or that is too hard to implement with the same API in both backends I would understand it but in this case it seems an omission to me.\r\n\r\nAnyway, thanks for the amazing work!\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)."}}
{"actor":{"display_login":"angeloskath"}}