We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add docs on how to define your own quantizer


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `larq/quantizers.py`
Content:
```
1 """A Quantizer defines the way of transforming a full precision input to a
2 quantized output and the pseudo-gradient method used for the backwards pass."""
3 
4 import tensorflow as tf
5 from larq import utils
6 
7 
8 def sign(x):
9     """A sign function that will never be zero"""
10     return tf.sign(tf.sign(x) + 0.1)
11 
12 
13 @tf.custom_gradient
14 def _binarize_with_identity_grad(x):
15     def grad(dy):
16         return dy
17 
18     return sign(x), grad
19 
20 
21 @tf.custom_gradient
22 def _binarize_with_weighted_grad(x):
23     def grad(dy):
24         return (1 - tf.abs(x)) * 2 * dy
25 
26     return sign(x), grad
27 
28 
29 @utils.register_keras_custom_object
30 def ste_sign(x):
31     r"""
32     Sign binarization function.
33     \\[
34     q(x) = \begin{cases}
35       -1 & x < 0 \\\
36       1 & x \geq 0
37     \end{cases}
38     \\]
39 
40     The gradient is estimated using the Straight-Through Estimator
41     (essentially the binarization is replaced by a clipped identity on the
42     backward pass).
43     \\[\frac{\partial q(x)}{\partial x} = \begin{cases}
44       1 & \left|x\right| \leq 1 \\\
45       0 & \left|x\right| > 1
46     \end{cases}\\]
47 
48     # Arguments
49     x: Input tensor.
50 
51     # Returns
52     Binarized tensor.
53 
54     # References
55     - [Binarized Neural Networks: Training Deep Neural Networks with Weights and
56       Activations Constrained to +1 or -1](http://arxiv.org/abs/1602.02830)
57     """
58 
59     x = tf.clip_by_value(x, -1, 1)
60 
61     return _binarize_with_identity_grad(x)
62 
63 
64 @utils.register_keras_custom_object
65 def magnitude_aware_sign(x):
66     r"""
67     Magnitude-aware sign for birealnet.
68 
69 
70     # Arguments
71     x: Input tensor
72 
73     # Returns
74     Scaled binarized tensor (with values in $\{-a, a\}$, where $a$ is a float).
75 
76     # References
77     - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved
78       Representational Capability and Advanced Training
79       Algorithm](https://arxiv.org/abs/1808.00278)
80 
81     """
82     scale_factor = tf.stop_gradient(
83         tf.reduce_mean(tf.abs(x), axis=list(range(len(x.shape) - 1)))
84     )
85     return scale_factor * ste_sign(x)
86 
87 
88 @utils.register_keras_custom_object
89 def approx_sign(x):
90     r"""
91     Sign binarization function.
92     \\[
93     q(x) = \begin{cases}
94       -1 & x < 0 \\\
95       1 & x \geq 0
96    \end{cases}
97    \\]
98 
99     The gradient is estimated using the ApproxSign method.
100     \\[\frac{\partial q(x)}{\partial x} = \begin{cases}
101       (2 - 2 \left|x\right|) & \left|x\right| \leq 1 \\\
102       0 & \left|x\right| > 1
103     \end{cases}
104     \\]
105 
106     # Arguments
107     x: Input tensor.
108 
109     # Returns
110     Binarized tensor.
111 
112     # References
113     - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved
114       Representational Capability and Advanced
115       Training Algorithm](http://arxiv.org/abs/1808.00278)
116     """
117 
118     x = tf.clip_by_value(x, -1, 1)
119 
120     return _binarize_with_weighted_grad(x)
121 
122 
123 def serialize(initializer):
124     return tf.keras.utils.serialize_keras_object(initializer)
125 
126 
127 def deserialize(name, custom_objects=None):
128     return tf.keras.utils.deserialize_keras_object(
129         name,
130         module_objects=globals(),
131         custom_objects=custom_objects,
132         printable_module_name="quantization function",
133     )
134 
135 
136 def get(identifier):
137     if identifier is None:
138         return None
139     if isinstance(identifier, str):
140         return deserialize(str(identifier))
141     if callable(identifier):
142         return identifier
143     raise ValueError(
144         f"Could not interpret quantization function identifier: {identifier}"
145     )
146
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/larq/quantizers.py b/larq/quantizers.py
--- a/larq/quantizers.py
+++ b/larq/quantizers.py
@@ -64,7 +64,7 @@
 @utils.register_keras_custom_object
 def magnitude_aware_sign(x):
     r"""
-    Magnitude-aware sign for birealnet.
+    Magnitude-aware sign for Bi-Real Net.
 
 
     # Arguments

{"golden_diff": "diff --git a/larq/quantizers.py b/larq/quantizers.py\n--- a/larq/quantizers.py\n+++ b/larq/quantizers.py\n@@ -64,7 +64,7 @@\n @utils.register_keras_custom_object\n def magnitude_aware_sign(x):\n     r\"\"\"\n-    Magnitude-aware sign for birealnet.\n+    Magnitude-aware sign for Bi-Real Net.\n \n \n     # Arguments\n", "issue": "Add docs on how to define your own quantizer\n\n", "before_files": [{"content": "\"\"\"A Quantizer defines the way of transforming a full precision input to a\nquantized output and the pseudo-gradient method used for the backwards pass.\"\"\"\n\nimport tensorflow as tf\nfrom larq import utils\n\n\ndef sign(x):\n    \"\"\"A sign function that will never be zero\"\"\"\n    return tf.sign(tf.sign(x) + 0.1)\n\n\n@tf.custom_gradient\ndef _binarize_with_identity_grad(x):\n    def grad(dy):\n        return dy\n\n    return sign(x), grad\n\n\n@tf.custom_gradient\ndef _binarize_with_weighted_grad(x):\n    def grad(dy):\n        return (1 - tf.abs(x)) * 2 * dy\n\n    return sign(x), grad\n\n\n@utils.register_keras_custom_object\ndef ste_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n    \\end{cases}\n    \\\\]\n\n    The gradient is estimated using the Straight-Through Estimator\n    (essentially the binarization is replaced by a clipped identity on the\n    backward pass).\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      1 & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Binarized Neural Networks: Training Deep Neural Networks with Weights and\n      Activations Constrained to +1 or -1](http://arxiv.org/abs/1602.02830)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_identity_grad(x)\n\n\n@utils.register_keras_custom_object\ndef magnitude_aware_sign(x):\n    r\"\"\"\n    Magnitude-aware sign for birealnet.\n\n\n    # Arguments\n    x: Input tensor\n\n    # Returns\n    Scaled binarized tensor (with values in $\\{-a, a\\}$, where $a$ is a float).\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced Training\n      Algorithm](https://arxiv.org/abs/1808.00278)\n\n    \"\"\"\n    scale_factor = tf.stop_gradient(\n        tf.reduce_mean(tf.abs(x), axis=list(range(len(x.shape) - 1)))\n    )\n    return scale_factor * ste_sign(x)\n\n\n@utils.register_keras_custom_object\ndef approx_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n   \\end{cases}\n   \\\\]\n\n    The gradient is estimated using the ApproxSign method.\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      (2 - 2 \\left|x\\right|) & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\n    \\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced\n      Training Algorithm](http://arxiv.org/abs/1808.00278)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_weighted_grad(x)\n\n\ndef serialize(initializer):\n    return tf.keras.utils.serialize_keras_object(initializer)\n\n\ndef deserialize(name, custom_objects=None):\n    return tf.keras.utils.deserialize_keras_object(\n        name,\n        module_objects=globals(),\n        custom_objects=custom_objects,\n        printable_module_name=\"quantization function\",\n    )\n\n\ndef get(identifier):\n    if identifier is None:\n        return None\n    if isinstance(identifier, str):\n        return deserialize(str(identifier))\n    if callable(identifier):\n        return identifier\n    raise ValueError(\n        f\"Could not interpret quantization function identifier: {identifier}\"\n    )\n", "path": "larq/quantizers.py"}], "after_files": [{"content": "\"\"\"A Quantizer defines the way of transforming a full precision input to a\nquantized output and the pseudo-gradient method used for the backwards pass.\"\"\"\n\nimport tensorflow as tf\nfrom larq import utils\n\n\ndef sign(x):\n    \"\"\"A sign function that will never be zero\"\"\"\n    return tf.sign(tf.sign(x) + 0.1)\n\n\n@tf.custom_gradient\ndef _binarize_with_identity_grad(x):\n    def grad(dy):\n        return dy\n\n    return sign(x), grad\n\n\n@tf.custom_gradient\ndef _binarize_with_weighted_grad(x):\n    def grad(dy):\n        return (1 - tf.abs(x)) * 2 * dy\n\n    return sign(x), grad\n\n\n@utils.register_keras_custom_object\ndef ste_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n    \\end{cases}\n    \\\\]\n\n    The gradient is estimated using the Straight-Through Estimator\n    (essentially the binarization is replaced by a clipped identity on the\n    backward pass).\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      1 & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Binarized Neural Networks: Training Deep Neural Networks with Weights and\n      Activations Constrained to +1 or -1](http://arxiv.org/abs/1602.02830)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_identity_grad(x)\n\n\n@utils.register_keras_custom_object\ndef magnitude_aware_sign(x):\n    r\"\"\"\n    Magnitude-aware sign for Bi-Real Net.\n\n\n    # Arguments\n    x: Input tensor\n\n    # Returns\n    Scaled binarized tensor (with values in $\\{-a, a\\}$, where $a$ is a float).\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced Training\n      Algorithm](https://arxiv.org/abs/1808.00278)\n\n    \"\"\"\n    scale_factor = tf.stop_gradient(\n        tf.reduce_mean(tf.abs(x), axis=list(range(len(x.shape) - 1)))\n    )\n    return scale_factor * ste_sign(x)\n\n\n@utils.register_keras_custom_object\ndef approx_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n   \\end{cases}\n   \\\\]\n\n    The gradient is estimated using the ApproxSign method.\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      (2 - 2 \\left|x\\right|) & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\n    \\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced\n      Training Algorithm](http://arxiv.org/abs/1808.00278)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_weighted_grad(x)\n\n\ndef serialize(initializer):\n    return tf.keras.utils.serialize_keras_object(initializer)\n\n\ndef deserialize(name, custom_objects=None):\n    return tf.keras.utils.deserialize_keras_object(\n        name,\n        module_objects=globals(),\n        custom_objects=custom_objects,\n        printable_module_name=\"quantization function\",\n    )\n\n\ndef get(identifier):\n    if identifier is None:\n        return None\n    if isinstance(identifier, str):\n        return deserialize(str(identifier))\n    if callable(identifier):\n        return identifier\n    raise ValueError(\n        f\"Could not interpret quantization function identifier: {identifier}\"\n    )\n", "path": "larq/quantizers.py"}]}