Skip to content
This repository has been archived by the owner on Mar 3, 2024. It is now read-only.

Commit

Permalink
Compatible with Keras 2.4.3
Browse files Browse the repository at this point in the history
  • Loading branch information
CyberZHG committed Jul 11, 2020
1 parent 615e113 commit 3008b41
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 134 deletions.
34 changes: 22 additions & 12 deletions .travis.yml
@@ -1,19 +1,29 @@
dist: xenial
language: python
python:
- "2.7"
- "3.6"
python: "3.6"
env:
global:
- COVERALLS_PARALLEL=true
matrix:
- KERAS_BACKEND=tensorflow
- KERAS_BACKEND=tensorflow TF_KERAS=1
install:
- wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
- bash miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda info -a
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION
- source activate test-environment
- export LD_LIBRARY_PATH=$HOME/miniconda/envs/test-environment/lib/:$LD_LIBRARY_PATH
- pip install --upgrade pip
- pip install numpy
- pip install tensorflow
- pip install keras
- pip install pycodestyle
- pip install coverage
- pip install -r requirements.txt
- pip install -r requirements-dev.txt
- pip install coveralls
- pip install keras-bi-lm
before_script:
- bash lint.sh
script:
- bash test.sh
- ./test.sh
after_success:
coveralls
notifications:
webhooks: https://coveralls.io/webhook
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 PoW
Copyright (c) 2020 Zhao HG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 3 additions & 1 deletion keras_bi_lm/__init__.py
@@ -1 +1,3 @@
from .model import BiLM
from .model import *

__version__ = '0.24.0'
33 changes: 33 additions & 0 deletions keras_bi_lm/backend.py
@@ -0,0 +1,33 @@
import os
from distutils.util import strtobool

__all__ = [
'keras', 'utils', 'activations', 'applications', 'backend', 'datasets',
'layers', 'preprocessing', 'wrappers', 'callbacks', 'constraints', 'initializers',
'metrics', 'models', 'losses', 'optimizers', 'regularizers', 'TF_KERAS',
]

TF_KERAS = strtobool(os.environ.get('TF_KERAS', '0'))

if TF_KERAS:
import tensorflow as tf
keras = tf.keras
else:
import keras

utils = keras.utils
activations = keras.activations
applications = keras.applications
backend = keras.backend
datasets = keras.datasets
layers = keras.layers
preprocessing = keras.preprocessing
wrappers = keras.wrappers
callbacks = keras.callbacks
constraints = keras.constraints
initializers = keras.initializers
metrics = keras.metrics
models = keras.models
losses = keras.losses
optimizers = keras.optimizers
regularizers = keras.regularizers
62 changes: 33 additions & 29 deletions keras_bi_lm/model.py
@@ -1,8 +1,31 @@
import keras
import numpy as np

from .backend import keras
from .weighted_sum import WeightedSum


__all__ = ['Reverse', 'BiLM']


class Reverse(keras.layers.Layer):

def __init__(self, **kwargs):
super().__init__(**kwargs)

def compute_mask(self, inputs, mask=None):
return self._reverse(mask)

def call(self, inputs, **kwargs):
return self._reverse(inputs)

@staticmethod
def _reverse(x):
if x is None:
return None
from keras import backend as K
return K.reverse(x, 1)


class BiLM(object):

