blob: e69bab41965b86ce6d0dba39437b0e753ed1ce98 [file] [log] [blame]
# coding=utf-8
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
m4_changequote(`<!', `!>')
import sys
import numpy as np
import os
import re
from os import path
# Add convex module to the pythonpath.
sys.path.append(path.dirname(path.dirname(path.dirname(path.dirname(path.abspath(__file__))))))
sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
import keras
from keras.models import *
from keras.layers import *
import unittest
from mock import *
import plpy_mock as plpy
try:
from pgsanity.pgsanity import check_string as pglint
pglint("SELECT 1;")
except:
# Just skip this test if "pip install pgsanity" hasn't been run
# or isn't functioning (eg. ecpg isn't in path)
def pglint(q, s=False):
return (True, '')
# helper for multiplying array by int
def mult(k,arr):
return [ k*a for a in arr ]
class MadlibKerasFitTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras
self.subject = madlib_keras
self.model = Sequential()
self.model.add(Conv2D(2, kernel_size=(1, 1), activation='relu',
input_shape=(1,1,1,), padding='same'))
self.model.add(Flatten())
self.compile_params = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), loss='categorical_crossentropy', metrics=['accuracy']"
self.fit_params = "batch_size=1, epochs=1"
self.model_weights = [3,4,5,6]
self.serialized_weights = np.array(self.model_weights, dtype=np.float32
).tostring()
self.dist_key_mapping = [0,1,2]
self.accessible_gpus_for_seg = [0]
self.independent_var_real = [[[[0.5]]]] * 10
self.dependent_var_int = [[0,1]] * 10
# Params as bytea
self.independent_var = np.array(self.independent_var_real, dtype=np.float32).tobytes()
self.dependent_var = np.array(self.dependent_var_int, dtype=np.int16).tobytes()
self.independent_var_shape = [10,1,1,1]
self.dependent_var_shape = [10,2]
# We test on segment 0, which has 3 buffers filled with 10 identical
# images each, or 30 images total
self.total_images_per_seg = [3*len(self.dependent_var_int),20,40]
self.dummy_prev_weights = 'dummy weights'
def tearDown(self):
self.module_patcher.stop()
def _test_fit_transition_first_buffer_pass(self, is_platform_pg):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = 0
ending_image_count = len(self.dependent_var_int)
# last iteration Call
previous_state = np.array(self.model_weights, dtype=np.float32)
k = {'SD': {}}
new_state = self.subject.fit_transition(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_state.tostring(), True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue(k['SD']['segment_model'])
# Non-last iteration Call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
previous_state = np.array(self.model_weights, dtype=np.float32)
k = {'SD' : {}}
new_state = self.subject.fit_transition(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_state.tostring(), False, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue(k['SD']['segment_model'])
def test_fit_transition_multiple_model_no_cache_first_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 0
ending_image_count = len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
k = {'SD': {}}
new_state = self.subject.fit_transition(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), True, True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session must not be called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue(k['SD']['segment_model'])
def test_fit_transition_multiple_model_cache_first_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 0
ending_image_count = len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
k = {'SD': {}}
new_state = self.subject.fit_multiple_transition_caching(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session should only be called for the last row
self.assertEqual(0, self.subject.K.set_session.call_count)
# Clear session must not be called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue('segment_model' not in k['SD'])
self.assertTrue('cache_set' not in k['SD'])
self.assertTrue(k['SD']['x_train'])
self.assertTrue(k['SD']['y_train'])
def _test_fit_transition_middle_buffer_pass(self, is_platform_pg):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
# last iteration Call
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model': self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
# Non-last iteration Call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model': self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, False, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
def test_fit_transition_multiple_model_no_cache_middle_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
# last iteration Call
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model': self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, True, True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
def test_fit_transition_multiple_model_cache_middle_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
x_train = list()
y_train = list()
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
k = {'SD': {'x_train': x_train, 'y_train': y_train}}
state = starting_image_count
new_state = self.subject.fit_multiple_transition_caching(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), True, **k)
image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is only called for the last buffer
self.assertEqual(0, self.subject.K.set_session.call_count)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue('segment_model' not in k['SD'])
self.assertTrue('cache_set' not in k['SD'])
self.assertTrue(k['SD']['x_train'])
self.assertTrue(k['SD']['y_train'])
def _test_fit_transition_last_buffer_pass(self, is_platform_pg):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
# last iteration Call
multiplied_weights = mult(self.total_images_per_seg[0],self.model_weights)
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model' :self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, True, **k)
state = np.fromstring(new_state, dtype=np.float32)
image_count = state[0]
weights = np.rint(state[1:]).astype(np.int)
self.assertEqual(ending_image_count, image_count)
# weights should be multiplied by final image count
self.assertTrue((multiplied_weights == weights).all())
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer in gpdb,
# but not in postgres
self.assertEqual(1, self.subject.K.clear_session.call_count)
# Non-last iteration Call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
multiplied_weights = mult(self.total_images_per_seg[0],self.model_weights)
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model' :self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, False, **k)
state = np.fromstring(new_state, dtype=np.float32)
image_count = state[0]
weights = np.rint(state[1:]).astype(np.int)
self.assertEqual(ending_image_count, image_count)
# weights should be multiplied by final image count
self.assertTrue((multiplied_weights == weights).all())
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer in gpdb,
# but not in postgres
self.assertEqual(0, self.subject.K.clear_session.call_count)
def test_fit_transition_multiple_model_no_cache_last_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
# last iteration Call
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
k = {'SD': {'segment_model' :self.model, 'sess': Mock()}}
state = starting_image_count
new_state = self.subject.fit_transition(
state , self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), None, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, self.dummy_prev_weights, True, True, **k)
state = np.fromstring(new_state, dtype=np.float32)
weights = np.rint(state[0:]).astype(np.int)
## image count should not be added to the final state of
# fit multiple
self.assertEqual(len(self.model_weights), len(weights))
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer in gpdb,
# but not in postgres
self.assertEqual(1, self.subject.K.clear_session.call_count)
def test_fit_transition_multiple_model_cache_last_buffer_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
x_train = list()
y_train = list()
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
k = {'SD': {'x_train': x_train, 'y_train': y_train}}
state = starting_image_count
new_state = self.subject.fit_multiple_transition_caching(
state, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), False, **k)
state = np.fromstring(new_state, dtype=np.float32)
weights = np.rint(state[0:]).astype(np.int)
## image count should not be added to the final state of
# fit multiple
self.assertEqual(len(self.model_weights), len(weights))
# set_session is only called for the last buffer
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer
self.assertEqual(1, self.subject.K.clear_session.call_count)
self.assertTrue('segment_model' not in k['SD'])
self.assertTrue(k['SD']['cache_set'])
self.assertTrue(k['SD']['x_train'])
self.assertTrue(k['SD']['y_train'])
def test_fit_transition_multiple_model_cache_filled_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
x_train = list()
y_train = list()
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
k = {'SD': {'x_train': x_train, 'y_train': y_train, 'cache_set': True}}
new_state = self.subject.fit_multiple_transition_caching(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), False, **k)
state = np.fromstring(new_state, dtype=np.float32)
weights = np.rint(state[0:]).astype(np.int)
## image count should not be added to the final state of
# fit multiple
self.assertEqual(len(self.model_weights), len(weights))
# set_session is only called for the last buffer
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer
self.assertEqual(1, self.subject.K.clear_session.call_count)
self.assertTrue('segment_model' not in k['SD'])
self.assertTrue(k['SD']['cache_set'])
self.assertTrue(k['SD']['x_train'])
self.assertTrue(k['SD']['y_train'])
def test_fit_transition_multiple_model_cache_filled_final_training_pass(self):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
previous_weights = np.array(self.model_weights, dtype=np.float32)
x_train = list()
y_train = list()
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
x_train.append(self.subject.np_array_float32(self.independent_var, self.independent_var_shape))
y_train.append(self.subject.np_array_int16(self.dependent_var, self.dependent_var_shape))
k = {'SD': {'x_train': x_train, 'y_train': y_train, 'cache_set': True}}
new_state = self.subject.fit_multiple_transition_caching(
None, self.dependent_var, self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(), self.compile_params, self.fit_params, 0,
self.dist_key_mapping, 0, 4, self.total_images_per_seg, False,
self.accessible_gpus_for_seg, previous_weights.tostring(), True, **k)
state = np.fromstring(new_state, dtype=np.float32)
weights = np.rint(state[0:]).astype(np.int)
## image count should not be added to the final state of
# fit multiple
self.assertEqual(len(self.model_weights), len(weights))
# set_session is only called for the last buffer
self.assertEqual(1, self.subject.K.set_session.call_count)
# Clear session and sess.close must get called for the last buffer
self.assertEqual(1, self.subject.K.clear_session.call_count)
self.assertTrue('segment_model' not in k['SD'])
self.assertTrue('cache_set' not in k['SD'])
self.assertTrue('x_train' not in k['SD'])
self.assertTrue('y_train' not in k['SD'])
def test_fit_transition_first_buffer_pass_pg(self):
self._test_fit_transition_first_buffer_pass(True)
def test_fit_transition_first_buffer_pass_gpdb(self):
self._test_fit_transition_first_buffer_pass(False)
def test_fit_transition_middle_buffer_pass_pg(self):
self._test_fit_transition_middle_buffer_pass(True)
def test_fit_transition_middle_buffer_pass_gpdb(self):
self._test_fit_transition_middle_buffer_pass(False)
def test_fit_transition_last_buffer_pass_pg(self):
self._test_fit_transition_last_buffer_pass(True)
def test_fit_transition_last_buffer_pass_gpdb(self):
self._test_fit_transition_last_buffer_pass(False)
def test_fit_transition_first_tuple_none_ind_var_dep_var(self):
k = {}
self.assertEqual('dummy_state',
self.subject.fit_transition('dummy_state', [0], None,
'noshape', 'noshape',
'dummy_model_json', "foo", "bar",
1, [0,1,2], 0, 4, [3,3,3], False,
[0], 'dummy_prev_state', **k))
self.assertEqual('dummy_state',
self.subject.fit_transition('dummy_state', None, [[0.5]],
'noshape', 'noshape',
'dummy_model_json', "foo", "bar",
1, [0,1,2], 0, 4, [3,3,3], False,
[0], 'dummy_prev_state', **k))
self.assertEqual('dummy_state',
self.subject.fit_transition('dummy_state', None, None,
'noshape', 'noshape',
'dummy_model_json', "foo", "bar",
1, [0,1,2], 0, 4, [3,3,3], False,
[0], 'dummy_prev_state', **k))
def test_fit_merge(self):
image_count = self.total_images_per_seg[0]
state1 = [image_count]
state1.extend(mult(3,self.model_weights))
state1 = np.array(state1, dtype=np.float32)
state2 = [image_count+30]
state2.extend(mult(2,self.model_weights))
state2 = np.array(state2, dtype=np.float32)
merged_state = self.subject.fit_merge(state1.tostring(),state2.tostring())
state = np.fromstring(merged_state, dtype=np.float32)
image_count_total = state[0]
weights = np.rint(state[1:]).astype(np.int)
self.assertEqual( 2*image_count+30 , image_count_total )
self.assertTrue( (mult(5,self.model_weights) == weights).all())
def test_fit_merge_none_first(self):
image_count = self.total_images_per_seg[0]
input_state = [image_count]
input_state.extend(self.model_weights)
input_state = np.array(input_state, dtype=np.float32)
merged_state = self.subject.fit_merge(None, input_state.tostring())
state = np.fromstring(merged_state, dtype=np.float32)
image_count_total = state[0]
weights = np.rint(state[1:]).astype(np.int)
self.assertEqual(image_count, image_count_total)
self.assertTrue((self.model_weights == weights).all())
def test_fit_merge_none_second(self):
image_count = self.total_images_per_seg[0]
input_state = [image_count]
input_state.extend(self.model_weights)
input_state = np.array(input_state, dtype=np.float32)
merged_state = self.subject.fit_merge(input_state.tostring(), None)
state = np.fromstring(merged_state, dtype=np.float32)
image_count_total = state[0]
weights = np.rint(state[1:]).astype(np.int)
self.assertEqual(image_count, image_count_total)
self.assertTrue((self.model_weights == weights).all())
def test_fit_merge_both_none(self):
result = self.subject.fit_merge(None,None)
self.assertEqual(None, result)
def test_fit_final(self):
image_count = self.total_images_per_seg[0]
input_state = [image_count]
input_state.extend(mult(image_count,self.model_weights))
input_state = np.array(input_state, dtype=np.float32)
output_state = self.subject.fit_final(input_state.tostring())
output_state = np.fromstring(output_state, dtype=np.float32)
weights = np.rint(output_state).astype(np.int)
self.assertTrue((self.model_weights == weights).all())
def test_fit_final_none(self):
result = self.subject.fit_final(None)
self.assertEqual(result, None)
def test_fit_final_image_count_zero(self):
input_state = [0]
input_state.extend(self.model_weights)
input_state = np.array(input_state, dtype=np.float32)
with self.assertRaises(plpy.PLPYException):
result = self.subject.fit_final(input_state.tostring())
def test_should_compute_metrics_this_iter_last_iter_case1(self):
res = self.subject.should_compute_metrics_this_iter(5, 5, 5)
self.assertEqual(True, res)
def test_should_compute_metrics_this_iter_last_iter_case2(self):
res = self.subject.should_compute_metrics_this_iter(5, 3, 5)
self.assertEqual(True, res)
def test_should_compute_metrics_this_iter_before_interval(self):
res = self.subject.should_compute_metrics_this_iter(1, 3, 5)
self.assertEqual(False, res)
def test_should_compute_metrics_this_iter_after_interval(self):
res = self.subject.should_compute_metrics_this_iter(4, 3, 5)
self.assertEqual(False, res)
def test_should_compute_metrics_this_iter_at_interval(self):
res = self.subject.should_compute_metrics_this_iter(3, 3, 5)
self.assertEqual(True, res)
def test_should_compute_metrics_this_iter_every_iter(self):
res = self.subject.should_compute_metrics_this_iter(2, 1, 5)
self.assertEqual(True, res)
class InternalKerasPredictTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_predict
self.subject = madlib_keras_predict
self.model = Sequential()
self.model.add(Conv2D(2, kernel_size=(1, 1), activation='relu',
input_shape=(1,1,1,), padding='same'))
self.model.add(Flatten())
self.all_seg_ids = [0,1,2]
self.independent_var = [[[240]]]
self.total_images_per_seg = [3,3,4]
self.subject.K.set_session = Mock()
self.subject.clear_keras_session = Mock()
def tearDown(self):
self.module_patcher.stop()
def test_predict_first_image_pass_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
model_weights = [1, 2, 3, 4]
serialized_weights = np.array(model_weights, dtype=np.float32).tostring()
k = {'SD': {}}
is_response = True
result = self.subject.internal_keras_predict(
self.independent_var, self.model.to_json(),
serialized_weights, 255, 0, self.all_seg_ids,
self.total_images_per_seg, False, 0, 4, **k)
self.assertEqual(2, len(result))
self.assertEqual(1, k['SD']['row_count'])
self.assertEqual(True, 'segment_model_predict' in k['SD'])
def test_predict_middle_image_pass_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
k = {'SD': { 'row_count': 1}}
k['SD']['segment_model_predict'] = self.model
is_response = True
result = self.subject.internal_keras_predict(
self.independent_var, None, None, 255, 0,
self.all_seg_ids, self.total_images_per_seg, False, 0, 4, **k)
self.assertEqual(2, len(result))
self.assertEqual(2, k['SD']['row_count'])
self.assertEqual(True, 'segment_model_predict' in k['SD'])
def test_predict_last_image_pass_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
self.model.add(Dense(3))
k = {'SD': { 'row_count': 2}}
k['SD']['segment_model_predict'] = self.model
is_response = True
result = self.subject.internal_keras_predict(
self.independent_var, None, None, 255, 0,
self.all_seg_ids, self.total_images_per_seg, False, 0, 4, **k)
self.assertEqual(3, len(result))
self.assertEqual(False, 'row_count' in k['SD'])
self.assertEqual(False, 'segment_model_predict' in k['SD'])
k = {'SD': { 'row_count': 2}}
k['SD']['segment_model_predict'] = self.model
is_response = False
result = self.subject.internal_keras_predict(
self.independent_var, None, None, 255, 0,
self.all_seg_ids, self.total_images_per_seg, False, 0, 4, **k)
# we except len(result) to be 3 because we have 3 dense layers in the
# architecture
self.assertEqual(3, len(result))
self.assertEqual(False, 'row_count' in k['SD'])
self.assertEqual(False, 'segment_model_predict' in k['SD'])
def test_predict_error_should_clear_sd(self):
self.subject.is_platform_pg = Mock(return_value = False)
self.model.add(Dense(3))
# inject error by passing 0 as the normalizing const so that we get a
# divide by zero error
normalizing_const = 0
k = {'SD':{}}
is_response = True
with self.assertRaises(plpy.PLPYException):
self.subject.internal_keras_predict(
self.independent_var, None, None, normalizing_const,
0, self.all_seg_ids, self.total_images_per_seg, False, 0, 4, **k)
self.assertEqual(False, 'row_count' in k['SD'])
self.assertEqual(False, 'segment_model_predict' in k['SD'])
class MadlibKerasPredictBYOMTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
self.num_classes = 5
self.model = Sequential()
self.model.add(Conv2D(2, kernel_size=(1, 1), activation='relu',
input_shape=(1,1,1,), padding='same'))
self.model.add(Dense(self.num_classes))
self.pred_type = 'prob'
self.use_gpus = False
self.class_values = ['foo', 'bar', 'baaz', 'foo2', 'bar2']
self.normalizing_const = 255.0
import madlib_keras_predict
self.module = madlib_keras_predict
self.module.get_model_arch_weights = Mock(return_value=(
self.model.to_json(), 'weights'))
self.module.InputValidator.validate_predict_byom_tables = Mock()
self.module.InputValidator.validate_input_shape = Mock()
self.module.BasePredict.call_internal_keras = Mock()
def tearDown(self):
self.module_patcher.stop()
def test_predictbyom_defaults_1(self):
self.module.get_accessible_gpus_for_seg = Mock(return_value = [2,2,2])
res = self.module.PredictBYOM('schema_madlib', 'model_arch_table',
'model_id', 'test_table', 'id_col',
'independent_varname', 'output_table', None,
True, None, None)
self.assertEqual('prob', res.pred_type)
self.assertEqual(2, res.gpus_per_host)
self.assertEqual([0,1,2,3,4], res.class_values)
self.assertEqual(1.0, res.normalizing_const)
def test_predictbyom_defaults_2(self):
res = self.module.PredictBYOM('schema_madlib', 'model_arch_table',
'model_id', 'test_table', 'id_col',
'independent_varname', 'output_table',
self.pred_type, self.use_gpus,
self.class_values, self.normalizing_const)
self.assertEqual('prob', res.pred_type)
self.assertEqual(0, res.gpus_per_host)
self.assertEqual(['foo', 'bar', 'baaz', 'foo2', 'bar2'], res.class_values)
self.assertEqual(255.0, res.normalizing_const)
def test_predictbyom_exception_invalid_params(self):
with self.assertRaises(plpy.PLPYException) as error:
self.module.PredictBYOM('schema_madlib', 'model_arch_table',
'model_id', 'test_table', 'id_col',
'independent_varname', 'output_table',
'invalid_pred_type', self.use_gpus,
self.class_values, self.normalizing_const)
self.assertIn('invalid_pred_type', str(error.exception))
with self.assertRaises(plpy.PLPYException) as error:
self.module.PredictBYOM('schema_madlib', 'model_arch_table',
'model_id', 'test_table', 'id_col',
'independent_varname', 'output_table',
self.pred_type, self.use_gpus,
["foo", "bar", "baaz"], self.normalizing_const)
self.assertIn('class values', str(error.exception).lower())
with self.assertRaises(plpy.PLPYException) as error:
self.module.PredictBYOM('schema_madlib', 'model_arch_table',
'model_id', 'test_table', 'id_col',
'independent_varname', 'output_table',
self.pred_type, self.use_gpus,
self.class_values, 0)
self.assertIn('normalizing const', str(error.exception).lower())
class MadlibKerasWrapperTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_wrapper
self.subject = madlib_keras_wrapper
self.use_gpus = False
def tearDown(self):
self.module_patcher.stop()
def test_get_gpu_memory_fraction(self):
gpus_per_host = 4
segments_per_host = 4
result = self.subject.get_gpu_memory_fraction(gpus_per_host, segments_per_host)
self.assertEqual(result, 0.9)
gpus_per_host = 10
segments_per_host = 4
result = self.subject.get_gpu_memory_fraction(gpus_per_host, segments_per_host)
self.assertEqual(result, 0.9)
gpus_per_host = 2
segments_per_host = 6
result = self.subject.get_gpu_memory_fraction(gpus_per_host, segments_per_host)
self.assertEqual(result, 0.3)
gpus_per_host = 1
segments_per_host = 4
result = self.subject.get_gpu_memory_fraction(gpus_per_host, segments_per_host)
self.assertEqual(result, 0.225)
def test_get_device_name_and_set_cuda_env_postgres(self):
self.subject.is_platform_pg = Mock(return_value = True)
seg_id = -1
gpus_per_host = 3
self.assertEqual('/gpu:0', self.subject.get_device_name_and_set_cuda_env(
gpus_per_host, seg_id ))
self.assertEqual('0,1,2', os.environ['CUDA_VISIBLE_DEVICES'])
gpus_per_host = 0
self.assertEqual('/cpu:0', self.subject.get_device_name_and_set_cuda_env(
gpus_per_host, seg_id ))
self.assertEqual('-1', os.environ['CUDA_VISIBLE_DEVICES'])
def test_get_device_name_and_set_cuda_env_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
seg_id=3
gpus_per_host=2
self.assertEqual('/gpu:0', self.subject.get_device_name_and_set_cuda_env(
gpus_per_host, seg_id))
self.assertEqual('1', os.environ['CUDA_VISIBLE_DEVICES'])
gpus_per_host=0
self.assertEqual('/cpu:0', self.subject.get_device_name_and_set_cuda_env(
gpus_per_host, seg_id))
self.assertEqual('-1', os.environ['CUDA_VISIBLE_DEVICES'])
def test_split_and_strip(self):
self.assertEqual(('a','b'), self.subject.split_and_strip(' a = b '))
def test_parse_optimizer(self):
opt_name = 'SGD'
final_args = {'lr':0.01, 'decay':1e-6, 'nesterov':True}
compile_dict = {}
compile_dict['optimizer']='SGD(lr=0.01, decay=1e-6, nesterov=True)'
result_name, result_params = self.subject.parse_optimizer(compile_dict)
self.assertEqual(result_name, opt_name)
self.assertDictEqual(result_params, final_args)
def test_validate_and_literal_eval_keys(self):
test_dict = {'batch_size':'2', 'epochs':'1', 'verbose':'0'}
target_dict = {'batch_size':2, 'epochs':1, 'verbose':0}
literal_eval_fit_params = ['batch_size','epochs','verbose','shuffle',
'class_weight','initial_epoch','steps_per_epoch']
accepted_fit_params = literal_eval_fit_params + ['shuffle']
result_params = self.subject.validate_and_literal_eval_keys(
test_dict,
literal_eval_fit_params,
accepted_fit_params)
self.assertDictEqual(result_params, target_dict)
def test_parse_and_validate_fit_params(self):
result = {'batch_size':2, 'epochs':1, 'verbose':0}
self.assertDictEqual(result, self.subject.parse_and_validate_fit_params('batch_size=2, epochs=1, verbose=0'))
def test_parse_and_validate_fit_params(self):
test_str = "batch_size=2, epochs=1, verbose=0"
fit_dict = {'batch_size':2, 'epochs':1, 'verbose':0}
result_params = self.subject.parse_and_validate_fit_params(test_str)
self.assertDictEqual(result_params, fit_dict)
test_str = "batch_size=2, epochs=1, verbose=0, shuffle = 'batch'"
fit_dict = {'batch_size':2, 'epochs':1, 'verbose':0, 'shuffle':'batch'}
result_params = self.subject.parse_and_validate_fit_params(test_str)
self.assertDictEqual(result_params, fit_dict)
test_str = "batch_size=2, epochs=1, verbose=0, shuffle = True"
fit_dict = {'batch_size':2, 'epochs':1, 'verbose':0, 'shuffle':True}
result_params = self.subject.parse_and_validate_fit_params(test_str)
self.assertDictEqual(result_params, fit_dict)
test_str = ""
fit_dict = {}
result_params = self.subject.parse_and_validate_fit_params(test_str)
self.assertDictEqual(result_params, fit_dict)
def test_parse_and_validate_fit_params_duplicate_params(self):
test_str = "batch_size=1, batch_size=10, verbose=0"
fit_dict = {'batch_size':10, 'verbose':0}
result_params = self.subject.parse_and_validate_fit_params(test_str)
self.assertDictEqual(result_params, fit_dict)
def test_parse_and_validate_fit_params_invalid_fit_param_fail(self):
test_str = "does_not_exist=2, epochs=1, verbose=0"
with self.assertRaises(plpy.PLPYException) as error:
self.subject.parse_and_validate_fit_params(test_str)
self.assertIn('not currently accepted', str(error.exception))
test_str = "batch_size=not_lit_eval(1), epochs=1, verbose=0"
with self.assertRaises(plpy.PLPYException) as error:
self.subject.parse_and_validate_fit_params(test_str)
self.assertIn('invalid input value', str(error.exception))
def test_parse_and_validate_compile_params(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), " \
"loss='categorical_crossentropy', metrics=['accuracy']"
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['accuracy'], 'loss':'categorical_crossentropy'}
opt_name,opt_args,result_params = self.subject.parse_and_validate_compile_params(test_str)
self.assertDictEqual(result_params, compile_dict)
# Test without the metrics
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), " \
"loss='categorical_crossentropy'"
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'loss':'categorical_crossentropy'}
opt_name,opt_args,result_params = self.subject.parse_and_validate_compile_params(test_str)
self.assertDictEqual(result_params, compile_dict)
def test_validate_metrics_None_pass(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['accuracy'], 'loss':'categorical_crossentropy'}
self.subject._validate_metrics(compile_dict)
def test_validate_metrics_empty_pass(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':[], 'loss':'categorical_crossentropy'}
self.subject._validate_metrics(compile_dict)
def test_validate_metrics_two_params_fail(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['accuracy','mae'], 'loss':'categorical_crossentropy'}
with self.assertRaises(plpy.PLPYException) as error:
self.subject._validate_metrics(compile_dict)
def test_validate_metrics_one_unsupported_fail(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['sparse_categorical_accuracy'], 'loss':'categorical_crossentropy'}
with self.assertRaises(plpy.PLPYException) as error:
self.subject._validate_metrics(compile_dict)
def test_validate_metrics_two_unsupported_fail(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['sparse_categorical_accuracy', 'sparse_categorical_crossentropy'], 'loss':'categorical_crossentropy'}
with self.assertRaises(plpy.PLPYException) as error:
self.subject._validate_metrics(compile_dict)
def test_validate_metrics_one_supported_one_unsupported_fail(self):
compile_dict = {'optimizer':'SGD(lr=0.01, decay=1e-6, nesterov=True)',
'metrics':['accuracy', 'sparse_categorical_crossentropy'], 'loss':'categorical_crossentropy'}
with self.assertRaises(plpy.PLPYException) as error:
self.subject._validate_metrics(compile_dict)
def test_parse_and_validate_compile_params_default_optimizer_pass(self):
test_str = "optimizer='SGD', loss='categorical_crossentropy'"
_,_,result_dict = self.subject.parse_and_validate_compile_params(test_str)
self.assertEqual('SGD', result_dict['optimizer'])
test_str = "optimizer='sgd()', loss='categorical_crossentropy'"
_,_,result_dict = self.subject.parse_and_validate_compile_params(test_str)
self.assertEqual('sgd()', result_dict['optimizer'])
def test_parse_and_validate_compile_params_duplicate_loss(self):
test_str = "optimizer='SGD', loss='loss1', metrics=['accuracy'], loss='loss2'"
_,_,result_dict = self.subject.parse_and_validate_compile_params(test_str)
self.assertEqual('loss2', result_dict['loss'])
def test_parse_and_validate_compile_params_no_optimizer_fail(self):
test_str = "loss='categorical_crossentropy', metrics=['accuracy']"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_no_loss_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), " \
"metrics=['accuracy']"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_unsupported_loss_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), " \
"metrics=['accuracy'], loss='sparse_categorical_crossentropy'"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_dict_metrics_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), " \
"loss='categorical_crossentropy', metrics={'0':'accuracy'}"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_tensor_loss_weights_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy', metrics=['accuracy']," \
" loss_weights = keras.layers.Input(shape=(32,))"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_list_dict_sample_weight_mode_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy', metrics=['accuracy']," \
" sample_weight_mode = [0,1]"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy', metrics=['accuracy']," \
" sample_weight_mode = {'0':'1'}"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_compile_params_target_tensors_fail(self):
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy', metrics=['accuracy']," \
" target_tensors = keras.layers.Input(shape=(32,))"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_compile_params(test_str)
def test_parse_and_validate_fit_params_callbacks_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, callbacks=keras.callbacks.Callback()"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_fit_params_validation_split_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, validation_split=0.1"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_fit_params_validation_data_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, validation_data=(1,2,3)"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_fit_params_sample_weight_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, sample_weight=np.array([1,2,3])"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_fit_params_validation_steps_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, validation_steps=1"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_fit_params_validation_freq_fail(self):
test_str = "batch_size=2, epochs=1, verbose=0, validation_freq=1"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
test_str = "batch_size=2, epochs=1, verbose=0, validation_freq=[1]"
with self.assertRaises(plpy.PLPYException):
self.subject.parse_and_validate_fit_params(test_str)
def test_parse_and_validate_compile_params_syntax_error_fail(self):
#missing end parentheses
test_str = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True"
with self.assertRaises(ValueError) as error:
self.subject.parse_and_validate_compile_params(test_str)
self.assertIn('could not convert string to float', str(error.exception))
#missing beginning parentheses
test_str = "optimizer=SGDlr=0.01, decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy'"
with self.assertRaises(plpy.PLPYException) as error:
self.subject.parse_and_validate_compile_params(test_str)
self.assertIn('not currently accepted', str(error.exception))
#missing comma
test_str = "optimizer=SGD(lr=0.01 decay=1e-6, nesterov=True)," \
" loss='categorical_crossentropy'"
with self.assertRaises(ValueError) as error:
self.subject.parse_and_validate_compile_params(test_str)
self.assertIn('invalid literal for float', str(error.exception))
def test_parse_and_validate_fit_params_invalid_optimizer_fail(self):
test_str = "optimizer='SGD1', loss='categorical_crossentropy'"
with self.assertRaises(plpy.PLPYException) as error:
self.subject.parse_and_validate_compile_params(test_str)
self.assertIn('invalid optimizer', str(error.exception))
class MadlibKerasFitCommonValidatorTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_validator
self.subject = madlib_keras_validator
def tearDown(self):
self.module_patcher.stop()
def test_is_valid_metrics_compute_frequency_True_None(self):
self.subject.FitCommonValidator._validate_common_args = Mock()
obj = self.subject.FitCommonValidator(
'test_table', 'val_table', 'model_table', 'model_arch_table', 2,
'dep_varname', 'independent_varname', 5, None, False, False, [0],
'module_name', None)
self.assertEqual(True, obj._is_valid_metrics_compute_frequency())
def test_is_valid_metrics_compute_frequency_True_num(self):
self.subject.FitCommonValidator._validate_common_args = Mock()
obj = self.subject.FitCommonValidator(
'test_table', 'val_table', 'model_table', 'model_arch_table', 2,
'dep_varname', 'independent_varname', 5, 3, False, False, [0],
'module_name', None)
self.assertEqual(True, obj._is_valid_metrics_compute_frequency())
def test_is_valid_metrics_compute_frequency_False_zero(self):
self.subject.FitCommonValidator._validate_common_args = Mock()
obj = self.subject.FitCommonValidator(
'test_table', 'val_table', 'model_table', 'model_arch_table', 2,
'dep_varname', 'independent_varname', 5, 0, False, False, [0],
'module_name', None)
self.assertEqual(False, obj._is_valid_metrics_compute_frequency())
def test_is_valid_metrics_compute_frequency_False_greater(self):
self.subject.FitCommonValidator._validate_common_args = Mock()
obj = self.subject.FitCommonValidator(
'test_table', 'val_table', 'model_table', 'model_arch_table', 2,
'dep_varname', 'independent_varname', 5, 6, False, False, [0],
'module_name', None)
self.assertEqual(False, obj._is_valid_metrics_compute_frequency())
class InputValidatorTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_validator
self.module = madlib_keras_validator
self.subject = self.module.InputValidator
self.module_name = 'module'
self.test_table = 'test_table'
self.model_table = 'model_table'
self.id_col = 'id_col'
self.ind_var = 'ind_var'
self.model_arch_table = 'model_arch_table'
self.model_id = 2
self.num_classes = 1598
self.model = Sequential()
self.model.add(Conv2D(2, kernel_size=(1, 1), activation='relu',
input_shape=(1,1,1,), padding='same'))
self.model.add(Dense(self.num_classes))
self.classes = ['train', 'boat', 'car', 'airplane']
def tearDown(self):
self.module_patcher.stop()
def test_validate_pred_type_invalid_pred_type(self):
with self.assertRaises(plpy.PLPYException) as error:
self.subject.validate_pred_type(
self.module_name, 'invalid_pred_type', ['cat', 'dog'])
self.assertIn('type', str(error.exception).lower())
def test_validate_class_values_greater_than_1600_class_values(self):
self.model.add(Dense(1599))
with self.assertRaises(plpy.PLPYException) as error:
self.subject.validate_class_values(
self.module_name, range(1599), 'prob', self.model.to_json())
self.assertIn('1600', str(error.exception))
def test_validate_class_values_valid_class_values_prob(self):
self.subject.validate_class_values(
self.module_name, range(self.num_classes), 'prob', self.model.to_json())
self.subject.validate_class_values(
self.module_name, None, 'prob', self.model.to_json())
def test_validate_class_values_valid_pred_type_valid_class_values_response(self):
self.subject.validate_class_values(
self.module_name, range(self.num_classes), 'response', self.model.to_json())
self.subject.validate_class_values(
self.module_name, None, 'response', self.model.to_json())
def test_validate_input_shape_shapes_do_not_match(self):
# minibatched data
self.plpy_mock_execute.return_value = [{'shape': [1,3,32,32]}]
with self.assertRaises(plpy.PLPYException):
self.subject.validate_input_shape(
self.test_table, self.ind_var, [32,32,3], 2, True)
# non-minibatched data
self.plpy_mock_execute.return_value = [{'n_0': 1,'n_1': 32,'n_2': 32,'n_3': 3}]
with self.assertRaises(plpy.PLPYException):
self.subject.validate_input_shape(
self.test_table, self.ind_var, [32,32,3], 1)
self.plpy_mock_execute.return_value = [{'n_0': 1,'n_1': 3}]
with self.assertRaises(plpy.PLPYException):
self.subject.validate_input_shape(
self.test_table, self.ind_var, [3,32], 1)
def test_validate_input_shape_shapes_match(self):
# minibatched data
self.plpy_mock_execute.return_value = [{'shape': [1,32,32,3]}]
self.subject.validate_input_shape(
self.test_table, self.ind_var, [32,32,3], 2, True)
# non-minibatched data
self.plpy_mock_execute.return_value = [{'n_0': 32,'n_1': 32,'n_2': 3}]
self.subject.validate_input_shape(
self.test_table, self.ind_var, [32,32,3], 1)
def test_validate_model_arch_table_none_values(self):
with self.assertRaises(plpy.PLPYException) as error:
obj = self.subject.validate_model_arch_table(
self.module_name, None, self.model_id)
self.assertIn('null', str(error.exception).lower())
self.module.input_tbl_valid = Mock()
with self.assertRaises(plpy.PLPYException) as error:
obj = self.subject.validate_model_arch_table(
self.module_name, self.model_arch_table, None)
self.assertIn('id', str(error.exception).lower())
def test_validate_gpu_config_with_gpu_all_segments(self):
self.plpy_mock_execute.return_value = [{'__internal_gpu_config__': 'all_segments'}]
obj = self.subject._validate_gpu_config(self.module_name, 'foo', [1])
def test_validate_gpu_config_no_gpu_all_segments(self):
self.plpy_mock_execute.return_value = [{'__internal_gpu_config__': 'all_segments'}]
with self.assertRaises(plpy.PLPYException) as error:
obj = self.subject._validate_gpu_config(self.module_name, 'foo', [0])
self.assertIn('missing gpus', str(error.exception).lower())
def test_validate_gpu_config_with_gpu_valid_seg_list(self):
self.plpy_mock_execute.return_value = [{'__internal_gpu_config__': [0,1]}]
obj = self.subject._validate_gpu_config(self.module_name, 'foo', [1,1,0,1])
def test_validate_gpu_config_with_gpu_invalid_seg_list(self):
self.plpy_mock_execute.return_value = [{'__internal_gpu_config__': [0,1]}]
with self.assertRaises(plpy.PLPYException) as error:
obj = self.subject._validate_gpu_config(self.module_name, 'foo', [1,0,0,1])
self.assertIn('does not have gpu', str(error.exception).lower())
class MadlibSerializerTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_serializer
self.subject = madlib_keras_serializer
def tearDown(self):
self.module_patcher.stop()
def test_deserialize_image_1d_weights_null_state_returns_none(self):
self.assertEqual(None, self.subject.deserialize_as_image_1d_weights(None))
def test_deserialize_image_1d_weights_returns_not_none(self):
dummy_state = np.array([2,3,4,5,6], dtype=np.float32)
res = self.subject.deserialize_as_image_1d_weights(dummy_state.tostring())
self.assertEqual(2, res[0])
self.assertEqual([3,4,5,6], res[1].tolist())
def test_deserialize_nd_weights_null_input_returns_none(self):
dummy_state = np.array([0,1,2,3,4,5,6], dtype=np.float32)
self.assertEqual(None, self.subject.deserialize_as_nd_weights(dummy_state.tostring(), None))
self.assertEqual(None, self.subject.deserialize_as_nd_weights(None, [1, 2, 3]))
self.assertEqual(None, self.subject.deserialize_as_nd_weights(None, None))
def test_deserialize_nd_weights_valid_input_returns_not_none(self):
dummy_model_weights = np.array([3,4,5], dtype=np.float32)
dummy_model_shape = [(2, 1, 1, 1), (1,)]
res = self.subject.deserialize_as_nd_weights(dummy_model_weights.tostring(),
dummy_model_shape)
self.assertEqual([[[[3.0]]], [[[4.0]]]], res[0].tolist())
self.assertEqual([5], res[1].tolist())
def test_deserialize_nd_weights_invalid_input_fails(self):
# pass an invalid state with missing model weights
invalid_model_weights = np.array([1,2], dtype=np.float32)
dummy_model_shape = [(2, 1, 1, 1), (1,)]
# we expect raise exception because we cannot reshape
# model weights of size 0 into shape (2,2,3,1)
with self.assertRaises(plpy.PLPYException) as error:
self.subject.deserialize_as_nd_weights(invalid_model_weights.tostring(),
dummy_model_shape)
invalid_model_weights = np.array([1,2,3,4], dtype=np.float32)
dummy_model_shape = [(2, 2, 3, 1), (1,)]
# we expect raise exception because we cannot reshape
# model weights of size 2 into shape (2,2,3,1)
with self.assertRaises(plpy.PLPYException) as error:
self.subject.deserialize_as_nd_weights(invalid_model_weights.tostring(),
dummy_model_shape)
invalid_model_weights = np.array([0,1,2,3,4], dtype=np.float32)
dummy_model_shape = [(2, 1), (1,)]
# we expect to raise exception because we cannot reshape
# model weights of size 2 into shape (1,)
with self.assertRaises(plpy.PLPYException) as error:
self.subject.deserialize_as_nd_weights(invalid_model_weights.tostring(),
dummy_model_shape)
def test_serialize_image_nd_weights_none_weights_returns_none(self):
res = self.subject.serialize_state_with_nd_weights(0, None)
self.assertEqual(None , res)
def test_serialize_image_nd_weights_valid_output(self):
res = self.subject.serialize_state_with_nd_weights(0, [np.array([1, 3]),
np.array([4,5])])
self.assertEqual(np.array([0,1,3,4,5], dtype=np.float32).tostring(),
res)
def test_serialize_image_1d_weights_none_weights_returns_none(self):
res = self.subject.serialize_state_with_1d_weights(0, None)
self.assertEqual(None , res)
def test_serialize_image_1d_weights_valid_output(self):
res = self.subject.serialize_state_with_1d_weights(0, np.array([1, 3, 4, 5]))
self.assertEqual(np.array([0,1,3,4,5], dtype=np.float32).tostring(),
res)
class MadlibKerasHelperTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras_helper
self.subject = madlib_keras_helper
self.input_data = [32, 32, 3]
def tearDown(self):
self.module_patcher.stop()
def test_expand_input_dims(self):
self.assertEqual(np.array(self.input_data).shape, (3,))
res = self.subject.expand_input_dims(self.input_data)
self.assertEqual(res.shape, (1, 3))
def test_strip_trailing_nulls_from_class_values(self):
self.assertEqual(['cat', 'dog'],
self.subject.strip_trailing_nulls_from_class_values(
['cat', 'dog']))
self.assertEqual([None, 'cat', 'dog'],
self.subject.strip_trailing_nulls_from_class_values(
[None, 'cat', 'dog']))
self.assertEqual([None, 'cat', 'dog'],
self.subject.strip_trailing_nulls_from_class_values(
[None, 'cat', 'dog', None, None]))
self.assertEqual(['cat', 'dog'],
self.subject.strip_trailing_nulls_from_class_values(
['cat', 'dog', None, None]))
self.assertEqual([None],
self.subject.strip_trailing_nulls_from_class_values(
[None, None]))
def test_get_gpus_per_one_seg_gpu_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
self.plpy_mock_execute.side_effect = \
[ [],
[ {'hostname': 'mdw0', 'count' : 1}],
[],
[ {'hostname': 'mdw0', 'segment_id' : 0},
{'hostname': 'mdw1', 'segment_id' : 1},
{'hostname': 'mdw2', 'segment_id' : 2}
]]
self.assertEqual([1,0,0], self.subject.get_accessible_gpus_for_seg(
'schema_madlib', 2, 'foo'))
def test_get_gpus_per_mult_seg_gpu_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
self.plpy_mock_execute.side_effect = \
[[],
[ {'hostname': 'mdw0', 'count' : 1}],
[],
[ {'hostname': 'mdw0', 'segment_id' : 0},
{'hostname': 'mdw0', 'segment_id' : 1},
{'hostname': 'mdw1', 'segment_id' : 2},
{'hostname': 'mdw1', 'segment_id' : 3}
]]
self.assertEqual([1,1,0,0], self.subject.get_accessible_gpus_for_seg(
'schema_madlib', 2, 'foo'))
def test_get_gpus_per_no_gpu_gpdb(self):
self.subject.is_platform_pg = Mock(return_value = False)
self.plpy_mock_execute.side_effect = [[],[],[]]
with self.assertRaises(plpy.PLPYException) as error:
self.subject.get_accessible_gpus_for_seg('schema_madlib', 2, 'foo')
self.assertIn('no gpus configured on hosts', str(error.exception).lower())
def test_get_metrics_sql_string(self):
NaN = float('nan')
test_metrics = [ 3.2, NaN, 0.0, None, 8.94, -6.8, 1.2, NaN, NaN ]
py2sql = { x : str(x) for x in test_metrics if type(x) == float }
py2sql[NaN] = "'NaN'::DOUBLE PRECISION"
py2sql[None] = 'NULL'
correct = [ py2sql[x] for x in test_metrics ]
final, metrics = self.subject.get_metrics_sql_string(test_metrics)
m = re.match("\(ARRAY\[(.*)\]\)", metrics)
answers = m.group(1).split(', ')
self.assertListEqual(answers, correct)
self.assertEqual(final, '(' + correct[-1] + ')')
# Check that postgresql parser sees this as a valid sql data type
res = pglint('SELECT ' + final, True)
self.assertEqual(
res,
(True, ''),
"This is not valid PostgresSQL: {}".format('SELECT' + final)
)
# Check that postgresql parser sees this as a valid array
res = pglint('SELECT {}[1]'.format(metrics), True)
self.assertEqual(
res,
(True, ''),
"This is not valid PostgresSQL: SELECT {}[1]".format(metrics)
)
class MadlibKerasEvaluationTestCase(unittest.TestCase):
def setUp(self):
self.plpy_mock = Mock(spec='error')
patches = {
'plpy': plpy
}
self.plpy_mock_execute = MagicMock()
plpy.execute = self.plpy_mock_execute
self.module_patcher = patch.dict('sys.modules', patches)
self.module_patcher.start()
import madlib_keras
self.subject = madlib_keras
self.model = Sequential()
self.model.add(Conv2D(2, kernel_size=(1, 1), activation='relu',
input_shape=(1,1,1,), padding='same'))
self.model.add(Flatten())
self.compile_params = "optimizer=SGD(lr=0.01, decay=1e-6, nesterov=True), loss='categorical_crossentropy', metrics=['accuracy']"
self.model_weights = [3,4,5,6]
self.serialized_weights = np.array(self.model_weights, dtype='float32'
).tostring()
self.loss = 0.5947071313858032
self.accuracy = 1.0
self.dist_key_mapping = [0,1,2]
self.accessible_gpus_for_seg = [0]
#self.model.evaluate = Mock(return_value = [self.loss, self.accuracy])
self.independent_var_real = [[[[0.5]]]] * 10
self.dependent_var_int = [[0,1]] * 10
# Params as bytea
self.independent_var = np.array(self.independent_var_real, dtype=np.float32).tobytes()
self.dependent_var = np.array(self.dependent_var_int, dtype=np.int16).tobytes()
self.independent_var_shape = [10,1,1,1]
self.dependent_var_shape = [10,2]
# We test on segment 0, which has 3 buffers filled with 10 identical
# images each, or 30 images total
self.total_images_per_seg = [3*len(self.dependent_var_int),20,40]
def tearDown(self):
self.module_patcher.stop()
def _test_internal_keras_eval_transition_first_buffer(self, is_platform_pg):
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = 0
ending_image_count = len(self.dependent_var_int)
# last iteration call
k = {'SD' : {}}
state = [0,0,0]
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
self.serialized_weights, self.compile_params, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, True, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# Call set_session once for gpdb (but not for postgres)
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * image_count, agg_accuracy, 4)
# Clear session and sess.close must not get called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue(k['SD']['segment_model'])
# Non-final call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
k = {'SD' : {}}
state = [0,0,0]
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
self.serialized_weights, self.compile_params, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, False, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session must not get called for the first buffer
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * image_count, agg_accuracy, 4)
# Clear session and sess.close must not get called for the first buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
self.assertTrue(k['SD']['segment_model'])
def _test_internal_keras_eval_transition_middle_buffer(self, is_platform_pg):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
# last iteration call
k = {'SD' : {}}
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
state = [self.loss * starting_image_count, self.accuracy * starting_image_count, starting_image_count]
k['SD']['segment_model'] = self.model
k['SD']['sess'] = Mock()
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
'dummy_model_weights', None, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, True, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * ending_image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * ending_image_count, agg_accuracy, 4)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
# Non-last iteration call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
k = {'SD' : {}}
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
state = [self.loss * starting_image_count, self.accuracy * starting_image_count, starting_image_count]
k['SD']['segment_model'] = self.model
k['SD']['sess'] = Mock()
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
'dummy_model_weights', None, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, False, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * ending_image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * ending_image_count, agg_accuracy, 4)
# Clear session and sess.close must not get called for the middle buffer
self.assertEqual(0, self.subject.K.clear_session.call_count)
def _test_internal_keras_eval_transition_last_buffer(self, is_platform_pg):
#TODO should we mock tensorflow's close_session and keras'
# clear_session instead of mocking the function `K.clear_session`
self.subject.K.set_session = Mock()
self.subject.K.clear_session = Mock()
self.subject.is_platform_pg = Mock(return_value = is_platform_pg)
starting_image_count = 2*len(self.dependent_var_int)
ending_image_count = starting_image_count + len(self.dependent_var_int)
k = {'SD' : {}}
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
state = [self.loss * starting_image_count,
self.accuracy * starting_image_count,
starting_image_count]
k['SD']['segment_model'] = self.model
k['SD']['sess'] = Mock()
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
'dummy_model_weights', None, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, True, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * ending_image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * ending_image_count, agg_accuracy, 4)
# Clear session and sess.close must get called for the last buffer in gpdb,
# but not in postgres
self.assertEqual(1, self.subject.K.clear_session.call_count)
# Non-final call
self.subject.K.set_session.reset_mock()
self.subject.K.clear_session.reset_mock()
k = {'SD' : {}}
self.subject.compile_and_set_weights(self.model, self.compile_params,
'/cpu:0', self.serialized_weights)
state = [self.loss * starting_image_count,
self.accuracy * starting_image_count,
starting_image_count]
k['SD']['segment_model'] = self.model
k['SD']['sess'] = Mock()
new_state = self.subject.internal_keras_eval_transition(
state, self.dependent_var , self.independent_var,
self.dependent_var_shape, self.independent_var_shape,
self.model.to_json(),
'dummy_model_weights', None, 0,
self.dist_key_mapping, 0, 4,
self.total_images_per_seg, False, self.accessible_gpus_for_seg, False, **k)
agg_loss, agg_accuracy, image_count = new_state
self.assertEqual(ending_image_count, image_count)
# set_session is always called
self.assertEqual(1, self.subject.K.set_session.call_count)
# loss and accuracy should be unchanged
self.assertAlmostEqual(self.loss * ending_image_count, agg_loss, 4)
self.assertAlmostEqual(self.accuracy * ending_image_count, agg_accuracy, 4)
# Clear session and sess.close must not get called in non-final iterations
self.assertEqual(0, self.subject.K.clear_session.call_count)
def test_internal_keras_eval_transition_first_buffer_pg(self):
self._test_internal_keras_eval_transition_first_buffer(True)
def test_internal_keras_eval_transition_first_buffer_gpdb(self):
self._test_internal_keras_eval_transition_first_buffer(False)
def test_internal_keras_eval_transition_middle_buffer_pg(self):
self._test_internal_keras_eval_transition_middle_buffer(True)
def test_internal_keras_eval_transition_middle_buffer_gpdb(self):
self._test_internal_keras_eval_transition_middle_buffer(False)
def test_internal_keras_eval_transition_last_buffer_pg(self):
self._test_internal_keras_eval_transition_last_buffer(True)
def test_internal_keras_eval_transition_last_buffer_gpdb(self):
self._test_internal_keras_eval_transition_last_buffer(False)
def test_internal_keras_eval_merge(self):
image_count = self.total_images_per_seg[0]
state1 = [3.0*self.loss, 3.0*self.accuracy, image_count]
state1 = state1
state2 = [2.0*self.loss, 2.0*self.accuracy, image_count+30]
state2 = state2
merged_state = self.subject.internal_keras_eval_merge(state1,state2)
agg_loss = merged_state[0]
agg_accuracy = merged_state[1]
image_count_total = merged_state[2]
self.assertEqual( 2*image_count+30 , image_count_total )
self.assertAlmostEqual( 5.0*self.loss, agg_loss, 2)
self.assertAlmostEqual( 5.0*self.accuracy, agg_accuracy, 2)
def test_internal_keras_eval_merge_none_first(self):
image_count = self.total_images_per_seg[0]
input_state = [self.loss, self.accuracy, image_count]
merged_state = self.subject.internal_keras_eval_merge(None, input_state)
agg_loss = merged_state[0]
agg_accuracy = merged_state[1]
image_count_total = merged_state[2]
self.assertEqual(image_count, image_count_total)
self.assertAlmostEqual(self.loss, agg_loss, 2)
self.assertAlmostEqual(self.accuracy, agg_accuracy, 2)
def test_internal_keras_eval_merge_none_second(self):
image_count = self.total_images_per_seg[0]
input_state = [self.loss, self.accuracy, image_count]
merged_state = self.subject.internal_keras_eval_merge(input_state, None)
agg_loss = merged_state[0]
agg_accuracy = merged_state[1]
image_count_total = merged_state[2]
self.assertEqual(image_count, image_count_total)
self.assertAlmostEqual(self.loss, agg_loss, 2)
self.assertAlmostEqual(self.accuracy, agg_accuracy, 2)
def test_internal_keras_eval_merge_both_none(self):
result = self.subject.internal_keras_eval_merge(None,None)
self.assertEqual(None, result)
def test_internal_keras_eval_final(self):
image_count = self.total_images_per_seg[0]
input_state = [image_count*self.loss, image_count*self.accuracy, image_count]
output_state = self.subject.internal_keras_eval_final(input_state)
self.assertEqual(len(output_state), 2)
agg_loss = output_state[0]
agg_accuracy = output_state[1]
self.assertAlmostEqual(self.loss, agg_loss,2)
self.assertAlmostEqual(self.accuracy, agg_accuracy,2)
def internal_keras_eval_final_none(self):
result = self.subject.internal_keras_eval_final(None)
self.assertEqual(result, None)
def test_internal_keras_eval_final_image_count_zero(self):
input_state = [0, 0, 0]
with self.assertRaises(plpy.PLPYException):
result = self.subject.internal_keras_eval_final(input_state)
def tearDown(self):
self.module_patcher.stop()
if __name__ == '__main__':
unittest.main()
# ---------------------------------------------------------------------