A few weeks ago (see Getting started with ML: Colab or self-hosted Jupyter?), I said I would eventually install JupyterLab locally on my Mac with M1.


The date is Feb 25, 2021. I found out the hard way that since scipy won't work for M1 yet (https://github.com/scipy/scipy/issues/13409), there is no point trying to do TensorFlow locally on a Mac with M1. There might be a way with compatibility mode, but I haven't tried it yet.

Installing pip

First I had to install pip. I followed https://pip.pypa.io/en/stable/installing/. However, running python get-pip.py returned this error:

ERROR: This script does not work on Python 2.7 The minimum supported Python version is 3.6. Please use https://bootstrap.pypa.io/2.7/get-pip.py instead.

Instead I had to run python3 get-pip.py:

% python3 get-pip.py
Defaulting to user installation because normal site-packages is not writeable
Collecting pip
  Downloading pip-21.0.1-py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 1.4 MB/s 
Installing collected packages: pip
  WARNING: The scripts pip, pip3 and pip3.8 are installed in '/Users/[username]/Library/Python/3.8/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-21.0.1
WARNING: You are using pip version 19.2.3; however, version 21.0.1 is available.
You should consider upgrading via the '/Applications/Xcode.app/Contents/Developer/usr/bin/python3 -m pip install --upgrade pip' command.

This is strange, why does it say that it installed pip 21, then tells me I am using pip 19?

Anyway, to finish I add Python's bin folder to the path with vim .zshrc. When I reopen the terminal and run pip, it works as expected.

Installing pipenv

Over at https://pipenv.pypa.io/en/latest/install/#pragmatic-installation-of-pipenv, I follow their install command:

% pip install --user pipenv

Then try it by running pipenv, and it works.

Installing packages

JupyterLab installs fine.

% pipenv install jupyterlab
Creating a virtualenv for this project...
Pipfile: /Users/[username]/git/jupyter/Pipfile
Using /usr/bin/python3 (3.8.2) to create virtualenv...
⠦ Creating virtual environment...created virtual environment CPython3.8.2.final.0-64 in 410ms
  creator CPython3macOsFramework(dest=/Users/[username]/.local/share/virtualenvs/jupyter-l45QZaht, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/[username]/Library/Application Support/virtualenv)
    added seed packages: pip==21.0.1, setuptools==52.0.0, wheel==0.36.2
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

✔ Successfully created virtual environment! 
Virtualenv location: /Users/[username]/.local/share/virtualenvs/jupyter-l45QZaht
Creating a Pipfile for this project...
Installing jupyterlab...
Adding jupyterlab to Pipfile's [packages]...
✔ Installation Succeeded 
Pipfile.lock not found, creating...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success! 
Updated Pipfile.lock (73f34e)!
Installing dependencies from Pipfile.lock (73f34e)...
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

But it failed for TensorFlow.