def __init__(self,
Expand Down Expand Up @@ -72,11 +95,7 @@ def __init__(self,
name='Bi-LM-Input')
embedding_layer = input_layer

last_layer_forward, last_layer_backward = embedding_layer, keras.layers.Lambda(
function=self._reverse_x,
mask=lambda _, mask: self._reverse_x(mask),
name='Reverse'
)(embedding_layer)
last_layer_forward, last_layer_backward = embedding_layer, Reverse(name='Reverse')(embedding_layer)
self.rnn_layers_forward, self.rnn_layers_backward = [last_layer_forward], [last_layer_backward]
if rnn_type.lower() == 'gru':
rnn = keras.layers.GRU
Expand Down Expand Up @@ -139,11 +158,7 @@ def __init__(self,
last_layer_forward = keras.layers.Concatenate(name='Bi-LM-Forward')(self.rnn_layers_forward)
last_layer_backward = keras.layers.Concatenate(name='Bi-LM-Backward-Rev')(self.rnn_layers_backward)

last_layer_backward = keras.layers.Lambda(
function=self._reverse_x,
mask=lambda _, mask: self._reverse_x(mask),
name='Bi-LM-Backward'
)(last_layer_backward)
last_layer_backward = Reverse(name='Bi-LM-Backward')(last_layer_backward)

dense_layer_forward = keras.layers.Dense(units=token_num,
activation='softmax',
Expand All @@ -162,7 +177,7 @@ def save_model(self, model_path):
self.model.save(model_path)

def load_model(self, model_path):
self.model = keras.models.load_model(model_path)
self.model = keras.models.load_model(model_path, custom_objects={'Reverse': Reverse})

@staticmethod
def get_batch(sentences,
Expand Down Expand Up @@ -231,7 +246,7 @@ def get_feature_layers(self, input_layer=None, trainable=False, use_weighted_sum
:return [input_layer,] output_layer: Input and output layer.
"""
model = keras.models.clone_model(self.model, input_layer)
model = keras.models.clone_model(self.model)
if not trainable:
for layer in model.layers:
layer.trainable = False
Expand All @@ -246,23 +261,12 @@ def get_feature_layers(self, input_layer=None, trainable=False, use_weighted_sum
))
forward_layer = WeightedSum(name='Bi-LM-Forward-Sum')(rnn_layers_forward)
backward_layer_rev = WeightedSum(name='Bi-LM-Backward-Sum-Rev')(rnn_layers_backward)
backward_layer = keras.layers.Lambda(
function=self._reverse_x,
mask=lambda _, mask: self._reverse_x(mask),
name='Bi-LM-Backward-Sum'
)(backward_layer_rev)
backward_layer = Reverse(name='Bi-LM-Backward-Sum')(backward_layer_rev)
else:
forward_layer = model.get_layer(name='Bi-LM-Forward').output
backward_layer = model.get_layer(name='Bi-LM-Backward').output
output_layer = keras.layers.Concatenate(name='Bi-LM-Feature')([forward_layer, backward_layer])
if input_layer is None:
input_layer = model.layers[0].input
return input_layer, output_layer
return output_layer

@staticmethod
def _reverse_x(x):
if x is None:
return None
from keras import backend as K
return K.reverse(x, 1)
if input_layer is not None:
return model(input_layer)
input_layer = model.layers[0].input
return input_layer, output_layer
8 changes: 5 additions & 3 deletions keras_bi_lm/weighted_sum.py
@@ -1,9 +1,11 @@
import keras
import keras.backend as K
from.backend import keras
from.backend import backend as K

__all__ = ['WeightedSum']


class WeightedSum(keras.layers.Layer):
"""Sum the layers with trainable weights. All the layers should have the same shape and mask.
r"""Sum the layers with trainable weights. All the layers should have the same shape and mask.
h = \gamma * \sum_{i=0}^L w_i h_i
Expand Down
2 changes: 0 additions & 2 deletions lint.sh

This file was deleted.

1 change: 1 addition & 0 deletions requirements-dev.txt
Expand Up @@ -4,3 +4,4 @@ wheel>=0.31.0
tensorflow
coverage
nose
pycodestyle
33 changes: 23 additions & 10 deletions setup.py
@@ -1,30 +1,43 @@
import os
import re
import codecs
from setuptools import setup, find_packages

current_path = os.path.abspath(os.path.dirname(__file__))

with codecs.open('README.md', 'r', 'utf8') as reader:
long_description = reader.read()

def read_file(*parts):
with codecs.open(os.path.join(current_path, *parts), 'r', 'utf8') as reader:
return reader.read()

with codecs.open('requirements.txt', 'r', 'utf8') as reader:
install_requires = list(map(lambda x: x.strip(), reader.readlines()))

def get_requirements(*parts):
with codecs.open(os.path.join(current_path, *parts), 'r', 'utf8') as reader:
return list(map(lambda x: x.strip(), reader.readlines()))


def find_version(*file_paths):
version_file = read_file(*file_paths)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
if version_match:
return version_match.group(1)
raise RuntimeError('Unable to find version string.')


setup(
name='keras-bi-lm',
version='0.23.0',
version=find_version('keras_bi_lm', '__init__.py'),
packages=find_packages(),
url='https://github.com/CyberZHG/keras-bi-lm',
license='MIT',
author='CyberZHG',
author_email='CyberZHG@gmail.com',
author_email='CyberZHG@users.noreply.github.com',
description='Train the Bi-LM model and use it as a feature extraction method',
long_description=long_description,
long_description=read_file('README.md'),
long_description_content_type='text/markdown',
install_requires=install_requires,
install_requires=get_requirements('requirements.txt'),
classifiers=(
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
),
Expand Down
3 changes: 2 additions & 1 deletion test.sh
@@ -1,2 +1,3 @@
#!/usr/bin/env bash
nosetests --with-coverage --cover-html --cover-html-dir=htmlcov --cover-package="keras_bi_lm" tests
pycodestyle --max-line-length=120 keras_bi_lm tests && \
nosetests --nocapture --with-coverage --cover-erase --cover-html --cover-html-dir=htmlcov --cover-package=keras_bi_lm --with-doctest
14 changes: 7 additions & 7 deletions tests/test_get_feature_layers.py
@@ -1,5 +1,5 @@
import unittest
import keras
from keras_bi_lm.backend import keras
from keras_bi_lm import BiLM


Expand All @@ -8,24 +8,24 @@ class TestGetFeatureLayers(unittest.TestCase):
def test_one_layer(self):
bi_lm = BiLM(token_num=101, rnn_layer_num=1, rnn_units=50, rnn_type='gru')
input_layer, output_layer = bi_lm.get_feature_layers()
self.assertEqual((None, None), input_layer._keras_shape)
self.assertEqual((None, None, 100), output_layer._keras_shape)
self.assertEqual((None, None), tuple(input_layer.shape))
self.assertEqual((None, None, 100), tuple(output_layer.shape))
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.summary()

def test_bidirectional(self):
bi_lm = BiLM(token_num=102, rnn_layer_num=1, rnn_units=50, rnn_type='gru', use_bidirectional=True)
input_layer, output_layer = bi_lm.get_feature_layers()
self.assertEqual((None, None), input_layer._keras_shape)
self.assertEqual((None, None, 200), output_layer._keras_shape)
self.assertEqual((None, None), tuple(input_layer.shape))
self.assertEqual((None, None, 200), tuple(output_layer.shape))
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.summary()

def test_multiple_layers(self):
bi_lm = BiLM(token_num=103, rnn_layer_num=6, rnn_keep_num=3, rnn_units=50, rnn_type='lstm')
input_layer, output_layer = bi_lm.get_feature_layers()
self.assertEqual((None, None), input_layer._keras_shape)
self.assertEqual((None, None, 300), output_layer._keras_shape)
self.assertEqual((None, None), tuple(input_layer.shape))
self.assertEqual((None, None, 300), tuple(output_layer.shape))
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.summary()
for layer in bi_lm.model.layers:
Expand Down
24 changes: 11 additions & 13 deletions tests/test_save_load.py
@@ -1,23 +1,21 @@
import os
import unittest
import tempfile
from keras_bi_lm import BiLM


class TestSaveLoad(unittest.TestCase):

def setUp(self):
self.tmp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
if not os.path.exists(self.tmp_path):
os.makedirs(self.tmp_path)

def test_save_load(self):
model_path = os.path.join(self.tmp_path, 'save_load.h5')
model = BiLM(token_num=101)
model.save_model(model_path)
model.load_model(model_path)
with tempfile.TemporaryDirectory() as temp_path:
model_path = os.path.join(temp_path, 'save_load.h5')
model = BiLM(token_num=101)
model.save_model(model_path)
model.load_model(model_path)

def test_init_load(self):
model_path = os.path.join(self.tmp_path, 'save_load.h5')
model = BiLM(token_num=101)
model.save_model(model_path)
BiLM(model_path=model_path)
with tempfile.TemporaryDirectory() as temp_path:
model_path = os.path.join(temp_path, 'save_load.h5')
model = BiLM(token_num=101)
model.save_model(model_path)
BiLM(model_path=model_path)

0 comments on commit 3008b41

Please sign in to comment.