def build_network(state_dim): state_input = Input((state_dim,)) h1 = Dense(64, activation='relu')(state_input) h2 = Dense(32, activation='relu')(h1) h3 = Dense(16, activation='relu')(h2) v_output = Dense(1, activation='linear')(h3) model = Model(state_input, v_output) #model.summary() model._make_predict_function() # class 안에서 def가 정의되면 필요없음 return model
def build_network(state_dim, action_dim, action_bound): state_input = Input((state_dim, )) h1 = Dense(64, activation='relu')(state_input) h2 = Dense(32, activation='relu')(h1) h3 = Dense(16, activation='relu')(h2) out_mu = Dense(action_dim, activation='tanh')(h3) std_output = Dense(action_dim, activation='softplus')(h3) # Scale output to [-action_bound, action_bound] mu_output = Lambda(lambda x: x * action_bound)(out_mu) model = Model(state_input, [mu_output, std_output]) # model.summary() model._make_predict_function() # class 안에서 def가 정의되면 필요없음 return model
import pickle import numpy as np import datetime import warnings warnings.filterwarnings("ignore") model = load_model('./model_weights/model_9.h5') model._make_predict_function() model_temp = ResNet50(weights="imagenet", input_shape=(224,224,3)) # Create a new model, by removing the last layer (output layer of 1000 classes) from the resnet50 model_resnet = Model(model_temp.input, model_temp.layers[-2].output) model_resnet._make_predict_function() # Load the word_to_idx and idx_to_word from disk with open("./storage/word_to_idx.pkl", "rb") as w2i: word_to_idx = pickle.load(w2i) with open("./storage/idx_to_word.pkl", "rb") as i2w: idx_to_word = pickle.load(i2w) max_len = 35
# Add skip connection fcn20_skip_connected = Add(name="fcn20_plus_vgg_layer4")([fcn20, layer4]) # Upsample again fcn21 = Conv2DTranspose(filters=2, kernel_size=16, strides=(8, 8), padding='same', name="fcn21", activation="softmax")(fcn20_skip_connected) model1 = Model(inputs=mbl.input, outputs=fcn21) model1.compile(loss="categorical_crossentropy", optimizer='adam', metrics=['accuracy']) model1.load_weights(path + 'model-mobilenetv2-round1' + '.h5') model1._make_predict_function() print("Finish") s2s = SegmentToSteer(roi=0.45, margin=10) pre_turn_left = False pre_turn_right = False obstacle_time = 0.0 rects = [] def callback(data): global end, i_left, i_right, rects, ratio, skip if skip > 0: skip -= 1 return try: # global image, color_image
class HTRModel: def __init__(self, inputs, outputs, greedy=False, beam_width=100, top_paths=1): """ Initialization of a HTR Model. :param inputs: Input layer of the neural network outputs: Last layer of the neural network before CTC (e.g. a TimeDistributed Dense) greedy, beam_width, top_paths: Parameters of the CTC decoding (see ctc decoding tensorflow for more details) """ self.model_train = None self.model_pred = None if not isinstance(inputs, list): self.inputs = [inputs] else: self.inputs = inputs if not isinstance(outputs, list): self.outputs = [outputs] else: self.outputs = outputs self.greedy = greedy self.beam_width = beam_width self.top_paths = top_paths def summary(self, output=None, target=None): """Show/Save model structure (summary)""" if target is not None: os.makedirs(output, exist_ok=True) with open(os.path.join(output, target), "w") as f: with redirect_stdout(f): self.model_train.summary() self.model_train.summary() def load_checkpoint(self, target): """ Load a model with checkpoint file""" if os.path.isfile(target): if self.model_train is None: self.compile() self.model_train.load_weights(target, by_name=True) self.model_pred.load_weights(target, by_name=True) def get_callbacks(self, logdir, hdf5, monitor="val_loss", verbose=0): """Setup the list of callbacks for the model""" callbacks = [ CSVLogger(filename=os.path.join(logdir, "epochs.log"), separator=";", append=True), TensorBoard(log_dir=logdir, histogram_freq=10, profile_batch=0, write_graph=True, write_images=False, update_freq="epoch"), ModelCheckpoint(filepath=os.path.join(logdir, hdf5), monitor=monitor, save_best_only=True, save_weights_only=True, verbose=verbose), EarlyStopping(monitor=monitor, min_delta=0, patience=20, restore_best_weights=True, verbose=verbose), ReduceLROnPlateau(monitor=monitor, min_delta=0, factor=0.2, patience=10, verbose=verbose) ] return callbacks def compile(self, optimizer): """ Configures the HTR Model for training. There is 2 Tensorflow Keras models: - one for training - one for predicting/evaluate Lambda layers are used to compute: - the CTC loss function - the CTC decoding :param optimizer: The optimizer used during training """ # Others inputs for the CTC approach labels = Input(name="labels", shape=[None]) input_length = Input(name="input_length", shape=[1]) label_length = Input(name="label_length", shape=[1]) # Lambda layer for computing the loss function loss_out = Lambda(self.ctc_loss_lambda_func, output_shape=(1, ), name="CTCloss")(self.outputs + [labels, input_length, label_length]) # Lambda layer for the decoding function out_decoded_dense = Lambda(self.ctc_complete_decoding_lambda_func, output_shape=(None, None), name="CTCdecode", arguments={ "greedy": self.greedy, "beam_width": self.beam_width, "top_paths": self.top_paths }, dtype="float32")(self.outputs + [input_length]) # create Tensorflow Keras models self.model_train = Model(inputs=self.inputs + [labels, input_length, label_length], outputs=loss_out) self.model_pred = Model(inputs=self.inputs + [input_length], outputs=out_decoded_dense) # Compile models self.model_train.compile(loss={ "CTCloss": lambda yt, yp: yp }, optimizer=optimizer) self.model_pred.compile(loss={ "CTCdecode": lambda yt, yp: yp }, optimizer=optimizer) def fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_queue_size=10, workers=1, shuffle=True, initial_epoch=0): """ Model training on data yielded batch-by-batch by a Python generator. The generator is run in parallel to the model, for efficiency. For instance, this allows you to do real-time data augmentation on images on CPU in parallel to training your model on GPU. A major modification concerns the generator that must provide x data of the form: [input_sequences, label_sequences, inputs_lengths, labels_length] (in a similar way than for using CTC in tensorflow) :param: See tensorflow.keras.engine.Model.fit_generator() :return: A History object """ out = self.model_train.fit_generator(generator, steps_per_epoch, epochs=epochs, verbose=verbose, callbacks=callbacks, validation_data=validation_data, validation_steps=validation_steps, class_weight=class_weight, max_queue_size=max_queue_size, workers=workers, shuffle=shuffle, initial_epoch=initial_epoch) self.model_pred.set_weights(self.model_train.get_weights()) return out def predict_generator(self, generator, steps, max_queue_size=10, workers=1, use_multiprocessing=False, verbose=0): """Generates predictions for the input samples from a data generator. The generator should return the same kind of data as accepted by `predict_on_batch`. generator = DataGenerator class that returns: x = Input data as a 3D Tensor (batch_size, max_input_len, dim_features) x_len = 1D array with the length of each data in batch_size # Arguments generator: Generator yielding batches of input samples or an instance of Sequence (tensorflow.keras.utils.Sequence) object in order to avoid duplicate data when using multiprocessing. steps: Total number of steps (batches of samples) to yield from `generator` before stopping. max_queue_size: Maximum size for the generator queue. workers: Maximum number of processes to spin up when using process based threading use_multiprocessing: If `True`, use process based threading. Note that because this implementation relies on multiprocessing, you should not pass non picklable arguments to the generator as they can't be passed easily to children processes. verbose: verbosity mode, 0 or 1. # Returns A numpy array(s) of predictions. # Raises ValueError: In case the generator yields data in an invalid format. """ self.model_pred._make_predict_function() is_sequence = isinstance(generator, Sequence) allab_outs = [] steps_done = 0 enqueuer = None try: if is_sequence: enqueuer = OrderedEnqueuer( generator, use_multiprocessing=use_multiprocessing) else: enqueuer = GeneratorEnqueuer( generator, use_multiprocessing=use_multiprocessing) enqueuer.start(workers=workers, max_queue_size=max_queue_size) output_generator = enqueuer.get() if verbose == 1: progbar = Progbar(target=steps) while steps_done < steps: x = next(output_generator) outs = self.predict_on_batch(x) if not isinstance(outs, list): outs = [outs] for i, out in enumerate(outs): allab_outs.append([int(c) for c in out]) steps_done += 1 if verbose == 1: progbar.update(steps_done) finally: if enqueuer is not None: enqueuer.stop() return allab_outs def predict_on_batch(self, x): """Returns predictions for a single batch of samples. # Arguments x: [Input samples as a Numpy array, Input length as a numpy array] # Returns Numpy array(s) of predictions. """ out = self.model_pred.predict_on_batch(x) output = [[pr for pr in pred if pr != -1] for pred in out] return output def get_loss_on_batch(self, inputs, verbose=0): """ Computation the loss inputs is a list of 4 elements: x_features, y_label, x_len, y_len (similarly to the CTC in tensorflow) :return: Probabilities (output of the TimeDistributedDense layer) """ x = inputs[0] x_len = inputs[2] y = inputs[1] y_len = inputs[3] no_lab = True if 0 in y_len else False if no_lab is False: loss_data = self.model_train.predict_on_batch([x, y, x_len, y_len]) return np.sum(loss_data), loss_data @staticmethod def ctc_loss_lambda_func(args): """ Function for computing the ctc loss (can be put in a Lambda layer) :param args: y_pred, labels, input_length, label_length :return: CTC loss """ y_pred, labels, input_length, label_length = args return K.ctc_batch_cost(labels, y_pred, input_length, label_length) @staticmethod def ctc_complete_decoding_lambda_func(args, **arguments): """ Complete CTC decoding using Tensorflow Keras (function K.ctc_decode) :param args: y_pred, input_length :param arguments: greedy, beam_width, top_paths :return: K.ctc_decode with dtype="float32" """ y_pred, input_length = args my_params = arguments assert (K.backend() == "tensorflow") return K.cast(K.ctc_decode(y_pred, tf.squeeze(input_length), greedy=my_params["greedy"], beam_width=my_params["beam_width"], top_paths=my_params["top_paths"])[0][0], dtype="float32")
class HTRModel: def __init__(self, inputs, outputs, charset, greedy=False, beam_width=100, top_paths=1): """ Initialization of a HTR Model. :param inputs: Input layer of the neural network outputs: Last layer of the neural network before CTC (e.g. a TimeDistributed Dense) greedy, beam_width, top_paths: Parameters of the CTC decoding (see ctc decoding tensorflow for more details) charset: labels related to the input of the CTC approach """ self.model_train = None self.model_pred = None if not isinstance(inputs, list): self.inputs = [inputs] else: self.inputs = inputs if not isinstance(outputs, list): self.outputs = [outputs] else: self.outputs = outputs self.charset = charset self.greedy = greedy self.beam_width = beam_width self.top_paths = top_paths def compile(self, optimizer): """ Configures the HTR Model for training. There is 2 Tensorflow Keras models: - one for training - one for predicting/evaluate Lambda layers are used to compute: - the CTC loss function - the CTC decoding :param optimizer: The optimizer used during training """ # Others inputs for the CTC approach labels = Input(name="labels", shape=[None]) input_length = Input(name="input_length", shape=[1]) label_length = Input(name="label_length", shape=[1]) # Lambda layer for computing the loss function loss_out = Lambda(self.ctc_loss_lambda_func, output_shape=(1,), name="CTCloss")( self.outputs + [labels, input_length, label_length]) # Lambda layer for the decoding function out_decoded_dense = Lambda(self.ctc_complete_decoding_lambda_func, output_shape=(None, None), name="CTCdecode", arguments={"greedy": self.greedy, "beam_width": self.beam_width, "top_paths": self.top_paths}, dtype="float32")(self.outputs + [input_length]) # create Tensorflow Keras models self.model_init = Model(inputs=self.inputs, outputs=self.outputs) self.model_train = Model(inputs=self.inputs + [labels, input_length, label_length], outputs=loss_out) self.model_pred = Model(inputs=self.inputs + [input_length], outputs=out_decoded_dense) # Compile models self.model_train.compile(loss={"CTCloss": lambda yt, yp: yp}, optimizer=optimizer) self.model_pred.compile(loss={"CTCdecode": lambda yt, yp: yp}, optimizer=optimizer) def fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_queue_size=10, workers=1, shuffle=True, initial_epoch=0): """ Model training on data yielded batch-by-batch by a Python generator. The generator is run in parallel to the model, for efficiency. For instance, this allows you to do real-time data augmentation on images on CPU in parallel to training your model on GPU. A major modification concerns the generator that must provide x data of the form: [input_sequences, label_sequences, inputs_lengths, labels_length] (in a similar way than for using CTC in tensorflow) :param: See tensorflow.keras.engine.Model.fit_generator() :return: A History object """ out = self.model_train.fit_generator(generator, steps_per_epoch, epochs=epochs, verbose=verbose, callbacks=callbacks, validation_data=validation_data, validation_steps=validation_steps, class_weight=class_weight, max_queue_size=max_queue_size, workers=workers, shuffle=shuffle, initial_epoch=initial_epoch) self.model_pred.set_weights(self.model_train.get_weights()) return out def predict_generator(self, generator, steps, max_queue_size=10, workers=1, use_multiprocessing=False, verbose=0): """Generates predictions for the input samples from a data generator. The generator should return the same kind of data as accepted by `predict_on_batch`. generator = DataGenerator class that returns: x = Input data as a 3D Tensor (batch_size, max_input_len, dim_features) x_len = 1D array with the length of each data in batch_size # Arguments generator: Generator yielding batches of input samples or an instance of Sequence (tensorflow.keras.utils.Sequence) object in order to avoid duplicate data when using multiprocessing. steps: Total number of steps (batches of samples) to yield from `generator` before stopping. max_queue_size: Maximum size for the generator queue. workers: Maximum number of processes to spin up when using process based threading use_multiprocessing: If `True`, use process based threading. Note that because this implementation relies on multiprocessing, you should not pass non picklable arguments to the generator as they can't be passed easily to children processes. verbose: verbosity mode, 0 or 1. # Returns A numpy array(s) of predictions. # Raises ValueError: In case the generator yields data in an invalid format. """ self.model_pred._make_predict_function() is_sequence = isinstance(generator, Sequence) allab_outs = [] steps_done = 0 enqueuer = None try: if is_sequence: enqueuer = OrderedEnqueuer(generator, use_multiprocessing=use_multiprocessing) else: enqueuer = GeneratorEnqueuer(generator, use_multiprocessing=use_multiprocessing) enqueuer.start(workers=workers, max_queue_size=max_queue_size) output_generator = enqueuer.get() if verbose == 1: progbar = Progbar(target=steps) while steps_done < steps: x = next(output_generator) outs = self.predict_on_batch(x) if not isinstance(outs, list): outs = [outs] for i, out in enumerate(outs): encode = [valab_out for valab_out in out if valab_out != -1] allab_outs.append([int(c) for c in encode]) steps_done += 1 if verbose == 1: progbar.update(steps_done) finally: if enqueuer is not None: enqueuer.stop() return allab_outs def predict_on_batch(self, x): """Returns predictions for a single batch of samples. # Arguments x: [Input samples as a Numpy array, Input length as a numpy array] # Returns Numpy array(s) of predictions. """ out = self.model_pred.predict_on_batch(x) output = [[pr for pr in pred if pr != -1] for pred in out] return output def get_loss_on_batch(self, inputs, verbose=0): """ Computation the loss inputs is a list of 4 elements: x_features, y_label, x_len, y_len (similarly to the CTC in tensorflow) :return: Probabilities (output of the TimeDistributedDense layer) """ x = inputs[0] x_len = inputs[2] y = inputs[1] y_len = inputs[3] no_lab = True if 0 in y_len else False if no_lab is False: loss_data = self.model_train.predict_on_batch([x, y, x_len, y_len]) return np.sum(loss_data), loss_data def save_model(self, path, charset=None): """ Save a model in path save model_train, model_pred in json save inputs and outputs in json save model CTC parameters in a pickle :param path: directory where the model architecture will be saved :param charset: set of labels (useful to keep the label order) """ model_json = self.model_train.to_json() with open(path + "/model_train.json", "w") as json_file: json_file.write(model_json) model_json = self.model_pred.to_json() with open(path + "/model_pred.json", "w") as json_file: json_file.write(model_json) model_json = self.model_init.to_json() with open(path + "/model_init.json", "w") as json_file: json_file.write(model_json) param = {"greedy": self.greedy, "beam_width": self.beam_width, "top_paths": self.top_paths, "charset": self.charset} output = open(path + "/model_param.pkl", "wb") p = pickle.Pickler(output) p.dump(param) output.close() def load_checkpoint(self, target): """ Load a model with checkpoint file""" if os.path.isfile(target): self.model_train.load_weights(target) self.model_pred.set_weights(self.model_train.get_weights()) def load_model(self, path, optimizer, init_archi=True, file_weights=None, change_parameters=False, init_last_layer=False, add_layers=None, trainable=False, removed_layers=2): """ Load a model in path load model_train, model_pred from json load inputs and outputs from json load model CTC parameters from a pickle :param path: directory where the model is saved :param optimizer: The optimizer used during training :param init_archi: load an architecture from json. Otherwise, the network archtiecture muste be initialized. :param file_weights: weights to load (None = default parameters are returned). :param init_last_layer: reinitialize the last layer using self.charset to get the number of labels. :param add_layers: add some layers. None for no change in the network architecture. Otherwise, add_layers contains a list of layers to add after the last layer of the current architecture. :param trainable: in case of add_layers, lower layers can be not trained again. :param removed_layers: remove the last layers of the current architecture. It is applied before adding new layers using add_layers. """ if init_archi: json_file = open(path + "/model_train.json", "r") loaded_model_json = json_file.read() json_file.close() self.model_train = model_from_json(loaded_model_json) json_file = open(path + "/model_pred.json", "r") loaded_model_json = json_file.read() json_file.close() self.model_pred = model_from_json(loaded_model_json, custom_objects={"tf": tf}) json_file = open(path + "/model_init.json", "r") loaded_model_json = json_file.read() json_file.close() self.model_init = model_from_json(loaded_model_json, custom_objects={"tf": tf}) self.inputs = self.model_init.inputs self.outputs = self.model_init.outputs input = open(path + "/model_param.pkl", "rb") p = pickle.Unpickler(input) param = p.load() input.close() if not change_parameters: self.greedy = param["greedy"] if "greedy" in param.keys() else self.greedy self.beam_width = param["beam_width"] if "beam_width" in param.keys() else self.beam_width self.top_paths = param["top_paths"] if "top_paths" in param.keys() else self.top_paths self.charset = param["charset"] if "charset" in param.keys() and self.charset is None else self.charset self.compile(optimizer) if file_weights is not None: if os.path.exists(file_weights): self.model_train.load_weights(file_weights) self.model_pred.set_weights(self.model_train.get_weights()) elif os.path.exists(path + file_weights): self.model_train.load_weights(path + file_weights) self.model_pred.set_weights(self.model_train.get_weights()) # add layers after transfer if add_layers is not None: labels = Input(name="labels", shape=[None]) input_length = Input(name="input_length", shape=[1]) label_length = Input(name="label_length", shape=[1]) new_layer = Input(name="input", shape=self.model_init.layers[0].output_shape[1:]) self.inputs = [new_layer] for layer in self.model_init.layers[1:-removed_layers]: print(layer) new_layer = layer(new_layer) layer.trainable = trainable for layer in add_layers: new_layer = layer(new_layer) layer.trainable = True self.outputs = [new_layer] loss_out = Lambda(self.ctc_loss_lambda_func, output_shape=(1,), name="CTCloss")( self.outputs + [labels, input_length, label_length]) # Lambda layer for the decoding function out_decoded_dense = Lambda(self.ctc_complete_decoding_lambda_func, output_shape=(None, None), name="CTCdecode", arguments={"greedy": self.greedy, "beam_width": self.beam_width, "top_paths": self.top_paths}, dtype="float32")( self.outputs + [input_length]) # create Tensorflow Keras models self.model_init = Model(inputs=self.inputs, outputs=self.outputs) self.model_train = Model(inputs=self.inputs + [labels, input_length, label_length], outputs=loss_out) self.model_pred = Model(inputs=self.inputs + [input_length], outputs=out_decoded_dense) # Compile models self.model_train.compile(loss={"CTCloss": lambda yt, yp: yp}, optimizer=optimizer) self.model_pred.compile(loss={"CTCdecode": lambda yt, yp: yp}, optimizer=optimizer) elif init_last_layer: labels = Input(name="labels", shape=[None]) input_length = Input(name="input_length", shape=[1]) label_length = Input(name="label_length", shape=[1]) new_layer = Input(name="input", shape=self.model_init.layers[0].output_shape[1:]) self.inputs = [new_layer] for layer in self.model_init.layers[1:-2]: new_layer = layer(new_layer) new_layer = TimeDistributed(Dense(len(self.charset) + 1), name="DenseSoftmax")(new_layer) new_layer = Activation("softmax", name="Softmax")(new_layer) self.outputs = [new_layer] # Lambda layer for computing the loss function loss_out = Lambda(self.ctc_loss_lambda_func, output_shape=(1,), name="CTCloss")( self.outputs + [labels, input_length, label_length]) # Lambda layer for the decoding function out_decoded_dense = Lambda(self.ctc_complete_decoding_lambda_func, output_shape=(None, None), name="CTCdecode", arguments={"greedy": self.greedy, "beam_width": self.beam_width, "top_paths": self.top_paths}, dtype="float32")( self.outputs + [input_length]) # create Tensorflow Keras models self.model_init = Model(inputs=self.inputs, outputs=self.outputs) self.model_train = Model(inputs=self.inputs + [labels, input_length, label_length], outputs=loss_out) self.model_pred = Model(inputs=self.inputs + [input_length], outputs=out_decoded_dense) # Compile models self.model_train.compile(loss={"CTCloss": lambda yt, yp: yp}, optimizer=optimizer) self.model_pred.compile(loss={"CTCdecode": lambda yt, yp: yp}, optimizer=optimizer) def summary(self, output=None, target=None): """Show/Save model structure (summary)""" if target is not None: os.makedirs(output, exist_ok=True) with open(os.path.join(output, target), "w") as f: with redirect_stdout(f): self.model_train.summary() self.model_train.summary() @staticmethod def ctc_loss_lambda_func(args): """ Function for computing the ctc loss (can be put in a Lambda layer) :param args: y_pred, labels, input_length, label_length :return: CTC loss """ y_pred, labels, input_length, label_length = args return K.ctc_batch_cost(labels, y_pred, input_length, label_length) @staticmethod def ctc_complete_decoding_lambda_func(args, **arguments): """ Complete CTC decoding using Tensorflow Keras (function K.ctc_decode) :param args: y_pred, input_length :param arguments: greedy, beam_width, top_paths :return: K.ctc_decode with dtype="float32" """ y_pred, input_length = args my_params = arguments assert (K.backend() == "tensorflow") return K.cast(K.ctc_decode(y_pred, tf.squeeze(input_length), greedy=my_params["greedy"], beam_width=my_params["beam_width"], top_paths=my_params["top_paths"])[0][0], dtype="float32")
class Fusion(): def __init__(self): self.IMG_HEIGHT = 150 self.IMG_WIDTH = 150 self.night = False self.image = np.zeros((900, 1600, 3)) self.image_lidar = np.zeros((600, 600, 3)) self.sub = rospy.Subscriber("/cam_front/raw", Image, self.image_cb) self.lidar_sub = rospy.Subscriber("image_lidar", Image, self.lidar_image_cb) self._session = tf.Session() self.bridge = cv_bridge.CvBridge() self.input_image = keras.Input(shape=(self.IMG_HEIGHT, self.IMG_WIDTH, 3)) self.input_lidar = keras.Input(shape=(self.IMG_HEIGHT, self.IMG_WIDTH, 3)) self.x = Conv2D(16, 3, padding='same', activation='relu')(self.input_image) self.output_image = MaxPooling2D()(self.x) self.model_image = keras.Model(inputs=self.input_image, outputs=self.output_image, name='image_input') self.model_image.summary() self.y = Conv2D(16, 3, padding='same', activation='relu')(self.input_lidar) self.output_lidar = MaxPooling2D()(self.y) self.model_lidar = keras.Model(inputs=self.input_lidar, outputs=self.output_lidar, name='lidar_input') self.model_lidar.summary() self.combined = concatenate( [self.model_image.output, self.model_lidar.output]) self.z = Conv2D(32, 3, padding='same', activation='relu')(self.combined) self.z = MaxPooling2D()(self.z) self.z = Conv2D(64, 3, padding='same', activation='relu')(self.z) self.z = MaxPooling2D()(self.z) self.z = Conv2D(16, 3, padding='same', activation='relu')(self.z) self.z = MaxPooling2D()(self.z) self.z = Flatten()(self.z) self.z = Dense(512, activation='relu')(self.z) self.z = Dense(128, activation='relu')(self.z) self.z = Dense(1, activation="linear")(self.z) self.fusion = Model( inputs=[self.model_lidar.input, self.model_image.input], outputs=self.z) #keras.utils.plot_model(fusion, 'fusion.png', show_shapes=True) self.fusion.load_weights('./checkpoints/my_checkpoint') self.fusion.compile( optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) self.fusion.load_weights('./checkpoints/my_checkpoint') self.fusion._make_predict_function() def create_model(self): model = Sequential([ Conv2D(16, 3, padding='same', activation='relu', input_shape=(150, 150, 3)), MaxPooling2D(), Conv2D(32, 3, padding='same', activation='relu'), MaxPooling2D(), Conv2D(64, 3, padding='same', activation='relu'), MaxPooling2D(), Flatten(), Dense(512, activation='relu'), Dense(1) ]) model.compile( optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) return model def image_cb(self, msg): self.image = self.bridge.imgmsg_to_cv2(msg) # if(False): # self.night=True def lidar_image_cb(self, msg): self.image_lidar = np.zeros((600, 600, 3)) self.image_lidar = self.bridge.imgmsg_to_cv2(msg) self.prediction() # if(self.night==False): # self.prediction() # else: # model=self.create_model() # model.load_weights('./checkpoints/lidar_checkpoint') # image_mod_lidar=cv2.resize(self.image_lidar,(150,150)) # val=model.predict(image_mod_lidar.reshape(-1,150,150,3)) # if(val[0][0]>0): # print("person") # else: # print("car") def prediction(self): image_mod = cv2.resize(self.image, (150, 150)) image_mod_lidar = cv2.resize(self.image_lidar, (150, 150)) val = self.fusion.predict([ image_mod.reshape(-1, 150, 150, 3), image_mod_lidar.reshape(-1, 150, 150, 3) ]) if (val[0][0] > 0): print("person") else: print("car")
from keras.applications.resnet50 import ResNet50 from keras.preprocessing import image from keras.applications.resnet50 import preprocess_input from tensorflow.keras.models import Model from keras.models import load_model import numpy as np import pickle model = ResNet50(weights="imagenet", input_shape=(224, 224, 3)) new_model = Model(model.input, model.layers[-2].output) new_model._make_predict_function() with open('term_dict.pickle', 'rb') as handle: vocabulary = pickle.load(handle) model = load_model("model_6.h5") model._make_predict_function() glove_embedding = {} with open("glove.6B.50d.txt", 'r', encoding="utf8") as f: for i in f: ax = i.split() glove_embedding[ax[0]] = np.array(ax[1:], dtype='float') embedding_dim = 50 import numpy as np def preprocess_img(img_path): img = image.load_img(img_path, target_size=(224, 224)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) return x
class LSTMMorphoAnalysis: def __init__(self, language: str): self.language = language # type: str self.morph = MorphAnalyzer() if language == "ru" else None # type: MorphAnalyzer self.converter = converters.converter('opencorpora-int', 'ud14') if self.language == "ru" else None self.grammeme_vectorizer_input = GrammemeVectorizer() # type: GrammemeVectorizer self.grammeme_vectorizer_output = GrammemeVectorizer() # type: GrammemeVectorizer self.word_vocabulary = WordVocabulary() # type: WordVocabulary self.char_set = "" # type: str self.train_model = None # type: Model self.eval_model = None # type: Model def prepare(self, gram_dump_path_input: str, gram_dump_path_output: str, word_vocabulary_dump_path: str, char_set_dump_path: str, file_names: List[str] = None) -> None: """ Подготовка векторизатора грамматических значений и словаря слов по корпусу. """ if os.path.exists(gram_dump_path_input): self.grammeme_vectorizer_input.load(gram_dump_path_input) if os.path.exists(gram_dump_path_output): self.grammeme_vectorizer_output.load(gram_dump_path_output) if os.path.exists(word_vocabulary_dump_path): self.word_vocabulary.load(word_vocabulary_dump_path) if os.path.exists(char_set_dump_path): with open(char_set_dump_path, 'r', encoding='utf-8') as f: self.char_set = f.read().rstrip() if self.grammeme_vectorizer_input.is_empty() or \ self.grammeme_vectorizer_output.is_empty() or \ self.word_vocabulary.is_empty() or\ not self.char_set: loader = Loader(self.language) loader.parse_corpora(file_names) self.grammeme_vectorizer_input = loader.grammeme_vectorizer_input self.grammeme_vectorizer_input.save(gram_dump_path_input) self.grammeme_vectorizer_output = loader.grammeme_vectorizer_output self.grammeme_vectorizer_output.save(gram_dump_path_output) self.word_vocabulary = loader.word_vocabulary self.word_vocabulary.save(word_vocabulary_dump_path) self.char_set = loader.char_set with open(char_set_dump_path, 'w', encoding='utf-8') as f: f.write(self.char_set) def save(self, model_config_path: str, model_weights_path: str, eval_model_config_path: str, eval_model_weights_path: str): if self.eval_model is not None: with open(eval_model_config_path, "w", encoding='utf-8') as f: f.write(self.eval_model.to_yaml()) self.eval_model.save_weights(eval_model_weights_path) if self.train_model is not None: with open(model_config_path, "w", encoding='utf-8') as f: f.write(self.train_model.to_yaml()) self.train_model.save_weights(model_weights_path) def load_train(self, config: BuildModelConfig, model_config_path: str=None, model_weights_path: str=None): with open(model_config_path, "r", encoding='utf-8') as f: if config.use_crf: from tensorflow.keras_contrib.layers import CRF custom_objects = {'ReversedLSTM': ReversedLSTM, 'CRF': CRF} self.train_model = model_from_yaml(f.read(), custom_objects=custom_objects) else: custom_objects = {'ReversedLSTM': ReversedLSTM} self.train_model = model_from_yaml(f.read(), custom_objects=custom_objects) self.train_model.load_weights(model_weights_path) loss = {} metrics = {} if config.use_crf: out_layer_name = 'crf' offset = 0 if config.use_pos_lm: offset += 2 if config.use_word_lm: offset += 2 loss[out_layer_name] = self.train_model.layers[-1-offset].loss_function metrics[out_layer_name] = self.train_model.layers[-1-offset].accuracy else: out_layer_name = 'main_pred' loss[out_layer_name] = 'sparse_categorical_crossentropy' metrics[out_layer_name] = 'accuracy' if config.use_pos_lm: prev_layer_name = 'shifted_pred_prev' next_layer_name = 'shifted_pred_next' loss[prev_layer_name] = loss[next_layer_name] = 'sparse_categorical_crossentropy' metrics[prev_layer_name] = metrics[next_layer_name] = 'accuracy' self.train_model.compile(Adam(clipnorm=5.), loss=loss, metrics=metrics) self.eval_model = Model(inputs=self.train_model.inputs, outputs=self.train_model.outputs[0]) def load_eval(self, config: BuildModelConfig, eval_model_config_path: str, eval_model_weights_path: str) -> None: with open(eval_model_config_path, "r", encoding='utf-8') as f: if config.use_crf: from tensorflow.keras_contrib.layers import CRF custom_objects = {'ReversedLSTM': ReversedLSTM, 'CRF': CRF} self.eval_model = model_from_yaml(f.read(), custom_objects=custom_objects) else: custom_objects = {'ReversedLSTM': ReversedLSTM} self.eval_model = model_from_yaml(f.read(), custom_objects=custom_objects) self.eval_model.load_weights(eval_model_weights_path) self.eval_model._make_predict_function() def build(self, config: BuildModelConfig, word_embeddings=None): """ Описание модели. :param config: конфиг модели. :param word_embeddings: матрица словных эмбеддингов. """ inputs = [] embeddings = [] if config.use_word_embeddings and word_embeddings is not None: words = Input(shape=(None,), name='words') word_vocabulary_size = word_embeddings.size.shape[0] word_embeddings_dim = word_embeddings.size.shape[1] words_embedding = Embedding(word_vocabulary_size, word_embeddings_dim, name='word_embeddings')(words) embeddings.append(words_embedding) if config.use_gram: grammemes_input = Input(shape=(None, self.grammeme_vectorizer_input.grammemes_count()), name='grammemes') grammemes_embedding = Dropout(config.gram_dropout)(grammemes_input) grammemes_embedding = Dense(config.gram_hidden_size, activation='relu')(grammemes_embedding) inputs.append(grammemes_input) embeddings.append(grammemes_embedding) if config.use_chars: chars_input = Input(shape=(None, config.char_max_word_length), name='chars') char_layer = build_dense_chars_layer( max_word_length=config.char_max_word_length, char_vocab_size=len(self.char_set)+1, char_emb_dim=config.char_embedding_dim, hidden_dim=config.char_function_hidden_size, output_dim=config.char_function_output_size, dropout=config.char_dropout) if config.use_trained_char_embeddings: char_layer = get_char_model( char_layer=char_layer, max_word_length=config.char_max_word_length, embeddings=word_embeddings, model_config_path=config.char_model_config_path, model_weights_path=config.char_model_weights_path, vocabulary=self.word_vocabulary, char_set=self.char_set) chars_embedding = char_layer(chars_input) inputs.append(chars_input) embeddings.append(chars_embedding) if len(embeddings) > 1: layer = concatenate(embeddings, name="LSTM_input") else: layer = embeddings[0] lstm_input = Dense(config.rnn_input_size, activation='relu')(layer) lstm_forward_1 = LSTM(config.rnn_hidden_size, dropout=config.rnn_dropout, recurrent_dropout=config.rnn_dropout, return_sequences=True, name='LSTM_1_forward')(lstm_input) lstm_backward_1 = ReversedLSTM(config.rnn_hidden_size, dropout=config.rnn_dropout, recurrent_dropout=config.rnn_dropout, return_sequences=True, name='LSTM_1_backward')(lstm_input) layer = concatenate([lstm_forward_1, lstm_backward_1], name="BiLSTM_input") for i in range(config.rnn_n_layers-1): layer = Bidirectional(LSTM( config.rnn_hidden_size, dropout=config.rnn_dropout, recurrent_dropout=config.rnn_dropout, return_sequences=True, name='LSTM_'+str(i)))(layer) layer = TimeDistributed(Dense(config.dense_size))(layer) layer = TimeDistributed(Dropout(config.dense_dropout))(layer) layer = TimeDistributed(BatchNormalization())(layer) layer = TimeDistributed(Activation('relu'))(layer) outputs = [] loss = {} metrics = {} num_of_classes = self.grammeme_vectorizer_output.size() + 1 if config.use_crf: from tensorflow.keras_contrib.layers import CRF out_layer_name = 'crf' crf_layer = CRF(num_of_classes, sparse_target=True, name=out_layer_name) outputs.append(crf_layer(layer)) loss[out_layer_name] = crf_layer.loss_function metrics[out_layer_name] = crf_layer.accuracy else: out_layer_name = 'main_pred' outputs.append(Dense(num_of_classes, activation='softmax', name=out_layer_name)(layer)) loss[out_layer_name] = 'sparse_categorical_crossentropy' metrics[out_layer_name] = 'accuracy' if config.use_pos_lm: prev_layer_name = 'shifted_pred_prev' next_layer_name = 'shifted_pred_next' prev_layer = Dense(num_of_classes, activation='softmax', name=prev_layer_name) next_layer = Dense(num_of_classes, activation='softmax', name=next_layer_name) outputs.append(prev_layer(Dense(config.dense_size, activation='relu')(lstm_backward_1))) outputs.append(next_layer(Dense(config.dense_size, activation='relu')(lstm_forward_1))) loss[prev_layer_name] = loss[next_layer_name] = 'sparse_categorical_crossentropy' metrics[prev_layer_name] = metrics[next_layer_name] = 'accuracy' if config.use_word_lm: out_layer_name = 'out_embedding' out_embedding = Dense(word_embeddings.shape[0], weights=[word_embeddings.T, np.zeros(word_embeddings.shape[0])], activation='softmax', name=out_layer_name, trainable=False) outputs.append(out_embedding(Dense(word_embeddings.shape[1], activation='relu')(lstm_backward_1))) outputs.append(out_embedding(Dense(word_embeddings.shape[1], activation='relu')(lstm_forward_1))) loss[out_layer_name] = 'sparse_categorical_crossentropy' metrics[out_layer_name] = 'accuracy' self.train_model = Model(inputs=inputs, outputs=outputs) self.train_model.compile(Adam(clipnorm=5.), loss=loss, metrics=metrics) self.eval_model = Model(inputs=inputs, outputs=outputs[0]) print(self.train_model.summary()) def train(self, file_names: List[str], train_config: TrainConfig, build_config: BuildModelConfig) -> None: np.random.seed(train_config.random_seed) sample_counter = self.count_samples(file_names) train_idx, val_idx = self.get_split(sample_counter, train_config.val_part) for big_epoch in range(train_config.epochs_num): print('------------Big Epoch {}------------'.format(big_epoch)) batch_generator = BatchGenerator( language=self.language, file_names=file_names, config=train_config, grammeme_vectorizer_input=self.grammeme_vectorizer_input, grammeme_vectorizer_output=self.grammeme_vectorizer_output, build_config=build_config, indices=train_idx, word_vocabulary=self.word_vocabulary, char_set=self.char_set) for epoch, (inputs, target) in enumerate(batch_generator): self.train_model.fit(inputs, target, batch_size=train_config.batch_size, epochs=1, verbose=2) if epoch != 0 and epoch % train_config.dump_model_freq == 0: self.save(train_config.train_model_config_path, train_config.train_model_weights_path, train_config.eval_model_config_path, train_config.eval_model_weights_path) self.evaluate( file_names=file_names, val_idx=val_idx, train_config=train_config, build_config=build_config) @staticmethod def count_samples(file_names: List[str]): """ Считает количество предложений в выборке. :param file_names: файлы выборки. :return: количество предложений. """ sample_counter = 0 for filename in file_names: with open(filename, "r", encoding='utf-8') as f: for line in f: line = line.strip() if len(line) == 0: sample_counter += 1 return sample_counter @staticmethod def get_split(sample_counter: int, val_part: float) -> Tuple[np.array, np.array]: """ Выдаёт индексы предложений, которые становятся train или val выборкой. :param sample_counter: количество предложений. :param val_part: часть выборки, которая станет val. :return: индексы выборок. """ perm = np.random.permutation(sample_counter) border = int(sample_counter * (1 - val_part)) train_idx = perm[:border] val_idx = perm[border:] return train_idx, val_idx def evaluate(self, file_names, val_idx, train_config: TrainConfig, build_config: BuildModelConfig) -> None: """ Оценка на val выборке. :param file_names: файлы выборки. :param val_idx: val индексы. :param train_config: конфиг обучения. :param build_config: конфиг модели. """ word_count = 0 word_errors = 0 sentence_count = 0 sentence_errors = 0 batch_generator = BatchGenerator( language=self.language, file_names=file_names, config=train_config, grammeme_vectorizer_input=self.grammeme_vectorizer_input, grammeme_vectorizer_output=self.grammeme_vectorizer_output, build_config=build_config, indices=val_idx, word_vocabulary=self.word_vocabulary, char_set=self.char_set) for epoch, (inputs, target) in enumerate(batch_generator): predicted_y = self.eval_model.predict(inputs, batch_size=train_config.batch_size, verbose=0) for i, sentence in enumerate(target[0]): sentence_has_errors = False count_zero = sum([1 for num in sentence if num == [0]]) real_sentence_tags = sentence[count_zero:] answer = [] for grammeme_probs in predicted_y[i][count_zero:]: num = np.argmax(grammeme_probs) answer.append(num) for tag, predicted_tag in zip(real_sentence_tags, answer): tag = tag[0] word_count += 1 if tag != predicted_tag: word_errors += 1 sentence_has_errors = True sentence_count += 1 if sentence_has_errors: sentence_errors += 1 print("Word accuracy: ", 1.0 - float(word_errors) / word_count) print("Sentence accuracy: ", 1.0 - float(sentence_errors) / sentence_count) def predict_probabilities(self, sentences: List[List[str]], batch_size: int, build_config: BuildModelConfig) -> List[List[List[float]]]: """ Предсказание полных PoS-тегов по предложению с вероятностями всех вариантов. :param sentences: массив предложений (которые являются массивом слов). :param build_config: конфиг архитектуры модели. :param batch_size: размер батча. :return: вероятности тегов. """ max_sentence_len = max([len(sentence) for sentence in sentences]) if max_sentence_len == 0: return [[] for _ in sentences] n_samples = len(sentences) words = np.zeros((n_samples, max_sentence_len), dtype=np.int) grammemes = np.zeros((n_samples, max_sentence_len, self.grammeme_vectorizer_input.grammemes_count()), dtype=np.float) chars = np.zeros((n_samples, max_sentence_len, build_config.char_max_word_length), dtype=np.int) for i, sentence in enumerate(sentences): if not sentence: continue word_indices, gram_vectors, char_vectors = BatchGenerator.get_sample( sentence, language=self.language, converter=self.converter, morph=self.morph, grammeme_vectorizer=self.grammeme_vectorizer_input, max_word_len=build_config.char_max_word_length, word_vocabulary=self.word_vocabulary, word_count=build_config.word_max_count, char_set=self.char_set) words[i, -len(sentence):] = word_indices grammemes[i, -len(sentence):] = gram_vectors chars[i, -len(sentence):] = char_vectors inputs = [] if build_config.use_word_embeddings: inputs.append(words) if build_config.use_gram: inputs.append(grammemes) if build_config.use_chars: inputs.append(chars) with sess.as_default(): with graph.as_default() as g: return self.eval_model.predict(inputs, batch_size=batch_size)
class Brain: MIN_BATCH = 25 def __init__(self, flags, summary_writer): self.lr = flags.learning_rate self.er = flags.entropy_rate self.flags = flags self.summary_writer = summary_writer self.N_STEP_RETURN = 40 self.GAMMA = .99 self.LAMBDA = 1 self.eps = .2 self.ssize = 32 self.isize = len(U.useful_actions) self.custom_input_size = 1 + len(U.useful_actions) self.stop_signal = False self.lock_queue = threading.Lock() self.train_queue = [[], [], [], [], [], [], [], []] self.counter_lock = threading.Lock() self.training_counter = 0 config = tf.ConfigProto(allow_soft_placement=True) config.gpu_options.allow_growth = True self.session = tf.Session(config=config) K.set_session(self.session) K.manual_variable_initialization(True) self.build_net('/gpu:0') self.build_model('/gpu:0') self.session.run(tf.global_variables_initializer()) self.default_graph = tf.get_default_graph() self.default_graph.finalize() self.summary_writer.add_graph(self.default_graph) # self.debug = np.array([]) def stop(self): self.stop_signal = True def getPredictFeedDict(self, obs, hState, cState): screen = np.array(obs.observation['feature_screen'], dtype=np.float32) screen = np.expand_dims(U.preprocess_screen(screen), axis=0) info = np.zeros([1, len(U.useful_actions)], dtype=np.float32) info[0, U.compressActions(obs.observation['available_actions'])] = 1 custom_inputs = np.expand_dims( np.array(obs.observation.custom_inputs, dtype=np.float32), axis=0) hState = np.expand_dims(np.array(hState), axis=0) cState = np.expand_dims(np.array(cState), axis=0) return { self.screen: screen, self.info: info, self.custom_inputs: custom_inputs, self.hStateInput: hState, self.cStateInput: cState } def getTrainFeedDict(self, obs, action, attributed_act_id): screen = np.array(obs.observation['feature_screen'], dtype=np.float32) screen = U.preprocess_screen(screen) info = np.zeros([len(U.useful_actions)], dtype=np.float32) info[U.compressActions(obs.observation['available_actions'])] = 1 valid_spatial_action = 0 valid_action = np.zeros([len(U.useful_actions)], dtype=np.float32) custom_inputs = np.array(obs.observation.custom_inputs, dtype=np.float32) act_id = action.function net_act_id = attributed_act_id act_args = action.arguments player_relative = obs.observation.feature_screen.player_relative valid_actions = obs.observation["available_actions"] valid_actions = U.compressActions(valid_actions) valid_action[valid_actions] = 1 args = actions.FUNCTIONS[act_id].args for arg, act_arg in zip(args, act_args): if arg.name in ('screen', 'minimap', 'screen2') and (not self.flags.force_focus_fire or (act_id != 12 and act_id != 2)): valid_spatial_action = 1 return { self.screen: screen, # yes self.info: info, # yes self.custom_inputs: custom_inputs, #yes self.valid_spatial_action: valid_spatial_action, #yes self.valid_action: valid_action, # yes } def predict(self, feed): with self.session.as_default(): v, policy, spatialPolicy, hS, cS, _ = self.model.predict([ feed[self.screen], feed[self.info], feed[self.custom_inputs], feed[self.hStateInput], feed[self.cStateInput], ]) return policy, spatialPolicy, v, hS, cS def train(self, feed): feed[self.learning_rate] = self.lr feed[self.entropy_rate] = self.er _, summary = self.session.run([self.train_op, self.summary_op], feed_dict=feed) with self.counter_lock: local_counter = self.training_counter self.training_counter = self.training_counter + 1 if self.flags.use_tensorboard: self.summary_writer.add_summary(summary, local_counter) self.summary_writer.flush() if local_counter % self.flags.snapshot_step == 1 or local_counter >= self.flags.max_train_steps: self.save_model('./snapshot/'+self.flags.map, local_counter) print("Snapshot of model saved at", local_counter) if local_counter >= self.flags.max_train_steps: print("Reached step %d, training complete." % local_counter) self.stop() def add_train(self, batch): with self.lock_queue: for i in range(len(self.train_queue)): self.train_queue[i] = self.train_queue[i] + batch[i] if len(self.train_queue[0]) > (5000 * Brain.MIN_BATCH): print("Training queue too large; optimizer likely crashed") exit() def optimize(self): time.sleep(0.001) with self.lock_queue: if len(self.train_queue[0]) < Brain.MIN_BATCH: return batch = self.train_queue self.train_queue = [[],[],[],[],[],[],[],[]] batch_train_feed = { self.value_target:np.squeeze(np.array(batch[0], dtype=np.float32)), self.screen:np.asarray([x[self.screen] for x in batch[1]],dtype=np.float32), self.info:np.asarray([x[self.info] for x in batch[1]],dtype=np.float32), self.custom_inputs:np.asarray([x[self.custom_inputs] for x in batch[1]],dtype=np.float32), self.valid_spatial_action:np.asarray([x[self.valid_spatial_action] for x in batch[1]],dtype=np.float32), self.valid_action:np.asarray([x[self.valid_action] for x in batch[1]],dtype=np.float32), self.action_selected:np.array(batch[2], dtype=np.float32), self.spatial_action_selected:np.array(batch[3], dtype=np.float32), self.advantage:np.array(batch[4], dtype=np.float32), self.hStateInput:np.array(batch[5], dtype=np.float32), self.cStateInput:np.array(batch[6], dtype=np.float32), self.roach_location:np.array(batch[7], dtype=np.float32) } self.train(batch_train_feed) def getPolicyLoss(self, action_probability, advantage): return -tf.log(action_probability + 1e-10) * advantage def getValueLoss(self, difference): return tf.square(difference) def getEntropy(self, policy, spatial_policy, valid_spatial): return tf.reduce_sum(policy * tf.log(policy + 1e-10), axis=1)# + valid_spatial * tf.reduce_sum(spatial_policy * tf.log(spatial_policy + 1e-10), axis=1) def getMinRoachLoss(self, roach_target, roach_prediction): return K.categorical_crossentropy(roach_target,roach_prediction) def build_model(self, dev): with tf.variable_scope('a3c') and tf.device(dev): self.valid_spatial_action = tf.placeholder( tf.float32, [None], name='valid_spatial_action') self.spatial_action_selected = tf.placeholder( tf.float32, [None, self.ssize**2], name='spatial_action_selected') self.valid_action = tf.placeholder( tf.float32, [None, len(U.useful_actions)], name='valid_action') self.action_selected = tf.placeholder( tf.float32, [None, len(U.useful_actions)], name='action_selected') self.value_target = tf.placeholder( tf.float32, [None], name='value_target') self.entropy_rate = tf.placeholder( tf.float32, None, name='entropy_rate') self.advantage = tf.placeholder(tf.float32, [None], name='advantage') self.learning_rate = tf.placeholder(tf.float32, None, name='learning_rate') self.screen = tf.placeholder( tf.float32, [None, U.screen_channel(), self.ssize, self.ssize], name='screen') self.info = tf.placeholder( tf.float32, [None, self.isize], name='info') self.custom_inputs = tf.placeholder( tf.float32, [None, self.custom_input_size], name='custom_input') self.hStateInput = tf.placeholder( tf.float32, [None, self.NUM_LSTM], name='h_state_input') self.cStateInput = tf.placeholder( tf.float32, [None, self.NUM_LSTM], name='c_state_input') self.roach_location = tf.placeholder( tf.float32, [None, self.ssize ** 2], name='roach_location' ) self.value, self.policy, self.spatial_policy, _, _, self.roachPrediction = self.model([self.screen, self.info, self.custom_inputs, self.hStateInput, self.cStateInput]) # This will get the probability of choosing a valid action. Given that we force it to choose from # the set of valid actions. The probability of an action is the probability the policy chooses # divided by the probability of a valid action valid_action_prob = tf.reduce_sum( self.valid_action * self.policy+1e-10, axis=1) action_prob = tf.reduce_sum( self.action_selected * self.policy+1e-10, axis=1) / valid_action_prob # Here we compute the probability of the spatial action. If the action selected was non spactial, # the probability will be one. # TODO: Make this use vectorized things (using a constant "valid_spatial_action" seems fishy to me, but maybe it's fine) spatial_action_prob = (self.valid_spatial_action * tf.reduce_sum( self.spatial_policy * self.spatial_action_selected, axis=1)) + (1.0 - self.valid_spatial_action)+1e-10 # The probability of the action will be the the product of the non spatial and the spatial prob combined_action_probability = action_prob * spatial_action_prob # The advantage function, which will represent how much better this action was than what was expected from this state policy_loss = self.getPolicyLoss(combined_action_probability, self.advantage) value_loss = self.getValueLoss(self.value_target - self.value) entropy = self.getEntropy( self.policy, self.spatial_policy, self.valid_spatial_action) roachLoss = self.getMinRoachLoss( self.roach_location, self.roachPrediction ) loss = tf.reduce_mean(policy_loss + value_loss * .5 + entropy * .01 + .5 * roachLoss) # Build the optimizer global_step = tf.Variable(0) learning_rate_decayed = tf.train.exponential_decay(self.learning_rate, global_step,10000, .95) opt = tf.train.AdamOptimizer(self.learning_rate) grads, vars = zip(*opt.compute_gradients(loss)) grads, glob_norm = tf.clip_by_global_norm(grads, 40.0) self.train_op = opt.apply_gradients(zip(grads, vars), global_step=global_step) if self.flags.use_tensorboard: summary = [] summary.append(tf.summary.scalar( 'policy_loss', tf.reduce_mean(policy_loss))) summary.append(tf.summary.scalar( 'glob_norm', glob_norm)) summary.append(tf.summary.scalar( 'value_loss', tf.reduce_mean(value_loss))) summary.append(tf.summary.scalar( 'entropy_loss', tf.reduce_mean(entropy))) summary.append(tf.summary.scalar( 'advantage', tf.reduce_mean(self.advantage))) summary.append(tf.summary.scalar( 'loss', tf.reduce_mean(loss))) summary.append(tf.summary.scalar( 'roachLoss', tf.reduce_mean(roachLoss))) self.summary_op = tf.summary.merge(summary) else: self.summary_op = [] self.saver = tf.train.Saver(max_to_keep=100) # debug graph: self.summary_writer.add_graph(self.session.graph) def broadcast(self, nonSpatialInput): nonSpatialInput = K.expand_dims(nonSpatialInput, axis=1) nonSpatialInput = K.expand_dims(nonSpatialInput, axis=2) return K.tile(nonSpatialInput,(1, self.ssize, self.ssize, 1)) def expand_dims(self, x): return K.expand_dims(x, 1) def Squeeze(self, x): return K.squeeze(x,axis=-1) def build_net(self, dev): with tf.variable_scope('a3c') and tf.device(dev): screenInput = Input( shape=(U.screen_channel(), self.ssize, self.ssize), name='screenInput', ) permutedScreenInput = Permute((2,3,1))(screenInput) conv1 = Conv2D(16, kernel_size=5, strides=(1,1), padding='same',name='conv1')(permutedScreenInput) conv2 = Conv2D(32, kernel_size=3, strides=(1,1), padding='same',name='conv2')(conv1) infoInput = Input( shape=(self.isize,), name='infoInput', ) customInput = Input( shape=(self.custom_input_size,), name='customInput', ) nonSpatialInput = Concatenate(name='nonSpatialInputConcat')([infoInput, customInput]) broadcasted = Lambda(self.broadcast,name='broadcasting')(nonSpatialInput) combinedSpatialNonSpatial = Concatenate(name='combinedConcat')([broadcasted, conv2]) conv3 = Conv2D(1, kernel_size=1, strides=(1,1), padding='same',name='conv3')(combinedSpatialNonSpatial) flatConv3 = Flatten(name='flatConv3')(conv3) lstmInput = Lambda(self.expand_dims, name='lstmInput')(flatConv3) self.NUM_LSTM = 100 hStateInput = Input( shape=(self.NUM_LSTM,), name='hStateInput' ) cStateInput = Input( shape=(self.NUM_LSTM,), name='cStateInput' ) lstm, hStates, cStates = LSTM(self.NUM_LSTM, return_state=True)(lstmInput, initial_state=[hStateInput, cStateInput]) fc1 = Dense(256, activation='relu',name='dense1')(lstm) fc2 = Dense(1, activation='linear',name='fc2')(fc1) value = Lambda(self.Squeeze,name='value')(fc2) policy = Dense(self.isize, activation='softmax',name='policy')(fc1) broadcastLstm = Lambda(self.broadcast, name='breadcastLstm')(lstm) spatialLstm = Concatenate(name='spatialLstm')([conv3, broadcastLstm]) conv4 = Conv2D(1,kernel_size=1, strides=(1,1), padding='same',name='conv4')(spatialLstm) flatConv4 = Flatten(name='flattenedConv3')(conv4) spatialPolicy = Softmax(name='spatialPolicy')(flatConv4) conv5 = Conv2D(1, kernel_size=1, strides=(1,1), padding='same',name='conv5')(spatialLstm) flatConv5 = Flatten(name='flattenedConv5')(conv5) bestRoach = Softmax(name='bestRoach')(flatConv5) self.model = Model( inputs=[screenInput, infoInput, customInput, hStateInput, cStateInput], outputs=[value, policy, spatialPolicy, hStates, cStates, bestRoach] ) self.model._make_predict_function() def save_model(self, path, count): self.saver.save(self.session, path + '/model.pkl', count) def load_model(self, path): ckpt = tf.train.get_checkpoint_state(path) self.saver.restore(self.session, ckpt.model_checkpoint_path) self.training_counter = int(ckpt.model_checkpoint_path.split('-')[-1])
class Brain: MIN_BATCH = 25 def __init__(self, flags, summary_writer, input_shape, output_shape): self.lr = flags.learning_rate self.er = flags.entropy_rate self.flags = flags self.summary_writer = summary_writer self.N_STEP_RETURN = 20 self.GAMMA = .99 self.LAMBDA = 1 self.stop_signal = False self.input_shape = input_shape self.output_shape = output_shape self.lock_queue = threading.Lock() self.train_queue = [[], [], [], [], [], []] self.counter_lock = threading.Lock() self.training_counter = 0 config = tf.ConfigProto(allow_soft_placement=True) config.gpu_options.allow_growth = True self.session = tf.Session(config=config) K.set_session(self.session) K.manual_variable_initialization(True) self.build_net('/gpu:0') self.build_model('/gpu:0') self.session.run(tf.global_variables_initializer()) self.default_graph = tf.get_default_graph() self.default_graph.finalize() self.summary_writer.add_graph(self.default_graph) def stop(self): self.stop_signal = True def getPredictFeedDict(self, observation, hState, cState): input = np.expand_dims(np.array(self.preprocess(observation), dtype=np.float32), axis=0) hState = np.expand_dims(np.array(hState), axis=0) cState = np.expand_dims(np.array(cState), axis=0) return { self.input: input, self.hStateInput: hState, self.cStateInput: cState } def predict(self, feed): with self.session.as_default(): policy, value, hs, cs = self.model.predict([ feed[self.input], feed[self.hStateInput], feed[self.cStateInput], ]) return policy, value, hs, cs def preprocess(self, data): if len(data.shape) == 1: return data stacks = [] for obs in data: cropped = obs[34:194, :, :] reduced = cropped[0:-1:2, 0:-1:2] grayscale = np.sum(reduced, axis=2) bw = np.zeros(grayscale.shape) bw[grayscale != 233] = 1 expand = np.expand_dims(bw, axis=2) stacks.append(expand) return np.concatenate(stacks, axis=2) def train(self, feed): feed[self.learning_rate] = self.lr feed[self.entropy_rate] = self.er _, summary = self.session.run([self.train_op, self.summary_op], feed_dict=feed) if self.flags.use_tensorboard: with self.counter_lock: self.training_counter = self.training_counter + 1 self.summary_writer.add_summary(summary, self.training_counter) self.summary_writer.flush() def add_train(self, batch): with self.lock_queue: for i in range(len(self.train_queue)): self.train_queue[i] = self.train_queue[i] + batch[i] if len(self.train_queue[0]) > (5000 * Brain.MIN_BATCH): print("Training queue too large; optimizer likely crashed %d" % len(self.train_queue[0])) exit() def optimize(self): time.sleep(0.001) with self.lock_queue: if len( self.train_queue[0] ) < Brain.MIN_BATCH: # more thread could have passed without lock return # we can't yield inside lock batch = self.train_queue self.train_queue = [[], [], [], [], [], []] batch_train_feed = { self.value_target: np.squeeze(np.array(batch[0], dtype=np.float32)), self.input: np.array(batch[1], dtype=np.float32), self.action_selected: np.array(batch[2], dtype=np.float32), self.advantage: np.array(batch[3], dtype=np.float32), self.hStateInput: np.array(batch[4], dtype=np.float32), self.cStateInput: np.array(batch[5], dtype=np.float32) } self.train(batch_train_feed) def getPolicyLoss(self, action_probability, advantage): return -tf.log(action_probability + 1e-10) * advantage def getValueLoss(self, difference): return tf.square(difference) def getEntropy(self, policy): return tf.reduce_sum(policy * tf.log(policy + 1e-10), axis=1) def build_model(self, dev): # Set targets and masks with tf.variable_scope('a3c'): self.action_selected = tf.placeholder(tf.float32, [None, self.output_shape[0]], name='action_selected') self.value_target = tf.placeholder(tf.float32, [None], name='value_target') self.entropy_rate = tf.placeholder(tf.float32, None, name='entropy_rate') self.learning_rate = tf.placeholder(tf.float32, None, name='learning_rate') self.advantage = tf.placeholder(tf.float32, [None], name='advantage') if len(self.input_shape) > 1: self.input = tf.placeholder(tf.float32, [None, 80, 80, 1], name='input') else: self.input = tf.placeholder(tf.float32, [None, self.input_shape[0]], name='input') self.hStateInput = tf.placeholder(tf.float32, [None, self.NUM_LSTM], name='h_state_input') self.cStateInput = tf.placeholder(tf.float32, [None, self.NUM_LSTM], name='c_state_input') self.policy, self.value, _, _ = self.model( [self.input, self.hStateInput, self.cStateInput]) # This will get the probability of choosing a valid action. Given that we force it to choose from # the set of valid actions. The probability of an action is the probability the policy chooses # divided by the probability of a valid action action_probability = tf.reduce_sum(self.action_selected * self.policy, axis=1) policy_loss = self.getPolicyLoss(action_probability, self.advantage) value_loss = self.getValueLoss(self.value_target - self.value) entropy = self.getEntropy(self.policy) loss = tf.reduce_mean(policy_loss + value_loss * .5 + entropy * .01) global_step = tf.Variable(0) learning_rate_decayed = tf.train.exponential_decay( self.learning_rate, global_step, 10000, .95, staircase=True) # Build the optimizer opt = tf.train.AdamOptimizer(learning_rate_decayed) grads, vars = zip(*opt.compute_gradients(loss)) grads, glob_norm = tf.clip_by_global_norm(grads, 40.0) self.train_op = opt.apply_gradients(zip(grads, vars), global_step=global_step) if self.flags.use_tensorboard: summary = [] summary.append( tf.summary.scalar('policy_loss', tf.reduce_mean(policy_loss))) summary.append(tf.summary.scalar('glob_norm', glob_norm)) summary.append( tf.summary.scalar('value_loss', tf.reduce_mean(value_loss))) summary.append( tf.summary.scalar('entropy_loss', tf.reduce_mean(entropy))) summary.append( tf.summary.scalar('advantage', tf.reduce_mean(self.advantage))) summary.append(tf.summary.scalar('loss', tf.reduce_mean(loss))) self.summary_op = tf.summary.merge(summary) else: self.summary_op = [] def expand_dims(self, x): return K.expand_dims(x, 1) def Squeeze(self, x): return K.squeeze(x, axis=-1) def build_net(self, dev): with tf.variable_scope('a3c'): if len(self.input_shape) > 1: input = Input(shape=(80, 80, 1), name='Input') conv1 = Conv2D(32, kernel_size=8, strides=(4, 4), padding='same', activation='relu', name='conv1')(input) conv2 = Conv2D(64, kernel_size=4, strides=(2, 2), padding='same', activation='relu', name='conv2')(conv1) conv3 = Conv2D(64, kernel_size=3, strides=(1, 1), padding='same', activation='relu', name='conv3')(conv2) flatConv3 = Flatten(name='flatConv3')(conv3) fc1 = Dense(512, activation='relu')(flatConv3) else: input = Input(shape=(self.input_shape[0], ), name='Input') fc1 = Dense(512, activation='relu')(input) LSTMIN = Lambda(self.expand_dims, name='expandFc1')(fc1) self.NUM_LSTM = 100 hStateInput = Input(shape=(self.NUM_LSTM, ), name='hStateInput') cStateInput = Input(shape=(self.NUM_LSTM, ), name='cStateInput') lstm, hStates, cStates = LSTM(self.NUM_LSTM, return_state=True)( LSTMIN, initial_state=[hStateInput, cStateInput]) fc2 = Dense(256, activation='relu', name='fc2')(lstm) vFc3 = Dense(1, activation='linear', name='vFc3')(fc2) value = Lambda(self.Squeeze, name='value')(vFc3) policy = Dense(self.output_shape[0], activation='softmax', name='policy')(fc2) self.model = Model(inputs=[input, hStateInput, cStateInput], outputs=[policy, value, hStates, cStates]) self.model._make_predict_function()