% pipenv install tensorflow
Installing tensorflow...
Adding tensorflow to Pipfile's [packages]...
✔ Installation Succeeded 
Pipfile.lock (73f34e) out of date, updating to (afb705)...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✘ Locking Failed! 
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/resolver.py", line 741, in _main
[ResolutionFailure]:       resolve_packages(pre, clear, verbose, system, write, requirements_dir, packages, dev)
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/resolver.py", line 702, in resolve_packages
[ResolutionFailure]:       results, resolver = resolve(
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/resolver.py", line 684, in resolve
[ResolutionFailure]:       return resolve_deps(
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/utils.py", line 1395, in resolve_deps
[ResolutionFailure]:       results, hashes, markers_lookup, resolver, skipped = actually_resolve_deps(
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/utils.py", line 1108, in actually_resolve_deps
[ResolutionFailure]:       resolver.resolve()
[ResolutionFailure]:   File "/Users/[username]/Library/Python/3.8/lib/python/site-packages/pipenv/utils.py", line 833, in resolve
[ResolutionFailure]:       raise ResolutionFailure(message=str(e))
[pipenv.exceptions.ResolutionFailure]: Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
  First try clearing your dependency cache with $ pipenv lock --clear, then try the original command again.
 Alternatively, you can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
  Hint: try $ pipenv lock --pre if it is a pre-release dependency.
ERROR: Could not find a version that matches tensorflow (from -r /var/folders/ym/2b7pw1yn0v71ybqwb07t4vw00000gn/T/pipenv_jovmhf7requirements/pipenv-f853nmkj-constraints.txt (line 2))
No versions found
Was https://pypi.org/simple reachable?

The URL is indeed reachable. I get the same error when I run the recommended pipenv lock --clear. When I run pipenv graph, however, I do see TensorFlow installed:

  - absl-py [required: ~=0.10, installed: 0.11.0]
    - six [required: Any, installed: 1.15.0]
  - astunparse [required: ~=1.6.3, installed: 1.6.3]
    - six [required: >=1.6.1,<2.0, installed: 1.15.0]
    - wheel [required: >=0.23.0,<1.0, installed: 0.36.2]
  - flatbuffers [required: ~=1.12.0, installed: 1.12]
  - gast [required: ==0.3.3, installed: 0.3.3]
  - google-pasta [required: ~=0.2, installed: 0.2.0]
    - six [required: Any, installed: 1.15.0]
  - grpcio [required: ~=1.32.0, installed: 1.32.0]
    - six [required: >=1.5.2, installed: 1.15.0]
  - h5py [required: ~=2.10.0, installed: 2.10.0]
    - numpy [required: >=1.7, installed: 1.19.5]
    - six [required: Any, installed: 1.15.0]
  - keras-preprocessing [required: ~=1.1.2, installed: 1.1.2]
    - numpy [required: >=1.9.1, installed: 1.19.5]
    - six [required: >=1.9.0, installed: 1.15.0]
  - numpy [required: ~=1.19.2, installed: 1.19.5]

Running JupyterLab

Following https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html#pipenv, I run:

pipenv shell
jupyter lab

Training a model

Looks like in Colab, keras is not automatically available as in Colab. On https://keras.io/, seeing from the screenshot, I should be importing it from tensorflow instead:

from tensorflow import keras

But every time I run this import, the Kernel crashes.

So it might be that TensorFlow did in fact not install correctly.

Using TensorFlow's M1 build

I am using a new Mac Mini with M1 processors. On this post, it seems that TensorFlow requires specific Python versions and hardware.

Could not find a version that satisfies the requirement tensorflow
I installed the latest version of Python (3.6.4 64-bit) and the latest version of PyCharm (2017.3.3 64-bit). Then I installed some modules in PyCharm (Numpy, Pandas, etc), but when I tried installing

So let's check the requirements on the official site. I remembered the announcement that TensorFlow supported M1 processors. Here's the blog post: https://blog.tensorflow.org/2020/11/accelerating-tensorflow-performance-on-mac.html.

It turns out the instructions to install this special build is at a separate repository, and is being brought into the main repository. So until then, we have to use the separate repository and instructions at https://github.com/apple/tensorflow_macos.

The installation guide is really nice. You can run their script, and it will create a venv environment with TensorFlow installed. After installing, I switch to the environment, install Jupyter Lab, run it and try importing tf again:

. "/Users/[username]/tensorflow_macos_venv/bin/activate"
pip install jupyterlab
jupyter lab

But I still get the same crash.

It also didn't output a precise error message, and when running, Jupyter doesn't tell whether there is a log file.

Googling the error some more, some recent posts recommend to upgrade Numpy:

The second link also recommends to try in a separate python script first, as does https://github.com/tensorflow/tensorflow/issues/9829#issuecomment-300783730, but for other reasons.

First I upgraded numpy just to see if it would work with dumb luck. pip list reveals I had version 1.18.5. Running pip install -U numpy upgraded it to version 1.20.1.

I ran JupyterLab and it failed again to load tf again.

Finally I tried with the python interpreter:

% python
Python 3.8.2 (default, Dec 21 2020, 15:06:04) 
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from tensorflow import keras
zsh: illegal hardware instruction  python

Now we're getting somewhere! Googling the error, I end up on https://stackoverflow.com/questions/65383338/zsh-illegal-hardware-instruction-python-when-installing-tensorflow-on-macbook. They say you should set up the environment to use the arm64 build of Python. Another person says you should disable Rosetta to run in the Terminal, which is roughly the same thing.

Trying to run the interpreter with arch, I get:

% arch -arm64 python
Python 3.8.2 (default, Dec 21 2020, 15:06:03) 
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from tensorflow import keras
Traceback (most recent call last):
  File "/Users/[username]/tensorflow_macos_venv/lib/python3.8/site-packages/tensorflow/python/pywrap_tensorflow.py", line 64, in <module>
    from tensorflow.python._pywrap_tensorflow_internal import *
ImportError: dlopen(/Users/[username]/tensorflow_macos_venv/lib/python3.8/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so, 6): no suitable image found.  Did find:
	/Users/[username]/tensorflow_macos_venv/lib/python3.8/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so: mach-o, but wrong architecture
	/Users/[username]/tensorflow_macos_venv/lib/python3.8/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so: mach-o, but wrong architecture

I don't know what this means. Could it be that I should have run the install script without Rosetta enabled in the first place? The original install command was:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/apple/tensorflow_macos/master/scripts/download_and_install.sh)"

So this time I tried:

arch -arm64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/apple/tensorflow_macos/master/scripts/download_and_install.sh)"

It ran fine when activating with . "/Users/[username]/tensorflow_macos_venv/bin/activate", but when testing in the interpreter, I got the same error as above.

I tried using arch to run the activate script, but I get strange arch-related errors about commands not being in the PATH.

Since I really don't know what I am doing with this arch command, I decided to disable running Terminal with Rosetta and try again. Still no luck:

% python
Python 3.8.2 (default, Dec 21 2020, 15:06:04) 
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow
zsh: illegal hardware instruction  python

Let's see what the TF for M1 repo says:

Let's see what my platform is:

% uname -m

Weird. I thought I had disabled Rosetta?... I close all my windows and try again.

% uname
% uname -m
% file $(which python)
/usr/bin/python: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/python (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/bin/python (for architecture arm64e):	Mach-O 64-bit executable arm64e

Alright, let's download the internet and reinstall for the nth time:

And it worked!!

~ % python
Python 3.8.2 (default, Dec 21 2020, 15:06:03) 
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow

Phew, the key information was using uname -m to make sure you're running Terminal in arm64 mode. I wish this information was shown prominently in the installation notes. I might contribute a PR later.

Back to JupyterLab

I am now able to import tensorflow.keras, set up my model and image generators. When trying to train the model, I get this error:

~/tensorflow_macos_venv/lib/python3.8/site-packages/keras_preprocessing/image/utils.py in load_img(path, grayscale, color_mode, target_size, interpolation)
    109         color_mode = 'grayscale'
    110     if pil_image is None:
--> 111         raise ImportError('Could not import PIL.Image. '
    112                           'The use of `load_img` requires PIL.')
    113     with open(path, 'rb') as f:

ImportError: Could not import PIL.Image. The use of `load_img` requires PIL.

Apparently I should install a package called pillow: https://stackoverflow.com/a/52230898. But running pip install Pillow throws an error about missing jpeg dependency:

__main__.RequiredDependencyException: jpeg

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/private/var/folders/ym/2b7pw1yn0v71ybqwb07t4vw00000gn/T/pip-install-wnvucnmh/pillow_17e014a21d31478bb1bd2fbf32cd1d2a/setup.py", line 922, in <module>
    raise RequiredDependencyException(msg)

The headers or library files could not be found for jpeg,
a required dependency when compiling Pillow from source.

Please see the install instructions at:

On Mac OS, you can install it with Homebrew:

But now that Rosetta is disabled, Homebrew won't work:

% brew install jpeg
Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)!
Please create a new installation in /opt/homebrew using one of the
"Alternative Installs" from:
You can migrate your previously installed formula list with:
  brew bundle dump

The fix is to run the command using arch, according to https://stackoverflow.com/a/64997047:

% arch -x86_64 brew install jpeg
==> Downloading https://homebrew.bintray.com/bottles/jpeg-9d.big_sur.bottle.tar.gz
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/c565929a4901365a3408b57275802f943625c1e29e1b48a186edd2e97d8c0bdb?response-content-disposition=attachment%3Bfilename%3D%22jpeg-9d.big_sur.bottle.tar.gz%22&Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZ
######################################################################## 100.0%
==> Pouring jpeg-9d.big_sur.bottle.tar.gz
/usr/local/Homebrew/Library/Homebrew/download_strategy.rb:94: warning: conflicting chdir during another chdir block
🍺  /usr/local/Cellar/jpeg/9d: 21 files, 953.8KB
==> `brew cleanup` has not been run in 30 days, running now...
Removing: /Users/[username]/Library/Caches/Homebrew/Cask/keycastr--0.9.9.zip... (2.6MB)
Pruned 1 symbolic links and 5 directories from /usr/local

Back to installing Pillow:

Collecting pillow
  Using cached Pillow-8.1.0.tar.gz (44.9 MB)
Building wheels for collected packages: pillow
  Building wheel for pillow (setup.py) ... done
  Created wheel for pillow: filename=Pillow-8.1.0-cp38-cp38-macosx_10_14_arm64.whl size=707578 sha256=4c08daab32255655bb04495b979369cdccc6b8eb38095494c019c3b86bf42f85
  Stored in directory: /Users/[username]/Library/Caches/pip/wheels/4e/db/04/9dcbaf9865568850d9bbdeb9b6b697e70f804d18e7e8aac050
Successfully built pillow
Installing collected packages: pillow
Successfully installed pillow-8.1.0

For Pillow to be available in the JupyterLab environment, I had to restart the kernel.

Running model.fit again, I get a new error:

~/tensorflow_macos_venv/lib/python3.8/site-packages/PIL/ImageFile.py in raise_oserror(error)
     65     if not message:
     66         message = f"decoder error {error}"
---> 67     raise OSError(message + " when reading image file")

OSError: broken data stream when reading image file

To make sure my image files were not corrupted, I unzipped my dataset file again. It failed again. So some of my images are truncated. According to this issue on the Pillow repository, I can make Pillow ignore truncation errors with a flag:

from PIL import ImageFile

Let's run model.fit again. Another error pops up:

~/tensorflow_macos_venv/lib/python3.8/site-packages/keras_preprocessing/image/affine_transformations.py in apply_affine_transform(x, theta, tx, ty, shear, zx, zy, row_axis, col_axis, channel_axis, fill_mode, cval, order)
    279     """
    280     if scipy is None:
--> 281         raise ImportError('Image transformations require SciPy. '
    282                           'Install SciPy.')
    283     transform_matrix = None

ImportError: Image transformations require SciPy. Install SciPy.

But the Tensorflow for M1 at https://github.com/apple/tensorflow_macos#notes states that NumPy is not available for M1:

SciPy and dependent packages and Server/Client TensorBoard packages

Let's try anyway:

% pip install scipy
Collecting scipy
  Using cached scipy-1.6.1.tar.gz (27.3 MB)
  Installing build dependencies ... error
  ERROR: Command errored out with exit status 1:
   command: /Users/[username]/tensorflow_macos_venv/bin/python3 /Users/anhtuan/tensorflow_macos_venv/lib/python3.8/site-packages/pip install --ignore-installed --no-user --prefix /private/var/folders/ym/2b7pw1yn0v71ybqwb07t4vw00000gn/T/pip-build-env-j_l1er80/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- wheel 'setuptools<=51.0.0' 'Cython>=0.29.18' 'pybind11>=2.4.3' 'numpy==1.19.2; python_version=='"'"'3.6'"'"' and platform_machine=='"'"'aarch64'"'"'' 'numpy==1.19.2; python_version=='"'"'3.7'"'"' and platform_machine=='"'"'aarch64'"'"'' 'numpy==1.16.5; python_version=='"'"'3.6'"'"' and platform_machine!='"'"'aarch64'"'"' and platform_python_implementation != '"'"'PyPy'"'"'' 'numpy==1.16.5; python_version=='"'"'3.7'"'"' and platform_machine!='"'"'aarch64'"'"' and platform_python_implementation != '"'"'PyPy'"'"'' 'numpy==1.17.3; python_version=='"'"'3.8'"'"' and platform_machine!='"'"'aarch64'"'"' and platform_python_implementation != '"'"'PyPy'"'"'' 'numpy==1.19.3; python_version=='"'"'3.9'"'"' and platform_python_implementation != '"'"'PyPy'"'"'' 'numpy==1.19.0; python_version=='"'"'3.6'"'"' and platform_python_implementation=='"'"'PyPy'"'"'' 'numpy==1.20.0; python_version=='"'"'3.7'"'"' and platform_python_implementation=='"'"'PyPy'"'"'' 'numpy; python_version>='"'"'3.10'"'"'' 'numpy; python_version>='"'"'3.8'"'"' and platform_python_implementation=='"'"'PyPy'"'"''
       cwd: None
  Complete output (4841 lines):
  Ignoring numpy: markers 'python_version == "3.6" and platform_machine == "aarch64"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.7" and platform_machine == "aarch64"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.6" and platform_machine != "aarch64" and platform_python_implementation != "PyPy"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.7" and platform_machine != "aarch64" and platform_python_implementation != "PyPy"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.9" and platform_python_implementation != "PyPy"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.6" and platform_python_implementation == "PyPy"' don't match your environment
  Ignoring numpy: markers 'python_version == "3.7" and platform_python_implementation == "PyPy"' don't match your environment
  Ignoring numpy: markers 'python_version >= "3.10"' don't match your environment
  Ignoring numpy: markers 'python_version >= "3.8" and platform_python_implementation == "PyPy"' don't match your environment

I'll skip the rest of the 4000 lines of logs. Basically it doesn't work. After some more digging, I found the open issue on scipy: https://github.com/scipy/scipy/issues/13409.

Numpy is fine though: https://github.com/apple/tensorflow_macos/blob/301e41cf699068ae1b55292472c2eb0b15d7a0f3/scripts/install_venv.sh#L51

So until scipy is properly fixed to run on M1, I am stuck to using Colab. It only took me ten hours to find out!


Some people report having better luck with Conda, including installing scipy:

But to try it properly, I'd have to learn conda. I'll try later.