Neulich in dem Artikel Try Deep Learning mit FPGA, PYNQ und Ich schrieb über BNN-PYNQ. Im vorherigen Artikel habe ich eine relativ kostengünstige FPGA-Karte namens PYNQ-Z1-Karte vorgestellt und sogar eine vorbereitete Demo (Cifar10
) ausgeführt. Daher werden wir dieses Mal die im Voraus vorbereitete Demo entwickeln und die Gurken auswählen.
Wie ich im vorherigen Artikel geschrieben habe, besteht Deep Learning hauptsächlich aus Lernen und Denken. In BNN-PYNQ ist nur Inferenz implementiert (das Lernen muss auf der CPU / GPU erfolgen). Daher bedeutet das Anpassen von BNN-PYNQ, dass die Netzwerkstruktur und die Inferenzparameter geändert werden, wenn sie gelernt werden.
Am Beispiel des vorherigen "Cifar10" in BNN-PYNQ wird die Deep-Learning-Verarbeitung auf FPGA von der Anwendung auf Jupyter gemäß dem folgenden Ablauf ausgeführt. Beim letzten Mal gab es ein Geschwindigkeitsvergleichsergebnis von CPU / FPGA, das jedoch durch Umschalten der gemeinsam genutzten gemeinsam genutzten Bibliothek (python_hw / sw) in # 4 unten realisiert wurde.
# | Datei | Überblick | Benutzerdefinierte Methode |
---|---|---|---|
1 | Cifar10.ipynb | Es ist eine Anwendung. Das letzte Mal war es eine Jupyter-Datei zum Ausführen der Demo. | |
2 | bnn.py | BNN-Eine Bibliothek zum Ausführen von PYNQ in Python. | |
3 | X-X-thres.bin X-X-weights.bin classes.txt |
Dies ist eine Parameterdatei. Zentralprozessor/BNN das Ergebnis des Lernens mit GPU-Es wird zum Erfassen mit PYNQ verwendet. | BinaryNets for Pynq - Training Networks |
4 | python_sw-cnv-pynq.so | Eine gemeinsam genutzte Bibliothek zum Ausführen von Deep Learning auf der CPU. | make-sw.sh |
python_hw-cnv-pynq.so | Eine gemeinsam genutzte Bibliothek zum Ausführen von Deep Learning auf FPGAs. | make-sw.sh |
|
5 | cnv-pynq-pynq.bit | Eine Bitstream-Datei zur Durchführung der Verarbeitung auf dem FPGA. Wenn Sie die Überlagerung wechseln, wird diese Datei gewechselt und gelesen. | make-hw.sh |
Dieses Mal werde ich BNN-PYNQ anpassen, aber da es eine Hürde gibt, die Netzwerkstruktur plötzlich wieder aufzubauen, möchte ich die Leseparameter ändern und dabei die Netzwerkstruktur wie "Cifar10" beibehalten.
Da es für eine Weile ein heißes Thema wurde, wissen es viele von Ihnen vielleicht, aber es ist ein Problem, die Noten basierend auf dem Gurkenbild in 9 Typen zu klassifizieren. Sortieren von "Gurke" durch tiefes Lernen mit TensorFlow
Die zum Lernen erforderlichen Daten werden auf GitHub veröffentlicht, daher werden wir sie verwenden. GitHub veröffentlicht zwei Typen, "ProtoType-1, 2", aber dieses Mal verwenden wir "ProtoType-1", dessen Dataset-Format nahe "Cifar10" liegt. GitHub - workpiles/CUCUMBER-9
- 2L〜2S
Gutes Produkt. Gute Farbe, relativ gerade und nicht vorgespannt. Es ist je nach Größe in 5 Stufen von 2L bis 2S sortiert.- BL〜BS
B Produkt. Diejenigen mit schlechter Farbe, leicht gebogener oder ungleichmäßiger Dicke. Es ist je nach Größe in 3 Stufen von L bis S sortiert.- C
C-Produkt. Schlechte Form.
In einigen Blogs scheint die korrekte Antwortrate ohne Einfallsreichtum bei etwa 80% zu liegen. Dieses Mal bin ich sehr dankbar, weil ich die Netzwerkstruktur nicht ändere.
Erstellen Sie Parameterdaten, die vom FPGA geladen werden sollen. Befolgen Sie, wie in der obigen Tabelle erwähnt, das auf GitHub veröffentlichte Verfahren. BinaryNets for Pynq - Training Networks
Beachten Sie, dass diese Parameterdatei auf der CPU / GPU erstellt werden muss. Dieses Mal habe ich eine GPU-Instanz (NC6 Ubuntu 16.04
) auf Azure eingerichtet.
Installieren Sie Nvidia Drivers, CUDA und cuDNN.
Installieren von Nvidia-Treibern
$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
$ sudo apt-get update
CUDA-Installation
$ sudo apt-get install cuda -y
CuDNN installieren
$ sudo dpkg -i libcudnn5_5.1.10-1+cuda8.0_amd64.deb libcudnn5-dev_5.1.10-1+cuda8.0_amd64.deb
PFAD-Einstellung
$ sudo sh -c "echo 'CUDA_HOME=/usr/local/cuda' >> /etc/profile.d/cuda.sh"
$ sudo sh -c "echo 'export LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}:\${CUDA_HOME}/lib64' >> /etc/profile.d/cuda.sh"
$ sudo sh -c "echo 'export LIBRARY_PATH=\${LIBRARY_PATH}:\${CUDA_HOME}/lib64' >> /etc/profile.d/cuda.sh"
$ sudo sh -c "echo 'export C_INCLUDE_PATH=\${C_INCLUDE_PATH}:\${CUDA_HOME}/include' >> /etc/profile.d/cuda.sh"
$ sudo sh -c "echo 'export CXX_INCLUDE_PATH=\${CXX_INCLUDE_PATH}:\${CUDA_HOME}/include' >> /etc/profile.d/cuda.sh"
$ sudo sh -c "echo 'export PATH=\${PATH}:\${CUDA_HOME}/bin' >> /etc/profile.d/cuda.sh"
Starten Sie die Instanz neu
$ sudo reboot
Bestätigung der Installation
$ nvidia-smi
Thu Mar 30 07:42:52 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.39 Driver Version: 375.39 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla K80 Off | 8CFC:00:00.0 Off | 0 |
| N/A 38C P0 75W / 149W | 0MiB / 11439MiB | 97% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
Installieren Sie die Python-Bibliotheken (Theano, Lasagne, Numpy, Pylearn2
). Ich habe auch pyenv zuerst installiert, um Python 2.7 zu verwenden.
Installieren Sie pyenv & Python 2.7
$ sudo apt-get install git gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ vi .bashrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
$ source .bashrc
$ env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 2.7.13
$ pyenv global 2.7.13
Installation von Python-Bibliotheken (Theano, Lasagne, Numpy, Pylearn 2
)
$ pip install --user git+https://github.com/Theano/[email protected]
$ pip install --user https://github.com/Lasagne/Lasagne/archive/master.zip
$ echo "[global]" >> ~/.theanorc
$ echo "floatX = float32" >> ~/.theanorc
$ echo "device = gpu" >> ~/.theanorc
$ echo "openmp = True" >> ~/.theanorc
$ echo "openmp_elemwise_minsize = 200000" >> ~/.theanorc
$ echo "" >> ~/.theanorc
$ echo "[nvcc]" >> ~/.theanorc
$ echo "fastmath = True" >> ~/.theanorc
$ echo "" >> ~/.theanorc
$ echo "[blas]" >> ~/.theanorc
$ echo "ldflags = -lopenblas" >> ~/.theanorc
$ git clone https://github.com/lisa-lab/pylearn2
$ cd pylearn2/
$ python setup.py develop --user
Bereiten Sie den Datensatz für das Training vor. Dieses Mal werde ich die Bilddaten der Gurke von GitHub verwenden.
$ git clone https://github.com/workpiles/CUCUMBER-9.git
$ cd CUCUMBER-9/prototype_1/
$ tar -zxvf cucumber-9-python.tar.gz
Wir werden einige Änderungen am Xilinx-Programm vornehmen, um den durch das Training geladenen Datensatz zu ändern. Die wichtigsten Änderungen sind die folgenden zwei Punkte.
Holen Sie sich das Programm von BNN-PYNQ
$ git clone https://github.com/Xilinx/BNN-PYNQ.git
$ cd BNN-PYNQ/bnn/src/training/
Ändern Sie das Programm, das beim Lernen ausgeführt werden soll Erstellen Sie cucumber9.py, das die Bilddaten der Gurke liest und das Training ausführt.
$ cp cifar10.py cucumber9.py
$ vi cucumber9.py
Änderungen am Binärdatenkonverter BNN-PYNQ verarbeitet binärisierte Daten. Daher ist es notwendig, reale Parameterdaten in Binärdaten umzuwandeln. Erstellen Sie cucumber9-gen-binary-weights.py, das die Bilddaten der Gurke lernt und die resultierenden Parameterdaten in eine Binärdatei konvertiert.
$ cp cifar10-gen-binary-weights.py cucumber9-gen-binary-weights.py
$ vi cucumber9-gen-binary-weights.py
Nachdem Sie die Umgebung, die Daten und das Programm zum Lernen bereit haben, führen Sie das Programm aus.
$ pwd /home/ubuntu/BNN-PYNQ/bnn/src/training
$ python cucumber9.py
WARNING (theano.sandbox.cuda): The cuda backend is deprecated and will be removed in the next release. Please switch to the gpuarray backend. You can get more information about how to switch at this URL:
https://github.com/Theano/Theano/wiki/Converting-to-the-new-gpu-back-end%28gpuarray%29
Using gpu device 0: Tesla K80 (CNMeM is disabled, cuDNN 5110)
/home/ubuntu/.local/lib/python2.7/site-packages/theano/tensor/basic.py:2144: UserWarning: theano.tensor.round() changed its default from `half_away_from_zero` to `half_to_even` to have the same default as NumPy. Use the Theano flag `warn.round=False` to disable this warning.
"theano.tensor.round() changed its default from"
batch_size = 50
alpha = 0.1
epsilon = 0.0001
W_LR_scale = Glorot
num_epochs = 500
LR_start = 0.001
LR_fin = 3e-07
LR_decay = 0.983907435305
save_path = cucumber9_parameters.npz
train_set_size = 2475
shuffle_parts = 1
Loading CUCUMBER9 dataset...
Building the CNN...
W_LR_scale = 20.0499
H = 1
W_LR_scale = 27.7128
H = 1
W_LR_scale = 33.9411
H = 1
W_LR_scale = 39.1918
H = 1
W_LR_scale = 48.0
H = 1
W_LR_scale = 55.4256
H = 1
W_LR_scale = 22.6274
H = 1
W_LR_scale = 26.1279
H = 1
W_LR_scale = 18.6369
H = 1
Training...
Epoch 1 of 500 took 6.08435511589s
LR: 0.001
training loss: 1.48512187053
validation loss: 2.05507221487
validation error rate: 61.1111117734%
best epoch: 1
best validation error rate: 61.1111117734%
test loss: 2.05507221487
test error rate: 61.1111117734%
…
Epoch 500 of 500 took 5.53324913979s
LR: 3.04906731299e-07
training loss: 0.0024273797482
validation loss: 0.132337698506
validation error rate: 14.2222222355%
best epoch: 205
best validation error rate: 11.9999999387%
test loss: 0.124302371922
test error rate: 11.9999999387%
Nach einer Weile ist das Lernen abgeschlossen und die Parameterdatei ist abgeschlossen.
$ ls
cucumber9_parameters.npz
Konvertiert reale Parameterdaten in Binärdaten.
$ python cucumber9-gen-binary-weights.py
cucumber9_parameters.npz
Die binären Parameterdaten sind abgeschlossen. Lassen Sie PYNQ diese Datei lesen.
$ ls binparam-cnv-pynq/
0-0-thres.bin 0-3-weights.bin 1-12-thres.bin 1-20-weights.bin 1-2-thres.bin 1-9-weights.bin 2-3-thres.bin 3-11-weights.bin 3-6-thres.bin 6-0-weights.bin
0-0-weights.bin 0-4-thres.bin 1-12-weights.bin 1-21-thres.bin 1-2-weights.bin 2-0-thres.bin 2-3-weights.bin 3-12-thres.bin 3-6-weights.bin 7-0-thres.bin
0-10-thres.bin 0-4-weights.bin 1-13-thres.bin 1-21-weights.bin 1-30-thres.bin 2-0-weights.bin 2-4-thres.bin 3-12-weights.bin 3-7-thres.bin 7-0-weights.bin
0-10-weights.bin 0-5-thres.bin 1-13-weights.bin 1-22-thres.bin 1-30-weights.bin 2-10-thres.bin 2-4-weights.bin 3-13-thres.bin 3-7-weights.bin 8-0-thres.bin
0-11-thres.bin 0-5-weights.bin 1-14-thres.bin 1-22-weights.bin 1-31-thres.bin 2-10-weights.bin 2-5-thres.bin 3-13-weights.bin 3-8-thres.bin 8-0-weights.bin
0-11-weights.bin 0-6-thres.bin 1-14-weights.bin 1-23-thres.bin 1-31-weights.bin 2-11-thres.bin 2-5-weights.bin 3-14-thres.bin 3-8-weights.bin 8-1-thres.bin
0-12-thres.bin 0-6-weights.bin 1-15-thres.bin 1-23-weights.bin 1-3-thres.bin 2-11-weights.bin 2-6-thres.bin 3-14-weights.bin 3-9-thres.bin 8-1-weights.bin
0-12-weights.bin 0-7-thres.bin 1-15-weights.bin 1-24-thres.bin 1-3-weights.bin 2-12-thres.bin 2-6-weights.bin 3-15-thres.bin 3-9-weights.bin 8-2-thres.bin
0-13-thres.bin 0-7-weights.bin 1-16-thres.bin 1-24-weights.bin 1-4-thres.bin 2-12-weights.bin 2-7-thres.bin 3-15-weights.bin 4-0-thres.bin 8-2-weights.bin
0-13-weights.bin 0-8-thres.bin 1-16-weights.bin 1-25-thres.bin 1-4-weights.bin 2-13-thres.bin 2-7-weights.bin 3-1-thres.bin 4-0-weights.bin 8-3-thres.bin
0-14-thres.bin 0-8-weights.bin 1-17-thres.bin 1-25-weights.bin 1-5-thres.bin 2-13-weights.bin 2-8-thres.bin 3-1-weights.bin 4-1-thres.bin 8-3-weights.bin
0-14-weights.bin 0-9-thres.bin 1-17-weights.bin 1-26-thres.bin 1-5-weights.bin 2-14-thres.bin 2-8-weights.bin 3-2-thres.bin 4-1-weights.bin classes.txt
0-15-thres.bin 0-9-weights.bin 1-18-thres.bin 1-26-weights.bin 1-6-thres.bin 2-14-weights.bin 2-9-thres.bin 3-2-weights.bin 4-2-thres.bin
0-15-weights.bin 1-0-thres.bin 1-18-weights.bin 1-27-thres.bin 1-6-weights.bin 2-15-thres.bin 2-9-weights.bin 3-3-thres.bin 4-2-weights.bin
0-1-thres.bin 1-0-weights.bin 1-19-thres.bin 1-27-weights.bin 1-7-thres.bin 2-15-weights.bin 3-0-thres.bin 3-3-weights.bin 4-3-thres.bin
0-1-weights.bin 1-10-thres.bin 1-19-weights.bin 1-28-thres.bin 1-7-weights.bin 2-1-thres.bin 3-0-weights.bin 3-4-thres.bin 4-3-weights.bin
0-2-thres.bin 1-10-weights.bin 1-1-thres.bin 1-28-weights.bin 1-8-thres.bin 2-1-weights.bin 3-10-thres.bin 3-4-weights.bin 5-0-thres.bin
0-2-weights.bin 1-11-thres.bin 1-1-weights.bin 1-29-thres.bin 1-8-weights.bin 2-2-thres.bin 3-10-weights.bin 3-5-thres.bin 5-0-weights.bin
0-3-thres.bin 1-11-weights.bin 1-20-thres.bin 1-29-weights.bin 1-9-thres.bin 2-2-weights.bin 3-11-thres.bin 3-5-weights.bin 6-0-thres.bin
Übertragen Sie die zuvor erstellten Parameterdaten an PYNQ.
$ sudo mkdir /opt/python3.6/lib/python3.6/site-packages/bnn/params/cucumber9
$ sudo ls /opt/python3.6/lib/python3.6/site-packages/bnn/params/cucumber9/
0-0-thres.bin 0-3-weights.bin 1-12-thres.bin 1-20-weights.bin 1-2-thres.bin 1-9-weights.bin 2-3-thres.bin 3-11-weights.bin 3-6-thres.bin 6-0-weights.bin
0-0-weights.bin 0-4-thres.bin 1-12-weights.bin 1-21-thres.bin 1-2-weights.bin 2-0-thres.bin 2-3-weights.bin 3-12-thres.bin 3-6-weights.bin 7-0-thres.bin
0-10-thres.bin 0-4-weights.bin 1-13-thres.bin 1-21-weights.bin 1-30-thres.bin 2-0-weights.bin 2-4-thres.bin 3-12-weights.bin 3-7-thres.bin 7-0-weights.bin
0-10-weights.bin 0-5-thres.bin 1-13-weights.bin 1-22-thres.bin 1-30-weights.bin 2-10-thres.bin 2-4-weights.bin 3-13-thres.bin 3-7-weights.bin 8-0-thres.bin
0-11-thres.bin 0-5-weights.bin 1-14-thres.bin 1-22-weights.bin 1-31-thres.bin 2-10-weights.bin 2-5-thres.bin 3-13-weights.bin 3-8-thres.bin 8-0-weights.bin
0-11-weights.bin 0-6-thres.bin 1-14-weights.bin 1-23-thres.bin 1-31-weights.bin 2-11-thres.bin 2-5-weights.bin 3-14-thres.bin 3-8-weights.bin 8-1-thres.bin
0-12-thres.bin 0-6-weights.bin 1-15-thres.bin 1-23-weights.bin 1-3-thres.bin 2-11-weights.bin 2-6-thres.bin 3-14-weights.bin 3-9-thres.bin 8-1-weights.bin
0-12-weights.bin 0-7-thres.bin 1-15-weights.bin 1-24-thres.bin 1-3-weights.bin 2-12-thres.bin 2-6-weights.bin 3-15-thres.bin 3-9-weights.bin 8-2-thres.bin
0-13-thres.bin 0-7-weights.bin 1-16-thres.bin 1-24-weights.bin 1-4-thres.bin 2-12-weights.bin 2-7-thres.bin 3-15-weights.bin 4-0-thres.bin 8-2-weights.bin
0-13-weights.bin 0-8-thres.bin 1-16-weights.bin 1-25-thres.bin 1-4-weights.bin 2-13-thres.bin 2-7-weights.bin 3-1-thres.bin 4-0-weights.bin 8-3-thres.bin
0-14-thres.bin 0-8-weights.bin 1-17-thres.bin 1-25-weights.bin 1-5-thres.bin 2-13-weights.bin 2-8-thres.bin 3-1-weights.bin 4-1-thres.bin 8-3-weights.bin
0-14-weights.bin 0-9-thres.bin 1-17-weights.bin 1-26-thres.bin 1-5-weights.bin 2-14-thres.bin 2-8-weights.bin 3-2-thres.bin 4-1-weights.bin classes.txt
0-15-thres.bin 0-9-weights.bin 1-18-thres.bin 1-26-weights.bin 1-6-thres.bin 2-14-weights.bin 2-9-thres.bin 3-2-weights.bin 4-2-thres.bin
0-15-weights.bin 1-0-thres.bin 1-18-weights.bin 1-27-thres.bin 1-6-weights.bin 2-15-thres.bin 2-9-weights.bin 3-3-thres.bin 4-2-weights.bin
0-1-thres.bin 1-0-weights.bin 1-19-thres.bin 1-27-weights.bin 1-7-thres.bin 2-15-weights.bin 3-0-thres.bin 3-3-weights.bin 4-3-thres.bin
0-1-weights.bin 1-10-thres.bin 1-19-weights.bin 1-28-thres.bin 1-7-weights.bin 2-1-thres.bin 3-0-weights.bin 3-4-thres.bin 4-3-weights.bin
0-2-thres.bin 1-10-weights.bin 1-1-thres.bin 1-28-weights.bin 1-8-thres.bin 2-1-weights.bin 3-10-thres.bin 3-4-weights.bin 5-0-thres.bin
0-2-weights.bin 1-11-thres.bin 1-1-weights.bin 1-29-thres.bin 1-8-weights.bin 2-2-thres.bin 3-10-weights.bin 3-5-thres.bin 5-0-weights.bin
0-3-thres.bin 1-11-weights.bin 1-20-thres.bin 1-29-weights.bin 1-9-thres.bin 2-2-weights.bin 3-11-thres.bin 3-5-weights.bin 6-0-thres.bin
Laden Sie die Testdaten herunter, die für den Rückschluss auf PYNQ verwendet werden.
$ git clone https://github.com/workpiles/CUCUMBER-9.git
$ cd CUCUMBER-9/prototype_1/
$ tar -zxvf cucumber-9-python.tar.gz
Lassen Sie es uns von Jupyter aus wie in der vorherigen Demo ausführen. Geben Sie bei der Ausführung von CUCUMBER9 an, dass "cucumber9" wie unten gezeigt als Parameter gelesen werden soll.
classifier = bnn.CnvClassifier('cucumber9')
Das Ausführungsergebnis ist in der folgenden Abbildung dargestellt.
Sie können es richtig klassifizieren! Die Ausführungszeit ist wie folgt. Obwohl die CPU von PYNQ schlecht ist, ist das Ergebnis von FPGA etwa 360-mal schneller.
FPGA
Inference took 2240.00 microseconds
Classification rate: 446.43 images per second
CPU
Inference took 816809.00 microseconds
Classification rate: 1.22 images per second
Beim Schreiben des Programms habe ich auf den folgenden Blog verwiesen.
Diesmal wurde PYNQ von einem mobilen Akku gespeist. Ich war überrascht, wie viel Strom gespart wurde.
Recommended Posts