HDF5の古いバージョンでKerasのモデルの保存ができない

 
### tl;dr

- hdf5のバージョンが古いとKerasのsave_weightsが動かない
- yumでhdf5-develを入れるのはやめて、ソースコードからコンパイルしよう

### 概要

Kerasではモデルを保存/ロードする際に[HDF5](https://www.hdfgroup.org/HDF5/)を利用します。このHDF5のバージョンが古いとHDF5のエラーで落ちることがあるので、そのエラーと対策を書き残しておきます。
 
### エラー

 
 ```
$ python test.py 
Using Theano backend.
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    model.save_weights('temp_keras.model', overwrite=True)
  File "/usr/local/lib/python2.7/site-packages/keras/engine/topology.py", line 2282, in save_weights
    g.attrs['weight_names'] = weight_names
  File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper (/tmp/pip-build-7ZnOvG/h5py/h5py/_objects.c:2682)
  File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper (/tmp/pip-build-7ZnOvG/h5py/h5py/_objects.c:2640)
  File "/usr/local/lib64/python2.7/site-packages/h5py/_hl/attrs.py", line 93, in __setitem__
    self.create(name, data=value, dtype=base.guess_dtype(value))
  File "/usr/local/lib64/python2.7/site-packages/h5py/_hl/attrs.py", line 175, in create
    space = h5s.create_simple(shape)
  File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper (/tmp/pip-build-7ZnOvG/h5py/h5py/_objects.c:2682)
  File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper (/tmp/pip-build-7ZnOvG/h5py/h5py/_objects.c:2640)
  File "h5py/h5s.pyx", line 101, in h5py.h5s.create_simple (/tmp/pip-build-7ZnOvG/h5py/h5py/h5s.c:1533)
ValueError: Zero sized dimension for non-unlimited dimension (Zero sized dimension for non-unlimited dimension)
 ```
 
### 対応
 
#### 最新版hdf5をインストール

ここでは、2016/5/25現在で最新版の1.18.17を、`$HOME/local`以下にインストールしています。
 
```sh
$ wget http://www.hdfgroup.org/ftp/HDF5/current/src/hdf5-1.8.17.tar
$ tar xvf hdf5-1.8.17.tar
$ cd hdf5-1.8.17/
$ ./configure --prefix=$HOME/local
$ make
$ make install
```


#### h5pyをインストール

最新版のhdf5をもとに、h5pyをインストールします。

```sh
# 古い環境の削除
$ pip uninstall h5py 
$ sudo yum remove hdf5-devel

# LIBRARY_PATHやINCLUDE_PATHの設定
$ export LIBRARY_PATH=$HOME/local/lib:$LIBRARY_PATH
$ export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
$ export C_INCLUDE_PATH=$HOME/local/include:$C_INCLUDE_PATH
$ export CPLUS_INCLUDE_PATH=$HOME/local/include:$CPLUS_INCLUDE_PATH

# h5pyのインストール
$ HDF5_DIR=$HOME/local/bin
$ pip install h5py
```

LIBRARY_PATHやINCLUDE_PATHまわりが設定できていないと、以下のようなエラーが表示されるので注意です。

```
[...]
    collect2: error: ld returned 1 exit status
    error: command 'gcc' failed with exit status 1
```

```
[...]
    /tmp/pip-build-CC4cFF/h5py/h5py/api_compat.h:27:18: fatal error: hdf5.h: No such file or directory
     #include "hdf5.h"
                      ^
    compilation terminated.
    error: command 'gcc' failed with exit status 1
```

#### h5pyで使用しているhdf5のバージョン確認

ちゃんと自分でコンパイルした最新版のhdf5が使用されているか確認します。

```py
In [1]: import h5py

In [2]: print(h5py.version.info)
Summary of the h5py configuration
---------------------------------

h5py    2.6.0
HDF5    1.8.17
Python  3.4.4 (default, May 19 2016, 04:58:42)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)]
sys.platform    linux
sys.maxsize     9223372036854775807
numpy   1.11.0
```

### テスト

それでは`save_weights`が正常に動作するかを、適当なmodelを作って確かめてみます。以下のコードを実行してkeras.h5が正常に出力されれば完了です。

```py
# test.py
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation

model = Sequential()
model.add(Dense(512, input_shape=(784,)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(10))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.save_weights('keras.h5')
```


### 参考

- [FAQ - Keras Documentation](http://keras.io/getting-started/faq/#how-can-i-save-a-keras-model)
	- Kerasにおけるモデルの保存方法
- [Bug Reports & Contributions — h5py 2.6.0 documentation](http://docs.h5py.org/en/latest/contributing.html)
	- h5pyのバージョンの確認方法