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

Add Keras layers support #529

Merged
merged 84 commits into from Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
fefc10e
Add first commit of keras interface
trbromley Mar 2, 2020
92e8f6e
Merge branch 'master' into keras_layer
josh146 Mar 4, 2020
bf57067
Update keras interface
trbromley Mar 4, 2020
dfda731
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 4, 2020
094b2d7
Make qnode.func visible in TF QNode
trbromley Mar 5, 2020
d82f368
Merge branch 'master' into keras_layer
trbromley Mar 10, 2020
58d2f3e
Move to new location
trbromley Mar 10, 2020
f3461da
Update
trbromley Mar 10, 2020
73c0d98
Move to right place
trbromley Mar 10, 2020
64cee5b
Update
trbromley Mar 10, 2020
2a41627
Start working on tests
trbromley Mar 10, 2020
80e2112
Add unit tests
trbromley Mar 11, 2020
518a60f
Update tests
trbromley Mar 11, 2020
a2b2ae5
Update test
trbromley Mar 11, 2020
f652a05
Update integration tests
trbromley Mar 11, 2020
12ddea7
Add to integration tests
trbromley Mar 11, 2020
9e2bf39
Allow for multiple types of tf.float
trbromley Mar 12, 2020
c47ce83
Revert changes
trbromley Mar 12, 2020
27a559a
Allow for output type to be set as an argument
trbromley Mar 12, 2020
b66aeec
Merge branch 'master' into keras_layer
trbromley Mar 12, 2020
7b2ecfc
Simplify circuit in test
trbromley Mar 12, 2020
709962f
Update tests
trbromley Mar 12, 2020
e05ec43
Run black
trbromley Mar 12, 2020
0b89ad3
Apply isort
trbromley Mar 12, 2020
ebed9ce
Tidy up due to PyLint
trbromley Mar 12, 2020
6747bc4
Add to docstrings
trbromley Mar 13, 2020
a0ae1a2
Merge branch 'master' into keras_layer
josh146 Mar 13, 2020
9263b58
Add to documentation
trbromley Mar 13, 2020
38e37c3
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 13, 2020
c45b887
Finalize docstrings
trbromley Mar 13, 2020
3206c01
Test with multiple input interfaces
trbromley Mar 13, 2020
84ed633
Merge branch 'master' into keras_layer
trbromley Mar 13, 2020
f0e8bbc
Run black
trbromley Mar 13, 2020
7c658e2
Remove from __init__ because this module requires TF explicitly
trbromley Mar 13, 2020
5715f4e
Update tests for cases where TF is not available
trbromley Mar 13, 2020
fca88d6
Fix tensor flow versioning
trbromley Mar 13, 2020
865688a
Skip variable in docs
trbromley Mar 13, 2020
c2ec895
Merge branch 'master' into keras_layer
mariaschuld Mar 16, 2020
cff01dd
Merge branch 'master' into keras_layer
josh146 Mar 16, 2020
26c2a98
Apply suggestions from code review
trbromley Mar 17, 2020
c85e5f2
Apply suggestions from code review
trbromley Mar 17, 2020
c8b078a
Apply suggestions from code review
trbromley Mar 17, 2020
492cda3
Apply suggestions from code review
trbromley Mar 17, 2020
d215200
Merge branch 'master' into keras_layer
trbromley Mar 17, 2020
c31abd9
Apply isort
trbromley Mar 17, 2020
37222d7
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 17, 2020
901dad0
Revert isort due to lint errors
trbromley Mar 17, 2020
ee8b969
Restructure
trbromley Mar 17, 2020
929e522
Apply black
trbromley Mar 17, 2020
f73b2fb
Merge branch 'master' into keras_layer
josh146 Mar 22, 2020
02874c0
Apply suggestions and make class attribute
trbromley Mar 23, 2020
e57b987
Apply suggestions from code review
trbromley Mar 23, 2020
e1102a5
Merge branch 'master' into keras_layer
mariaschuld Mar 24, 2020
37e4f5a
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 24, 2020
65e5cba
Apply suggestions from code review
trbromley Mar 24, 2020
0890145
Merge branch 'master' into keras_layer
trbromley Mar 24, 2020
b261348
Fix failing test
trbromley Mar 24, 2020
6f4f394
Update changelog
trbromley Mar 24, 2020
7d465a1
Merge branch 'master' into keras_layer
trbromley Mar 30, 2020
11a2aa7
Apply suggestions from code review
trbromley Mar 30, 2020
7f6c59a
Apply suggestions from code review
trbromley Mar 30, 2020
365d66b
Apply suggestions from code review
trbromley Mar 30, 2020
8c93384
Apply suggestions from code review
trbromley Mar 30, 2020
0bfca8c
Explain import
trbromley Mar 30, 2020
0fb5294
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 30, 2020
1c44624
Apply suggestions from code review
trbromley Mar 30, 2020
3e6e2e7
Apply suggestions from code review
trbromley Mar 30, 2020
06c9bc8
Merge branch 'keras_layer' of github.com:XanaduAI/pennylane into kera…
trbromley Mar 30, 2020
ee97ad6
Apply suggestions from code review
trbromley Mar 30, 2020
d812c2a
Fix pylint and apply black
trbromley Mar 30, 2020
a7affd5
Fix docs building
trbromley Mar 30, 2020
b09442e
Improve docs
trbromley Mar 30, 2020
2cd1585
Change example to have multidimensional input
trbromley Mar 31, 2020
b335b0f
Reorder Usage details
trbromley Mar 31, 2020
daef030
Update input_arg to property
trbromley Mar 31, 2020
1741f79
Remove setter and fix tests
trbromley Mar 31, 2020
e0c3548
Clarify docstring
trbromley Mar 31, 2020
54beadf
Apply black
trbromley Mar 31, 2020
bc017a0
Update pennylane/qnn/keras.py
co9olguy Mar 31, 2020
00a0a4a
Merge branch 'master' into keras_layer
trbromley Apr 1, 2020
a768967
Fix typo in changelog
trbromley Apr 1, 2020
66407b1
Fix link
trbromley Apr 1, 2020
2c61112
Update changelog to reflect current example
trbromley Apr 1, 2020
861ec80
Update indentation
trbromley Apr 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 46 additions & 37 deletions pennylane/qnn/keras.py
Expand Up @@ -73,7 +73,8 @@ class KerasLayer(Layer):

