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

Drop support for Python 3.5 #184

Merged
merged 4 commits into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ image: Visual Studio 2019

environment:
MODE: test
PYTHON_VERSION: C:\Python36-x64
PYTHON_VERSION: C:\Python37-x64
NUMPY_VERSION: numpy
TF_VERSION: tensorflow
NENGO_VERSION: nengo[tests]
Expand All @@ -18,7 +18,7 @@ environment:
- NENGO_VERSION: nengo[tests]==3.0.0
TF_VERSION: tensorflow==2.2.0
NUMPY_VERSION: numpy==1.16.0
PYTHON_VERSION: C:\Python35-x64
PYTHON_VERSION: C:\Python36-x64

init:
- set PATH=%PYTHON_VERSION%;%PYTHON_VERSION%\Scripts;%PATH%
Expand Down
5 changes: 2 additions & 3 deletions .nengobones.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ ci_scripts:
- template: deploy

travis_yml:
python: 3.6
python: 3.7
global_vars:
NUMPY_VERSION: numpy>=1.16.0
TF_VERSION: tensorflow
Expand All @@ -256,7 +256,7 @@ travis_yml:
NENGO_VERSION: nengo[tests]==3.0.0
TF_VERSION: tensorflow==2.2.0
NUMPY_VERSION: numpy==1.16.0
python: 3.5
python: 3.6
- script: test-coverage
test_args: --graph-mode
- stage: advanced
Expand Down Expand Up @@ -315,7 +315,6 @@ setup_py:
- "Operating System :: Microsoft :: Windows"
- "Operating System :: POSIX :: Linux"
- "Programming Language :: Python"
- "Programming Language :: Python :: 3.5"
- "Programming Language :: Python :: 3.6"
- "Programming Language :: Python :: 3.7"
- "Programming Language :: Python :: 3.8"
Expand Down
4 changes: 2 additions & 2 deletions .templates/setup.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ else:
# environment, so we can't just look up the tensorflow version in the current
# environment. but the pip package will be in the isolated sys.path, so we can use
# that to look up the site-packages directory of the original environment.
target_path = os.path.join("site-packages", "pip")
target_path = str(pathlib.Path("site-packages", "pip"))
for path in sys.path:
if target_path in path:
source_path = [path[: path.index("pip")]]
Expand All @@ -44,7 +44,7 @@ else:
install_req = [
"nengo>=3.0.0",
"numpy>=1.16.0",
"%s>=2.2.0" % tf_req,
"{}>=2.2.0".format(tf_req),
"jinja2>=2.10.1",
"packaging>=20.0",
"progressbar2>=3.39.0",
Expand Down
10 changes: 3 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Automatically generated by nengo-bones, do not edit this file directly

language: python
python: 3.6
python: 3.7
notifications:
email:
on_success: change
Expand Down Expand Up @@ -55,7 +55,7 @@ jobs:
TF_VERSION="tensorflow==2.2.0"
NUMPY_VERSION="numpy==1.16.0"
SCRIPT="test-coverage"
python: 3.5
python: 3.6
-
env:
SCRIPT="test-coverage"
Expand Down Expand Up @@ -111,11 +111,7 @@ before_install:
# install/run nengo-bones
- pip install git+https://github.com/nengo/nengo-bones#egg=nengo-bones
- bones-generate --output-dir .ci ci-scripts
- if [[ "$TRAVIS_PYTHON_VERSION" < "3.6" ]]; then
echo "Skipping bones-check because Python $TRAVIS_PYTHON_VERSION < 3.6";
else
bones-check --verbose;
fi
- bones-check --verbose
# display environment info
- pip freeze

Expand Down
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ Release history

*Compatible with TensorFlow 2.2.0 - 2.4.0*

**Removed**

- Dropped support for Python 3.5 (which reached its end of life in September 2020).
(`#184`_)

.. _#184: https://github.com/nengo/nengo-dl/pull/184

3.4.0 (November 26, 2020)
-------------------------

Expand Down
6 changes: 3 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# Automatically generated by nengo-bones, do not edit this file directly

import os
import pathlib

import nengo_dl

Expand Down Expand Up @@ -100,11 +100,11 @@
templates_path = ["_templates"]
html_static_path = ["_static"]
html_theme = "nengo_sphinx_theme"
html_title = "NengoDL {0} docs".format(release)
html_title = f"NengoDL {release} docs"
htmlhelp_basename = "NengoDL"
html_last_updated_fmt = "" # Default output format (suppressed)
html_show_sphinx = False
html_favicon = os.path.join("_static", "favicon.ico")
html_favicon = str(pathlib.Path("_static", "favicon.ico"))
html_theme_options = {
"nengo_logo": "nengo-dl-full-light.svg",
"nengo_logo_color": "#ff6600",
Expand Down
30 changes: 30 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,33 @@ setting ``nengo_dl.Simulator(..., unroll_simulation=x)``. This will explicitly b
``x`` timesteps into the model (without using a loop). So if we use
``unroll_simulation=x`` and ``use_loop=False``, then the simulation will always run
for exactly ``x`` timesteps.

learning_phase
--------------

NengoDL (and Keras in general) can run models in two different modes, or "phases":
training and inference. Typically the mode is set automatically based on the function
used to execute the model; ``sim.fit`` will run in training mode, and all other
functions (e.g., ``sim.predict``, ``sim.run``, and ``sim.evaluate``) run in inference
mode.

The most important way that the learning phase affects a NengoDL model is that it
controls whether spiking neurons are simulated in spiking or non-spiking mode.
Normally during training spiking neurons will automatically swap their behaviour to
a non-spiking equivalent, and use the spiking behaviour during inference.

However, sometimes it can be useful to override this default behaviour. For example,
we might want to evaluate a spiking model in training mode, to get more insight into
how it is behaving during training. That is the role of the ``learning_phase``
config option. It can be specified during Network construction to make a network
that will *always* run in training/inference mode, regardless of what function is
being called. For example:

.. testcode::

with nengo.Network() as net:
nengo_dl.configure_settings(learning_phase=True)

# this ensemble will always use the "training" mode of LIF
# (equivalent to LIFRate)
ens = nengo.Ensemble(10, 1, neuron_type=nengo.LIF())
9 changes: 5 additions & 4 deletions docs/examples/keras-to-snn.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@
" # last timestep\n",
" predictions = np.argmax(data[nengo_output][:, -1], axis=-1)\n",
" accuracy = (predictions == test_labels[:n_test, 0, 0]).mean()\n",
" print(\"Test accuracy: %.2f%%\" % (100 * accuracy))\n",
" print(f\"Test accuracy: {100 * accuracy:.2f}%\")\n",
"\n",
" # plot the results\n",
" for ii in range(3):\n",
Expand All @@ -282,7 +282,8 @@
" plt.ylabel(\"Firing rates (Hz)\")\n",
" plt.xlabel(\"Timestep\")\n",
" plt.title(\n",
" \"Neural activities (conv0 mean=%dHz max=%dHz)\" % (rates.mean(), rates.max())\n",
" f\"Neural activities (conv0 mean={rates.mean():.1f} Hz, \"\n",
" f\"max={rates.max():.1f} Hz)\"\n",
" )\n",
" plt.plot(scaled_data)\n",
"\n",
Expand Down Expand Up @@ -387,7 +388,7 @@
"outputs": [],
"source": [
"for s in [0.001, 0.005, 0.01]:\n",
" print(\"Synapse=%.3f\" % s)\n",
" print(f\"Synapse={s:.3f}\")\n",
" run_network(\n",
" activation=nengo.SpikingRectifiedLinear(),\n",
" n_steps=60,\n",
Expand Down Expand Up @@ -445,7 +446,7 @@
"outputs": [],
"source": [
"for scale in [2, 5, 10]:\n",
" print(\"Scale=%d\" % scale)\n",
" print(f\"Scale={scale}\")\n",
" run_network(\n",
" activation=nengo.SpikingRectifiedLinear(),\n",
" scale_firing_rates=scale,\n",
Expand Down
10 changes: 5 additions & 5 deletions docs/examples/spa-memory.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"\n",
" # iterate through examples to be generated, fill arrays\n",
" for n in range(n_inputs):\n",
" name = \"SP_%d\" % n\n",
" name = f\"SP_{n}\"\n",
" vocab.add(name, vocab.create_pointer())\n",
"\n",
" # create inputs and target memory for first pair\n",
Expand Down Expand Up @@ -163,7 +163,7 @@
"def plot_memory_example(plot_sim, vocab, example_input=0):\n",
" plt.figure(figsize=(8, 8))\n",
"\n",
" name = \"SP_%d\" % example_input\n",
" name = f\"SP_{example_input}\"\n",
"\n",
" plt.subplot(3, 1, 1)\n",
" plt.plot(\n",
Expand Down Expand Up @@ -351,8 +351,8 @@
"\n",
" # iterate through examples to be generated, fill arrays\n",
" for n in range(n_items):\n",
" role_names = [\"ROLE_%d_%d\" % (n, i) for i in range(pairs_per_item)]\n",
" filler_names = [\"FILLER_%d_%d\" % (n, i) for i in range(pairs_per_item)]\n",
" role_names = [f\"ROLE_{n}_{i}\" for i in range(pairs_per_item)]\n",
" filler_names = [f\"FILLER_{n}_{i}\" for i in range(pairs_per_item)]\n",
"\n",
" # each role/filler pair is presented for presentation_time seconds\n",
" for i in range(pairs_per_item):\n",
Expand All @@ -361,7 +361,7 @@
" filler_names[i]\n",
" ).v\n",
" binding[n, i * int_steps : (i + 1) * int_steps] = vocab.parse(\n",
" \"%s*%s\" % (role_names[i], filler_names[i])\n",
" f\"{role_names[i]}*{filler_names[i]}\"\n",
" ).v\n",
"\n",
" # randomly select a cue\n",
Expand Down
10 changes: 5 additions & 5 deletions docs/examples/spa-retrieval.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@
"\n",
" # iterate through all of the examples to be generated\n",
" for n in range(n_items):\n",
" role_names = [\"ROLE_%d_%d\" % (n, i) for i in range(pairs_per_item)]\n",
" filler_names = [\"FILLER_%d_%d\" % (n, i) for i in range(pairs_per_item)]\n",
" role_names = [f\"ROLE_{n}_{i}\" for i in range(pairs_per_item)]\n",
" filler_names = [f\"FILLER_{n}_{i}\" for i in range(pairs_per_item)]\n",
"\n",
" # create key for the 'trace' of bound pairs (i.e. a\n",
" # structured semantic pointer)\n",
" trace_key = \"TRACE_\" + str(n)\n",
" trace_ptr = vocab.parse(\n",
" \"+\".join(\"%s * %s\" % (x, y) for x, y in zip(role_names, filler_names))\n",
" \"+\".join(f\"{x} * {y}\" for x, y in zip(role_names, filler_names))\n",
" )\n",
" trace_ptr.normalize()\n",
" vocab.add(trace_key, trace_ptr)\n",
Expand All @@ -96,8 +96,8 @@
"\n",
" # fill array elements correspond to this example\n",
" traces[n, 0, :] = vocab[trace_key].v\n",
" cues[n, 0, :] = vocab[\"ROLE_%d_%d\" % (n, cue_idx)].v\n",
" targets[n, 0, :] = vocab[\"FILLER_%d_%d\" % (n, cue_idx)].v\n",
" cues[n, 0, :] = vocab[f\"ROLE_{n}_{cue_idx}\"].v\n",
" targets[n, 0, :] = vocab[f\"FILLER_{n}_{cue_idx}\"].v\n",
"\n",
" return traces, cues, targets, vocab"
]
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ That's it!

Requirements
------------
NengoDL works with Python 3.5 or later. ``pip`` will do its best to install
NengoDL works with Python 3.6 or later. ``pip`` will do its best to install
all of NengoDL's requirements when it installs NengoDL. However, if anything
goes wrong during this process you can install the requirements manually and
then try to ``pip install nengo-dl`` again.
Expand Down
26 changes: 0 additions & 26 deletions nengo_dl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,6 @@
__license__ = "Free for non-commercial use; see LICENSE.rst"
from nengo_dl.version import version as __version__

# check python version
import sys

if sys.version_info < (3, 5):
raise ImportError(
"""
You are running Python version %s with NengoDL version %s. NengoDL requires
at least Python 3.5.

The fact that this version was installed on your system probably means that you
are using an older version of pip; you should consider upgrading with

$ pip install pip setuptools --upgrade

There are two options for getting NengoDL working:

- Upgrade to Python >= 3.5

- Install an older version of NengoDL:

$ pip install 'nengo-dl<2.0'
"""
% (sys.version, __version__)
)
del sys

# filter out "INFO" level log messages
import os

Expand Down
4 changes: 2 additions & 2 deletions nengo_dl/benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,8 +747,8 @@ def build(obj, benchmark, dimensions, neurons_per_d, neuron_type, kwarg):

# build benchmark and add to context for chaining
print(
"Building %s with %s"
% (nengo_dl.utils.function_name(benchmark, sanitize=False), kwargs)
f"Building {nengo_dl.utils.function_name(benchmark, sanitize=False)} "
f"with {kwargs}"
)

obj["net"] = benchmark(**kwargs)
Expand Down
4 changes: 2 additions & 2 deletions nengo_dl/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, plan):
for ops in self.plan:
if type(ops[0]) not in Builder.builders:
raise BuildError(
"No registered builder for operators of type %r" % type(ops[0])
f"No registered builder for operators of type {type(ops[0])!r}"
)
self.op_builds[ops] = Builder.builders[type(ops[0])](ops)

Expand Down Expand Up @@ -157,7 +157,7 @@ def register_builder(build_class):

if nengo_op in cls.builders:
warnings.warn(
"Operator '%s' already has a builder. Overwriting." % nengo_op
f"Operator '{nengo_op}' already has a builder. Overwriting."
)

cls.builders[nengo_op] = build_class
Expand Down
16 changes: 8 additions & 8 deletions nengo_dl/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self, log_dir, sim, objects):
self.sim = sim

with contextlib.suppress() if compat.eager_enabled() else context.eager_mode():
self.writer = tf.summary.create_file_writer(log_dir)
self.writer = tf.summary.create_file_writer(str(log_dir))

self.summaries = []
for obj in objects:
Expand All @@ -56,26 +56,26 @@ def __init__(self, log_dir, sim, objects):
):
if isinstance(obj, nengo.Ensemble):
param = "encoders"
name = "Ensemble_%s" % obj.label
name = f"Ensemble_{obj.label}"
elif isinstance(obj, nengo.ensemble.Neurons):
param = "bias"
name = "Ensemble.neurons_%s" % obj.ensemble.label
name = f"Ensemble.neurons_{obj.ensemble.label}"
elif isinstance(obj, nengo.Connection):
if not compat.conn_has_weights(obj):
raise ValidationError(
"Connection '%s' does not have any weights to log" % obj,
f"Connection '{obj}' does not have any weights to log",
"objects",
)
param = "weights"
name = "Connection_%s" % obj.label
name = f"Connection_{obj.label}"

self.summaries.append(
(utils.sanitize_name("%s_%s" % (name, param)), obj, param)
(utils.sanitize_name(f"{name}_{param}"), obj, param)
)
else:
raise ValidationError(
"Unknown summary object %s; should be an Ensemble, Neurons, or "
"Connection" % obj,
f"Unknown summary object {obj}; should be an Ensemble, Neurons, or "
"Connection",
"objects",
)

Expand Down
Loading