@qml.qnode(dev)
def qnode(inputs, weights_0, weight_1):
qml.RX(inputs, wires=0)
qml.RX(inputs[0], wires=0)
qml.RX(inputs[1], wires=1)
qml.Rot(*weights_0, wires=0)
qml.RY(weight_1, wires=1)
qml.CNOT(wires=[0, 1])
Expand All @@ -89,6 +90,39 @@ def qnode(inputs, weights_0, weight_1):

.. UsageDetails::

The QNode must have a signature that satisfies the following conditions:

- Contain an ``inputs`` named argument for input data.
- All other arguments must accept an array or tensor and are treated as internal
weights of the QNode.
- All other arguments must have no default value.
- The ``inputs`` argument is permitted to have a default value provided the gradient with
respect to ``inputs`` is not required.
- There cannot be a variable number of positional or keyword arguments, e.g., no ``*args``
or ``**kwargs`` present in the signature.

The optional ``weight_specs`` argument allows for a more fine-grained
specification of the QNode weights, such as the method of initialization and any
regularization or constraints. For example, the initialization method of the ``weights``
argument in the example above could be specified by:

.. code-block::

weight_specs = {"weights": {"initializer": "random_uniform"}}

The values of ``weight_specs`` are dictionaries with keys given by arguments of
the Keras
`add_weight() <https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_weight>`__
method. For the ``"initializer"`` argument, one can specify a string such as
``"random_uniform"`` or an instance of an `Initializer
<https://www.tensorflow.org/api_docs/python/tf/keras/initializers>`__ class, such as
`tf.keras.initializers.RandomUniform <https://www.tensorflow.org/api_docs/python/tf/random_uniform_initializer>`__.

If ``weight_specs`` is not specified, weights will be added using the Keras default
initialization and without any regularization or constraints.
trbromley marked this conversation as resolved.
Show resolved Hide resolved

**Additional example**

The code block below shows how a circuit composed of templates from the
:doc:`/code/qml_templates` module can be combined with classical
`Dense <https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense>`__ layers to learn
Expand All @@ -106,8 +140,8 @@ def qnode(inputs, weights_0, weight_1):

@qml.qnode(dev)
def qnode(inputs, weights):
qml.templates.AngleEmbedding(inputs, wires=list(range(n_qubits)))
qml.templates.StronglyEntanglingLayers(weights, wires=list(range(n_qubits)))
qml.templates.AngleEmbedding(inputs, wires=range(n_qubits))
qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))
return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))

weight_shapes = {"weights": (3, n_qubits, 3)}
Expand Down Expand Up @@ -145,42 +179,8 @@ def qnode(inputs, weights):
Epoch 8/8
100/100 [==============================] - 9s 87ms/sample - loss: 0.1474

The QNode must have a signature that satisfies the following conditions:

- Contain an ``inputs`` named argument for input data.
- All other arguments must accept an array or tensor and are treated as internal
weights of the QNode.
- All other arguments must have no default value.
- The ``inputs`` argument is permitted to have a default value provided the gradient with
respect to ``inputs`` is not required.
- There cannot be a variable number of positional or keyword arguments, e.g., no ``*args``
or ``**kwargs`` present in the signature.

The optional ``weight_specs`` argument allows for a more fine-grained
specification of the QNode weights, such as the method of initialization and any
regularization or constraints. For example, the initialization method of the ``weights``
argument in the example above could be specified by:

.. code-block::

weight_specs = {"weights": {"initializer": "random_uniform"}}

The values of ``weight_specs`` are dictionaries with keys given by arguments of
the Keras
`add_weight() <https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_weight>`__
method. For the ``"initializer"`` argument, one can specify a string such as
``"random_uniform"`` or an instance of an `Initializer
<https://www.tensorflow.org/api_docs/python/tf/keras/initializers>`__ class, such as
`tf.keras.initializers.RandomUniform <https://www.tensorflow.org/api_docs/python/tf/random_uniform_initializer>`__.

If ``weight_specs`` is not specified, weights will be added using the Keras default
initialization and without any regularization or constraints.

.. _Layer: https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer
"""
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved

input_arg = "inputs"

def __init__(
self, qnode, weight_shapes: dict, output_dim, weight_specs: Optional[dict] = None, **kwargs
):
Expand Down Expand Up @@ -294,3 +294,12 @@ def __str__(self):
return detail.format(self.qnode.func.__name__)

__repr__ = __str__

_input_arg = "inputs"

@property
def input_arg(self):
"""Name of the argument to be used as the input to the Keras
`Layer <https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer>`__. Set to
``"inputs"``."""
return self._input_arg
trbromley marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 4 additions & 4 deletions tests/qnn/test_keras.py
Expand Up @@ -107,7 +107,7 @@ def test_no_input(self, get_circuit, output_dim):
"""Test if a TypeError is raised when instantiated with a QNode that does not have an
argument with name equal to the input_arg class attribute of KerasLayer"""
c, w = get_circuit
del c.func.sig[qml.qnn.keras.KerasLayer.input_arg]
del c.func.sig[qml.qnn.keras.KerasLayer._input_arg]
with pytest.raises(TypeError, match="QNode must include an argument with name"):
KerasLayer(c, w, output_dim)

Expand All @@ -118,11 +118,11 @@ def test_input_in_weight_shapes(self, get_circuit, n_qubits, output_dim):
contains the shape of the input argument given by the input_arg class attribute of
KerasLayer"""
c, w = get_circuit
w[qml.qnn.keras.KerasLayer.input_arg] = n_qubits
w[qml.qnn.keras.KerasLayer._input_arg] = n_qubits
with pytest.raises(
ValueError,
match="{} argument should not have its dimension".format(
qml.qnn.keras.KerasLayer.input_arg
qml.qnn.keras.KerasLayer._input_arg
),
):
KerasLayer(c, w, output_dim)
Expand Down Expand Up @@ -218,7 +218,7 @@ def c_dummy(inputs, w1, w2, w3, w4, w5, w6, w7, w8=None):

with pytest.raises(
TypeError,
match="Only the argument {} is permitted".format(qml.qnn.keras.KerasLayer.input_arg),
match="Only the argument {} is permitted".format(qml.qnn.keras.KerasLayer._input_arg),
):
KerasLayer(c_dummy, {**w, **{"w8": 1}}, output_dim)

Expand Down