def _build_models(self, batch_size, embedding_size, rnn_size, num_layers): model = Sequential() model.add( Embedding(self.vectorizer.vocab_size, embedding_size, batch_input_shape=(batch_size, None))) for layer in range(num_layers): model.add(LSTM(rnn_size, stateful=True, return_sequences=True)) model.add(Dropout(0.2)) model.add( TimeDistributed( Dense(self.vectorizer.vocab_size, activation='softmax'))) # With sparse_categorical_crossentropy we can leave as labels as # integers instead of one-hot vectors model.compile(loss='sparse_categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) model.summary() # Keep a separate model with batch_size 1 for sampling self.train_model = model config = model.get_config() config['layers'][0]['config']['batch_input_shape'] = (1, None) self.sample_model = Sequential.from_config(config) self.sample_model.trainable = False
def create_model_RNN_LSTM(optimizer='adam', units=200, activation='sigmoid', EMBEDDING_DIM=25, max_length=37, vocab_size=350, hidden_dims=1, hidden_dim_units=25): print("Parameters", "units", units, "activation", activation, "EMBEDDING_DIM", EMBEDDING_DIM, "max_length", max_length, "vocab_size", vocab_size, " hidden_dims ", hidden_dims) keras_eval_metric = [[ TruePositives(name='tp'), FalsePositives(name='fp'), TrueNegatives(name='tn'), FalseNegatives(name='fn'), BinaryAccuracy(name='accuracy'), Precision(name='precision'), Recall(name='recall'), AUC(name='auc'), ]] model = Sequential() model.add(Embedding(vocab_size, EMBEDDING_DIM, input_length=max_length)) model.add( LSTM(units=hidden_dim_units, dropout=0.2, recurrent_dropout=0.2, activation=activation)) for i in range(hidden_dims): model.add(Dense(hidden_dim_units)) model.add(Activation(activation)) model.add(Dropout(0.2)) model.add(Dense(1)) model.add(Activation(activation)) model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=keras_eval_metric) print("\n\n", model.summary(), "\n\n", model.get_config(), "\n\n") return model
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.utils import plot_model # Dense Layer model = Sequential() model.add(Dense(16, input_shape=(8, ))) model.summary() #plot_model(model,to_file='model_plot.png',show_shapes=True,show_layer_names=True) print(model.get_config()) print(model.get_weights()) # Dropout layer model = Sequential() model.add(Dense(16, input_shape=(8, ))) model.add(Dropout(.2)) # Reduce 20% input at the time of model training model.add(Dense(10)) model.summary()
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense import json import numpy as np import yaml model = Sequential([ Dense(units=32, input_shape=(32, 32, 3), activation='relu', name='dense_1'), Dense(units=10, activation='softmax', name='dense_2') ]) ''' Method 1 ''' # get_config returns the model's architecture as a dictionary config_dict = model.get_config() print("config_dict") print(config_dict) # Creating a new model from the config with reinitialized weights # For models that are not Sequential models, # use tf.keras.Model.from_config instead of tf.keras.Sequential.from_config. model_same_config = tf.keras.Sequential.from_config(config_dict) # check model architecture and weights print('Same config:', model.get_config() == model_same_config.get_config()) print( 'Same value for first weight matrix:', np.allclose(model.weights[0].numpy(), model_same_config.weights[0].numpy())) ''' Other file formats: JSON and YAML ''' ''' JSON ''' json_string = model.to_json()
class MLP(object): """ Class associated with Multi-Layer Perceptron (Neural Network) Parameters ---------- nhidden : int, optional, default: 1 The number of hidden layers in the neural network (excluding input and output) nneurons: list, optional, default: [100] * nhidden The number of nodes in each hidden layer. Must be of same length as nhidden activations: list, optional, default: ['sigmoid'] * nhidden The activation type for each hidden layer. Must be of same length as nhidden. Refer https://keras.io/activations/ for list of valid activations nepochs: int, optional, default: 100 Number of training epochs. batch_size: int, optional, default: 100 Number of training samples in mini-batch loss: str, optional, default: 'mean_squared_error' Type of loss used to train the neural network. Refer https://keras.io/losses/ for list of valid losses regression: bool, optional, default: True Decides whether we are training for regression or classification task nclasses: int, optional, default: None Number of classes labels needs to be specified if regression is False layer_config_file: str, optional, default: None Path to the file that specifies layer configuration Refer MLP test to see a sample file opt_config: list, optional, default: None optimizer configuration (for e.g., ["Adam",{"learning_rate":0.01}] or ["SGD",{"lr":0.01, "momentum":0.9, "lr_decay":0.0, nesterov=False) Refer MLP test to see a sample file """ def __init__(self, nhidden=1, nneurons=None, activations=None, learning_rate=0.01, lr_decay=0.0, nepochs=100, batch_size=100, loss='mean_squared_error', regression=True, nclasses=None, layer_config_file=None, opt_config=None): self.model = Sequential() if layer_config_file: self.layers = self.parse_layer_config(layer_config_file) self.nhidden = None self.nneurons = None self.activations = None else: self.layers = [] self.nhidden = nhidden self.nneurons = nneurons if nneurons else [100] * nhidden self.activations = activations if activations else ['sigmoid' ] * nhidden if opt_config: self.opt = self.parse_opt_config(opt_config) else: self.opt = SGD(lr=learning_rate, momentum=0.9, decay=lr_decay, nesterov=False) self.nepochs = nepochs self.batch_size = batch_size self.loss = loss self.is_regression = regression self.nclasses = nclasses def get_keras_model(self, include_output=True, n_layers=None): """ Returns the entire Keras model or the model without the output layer in its current state (fitted or compiled) Parameters __________ include_output: bool if True it will return the entire model, if False it will return the model without the output layer n_layers: int, optional (default=None) remove the last 'n' hidden layers from the model in addition to the output layer. Note that this number should not include the output layer. Returns _______ self.model: tensorflow.python.keras type object """ if not include_output: head_model = Model(self.model.input, self.model.layers[-2].output) if n_layers is not None: if isinstance(n_layers, int): head_model = Model( head_model.input, head_model.layers[-(1 + n_layers)].output) else: raise ValueError('n_layers should be an integer.') return head_model else: return self.model def save(self, path, filename): """ Saves the chemml.models.MLP object along with the underlying tensorflow.python.keras object Parameters __________ path: str the path to the directory where the models should be saved filename: str the name of the model file without the file type """ obj_dict = vars(self) self.model.save(path + '/' + filename + '.h5') # obj_dict['path_to_file'] = path +'/'+ filename+'.h5' obj_df = pd.DataFrame.from_dict(obj_dict, orient='index') obj_df.to_csv(path + '/' + filename + '_chemml_model.csv') print("File saved as " + path + "/" + filename + "_chemml_model.csv") def load(self, path_to_model): """ Loads the chemml.models.MLP object along with the underlying tensorflow.python.keras object Parameters __________ path_to_model: str path to the chemml.models.MLP csv file """ chemml_model = pd.read_csv(path_to_model, index_col=0) # self.model = load_model(chemml_model.loc['path_to_file'][0]) self.model = load_model( path_to_model.split('_chemml_model.csv')[0] + '.h5') # optimizer config opt = self.model.optimizer.get_config() opt_list = [opt['name']] del opt['name'] opt_list.append(opt) self.opt = self.parse_opt_config(opt_list) self.nepochs = int(chemml_model.loc['nepochs'][0]) self.batch_size = int(chemml_model.loc['batch_size'][0]) self.loss = chemml_model.loc['loss'][0] self.is_regression = eval(chemml_model.loc['is_regression'][0]) self.nclasses = chemml_model.loc['nclasses'][0] if str(self.nclasses).lower() == 'nan': self.nclasses = None else: self.nclasses = int(self.nclasses) self.feature_size = int(chemml_model.loc['feature_size'][0]) # layer config self.layers = [(n['class_name'], n['config']) for n in self.model.get_config()['layers']] self.nhidden = None self.nneurons = None self.activations = None return self def fit(self, X, y): """ Train the MLP for training data X and targets y Parameters ---------- X: array_like, shape=[n_samples, n_features] Training data y: array_like, shape=[n_samples,] Training targets """ if len(self.layers) == 0: for i in range(self.nhidden): self.layers.append(('Dense', { 'units': self.nneurons[i], 'activation': self.activations[i] })) if self.is_regression: self.layers.append(('Dense', { 'units': 1, 'activation': 'linear' })) else: self.layers.append(('Dense', { 'units': self.nclasses, 'activation': 'softmax' })) self.feature_size = X.shape[-1] layer_name, layer_params = self.layers[0] layer_params['input_dim'] = X.shape[-1] keras_layer_module = import_module('tensorflow.keras.layers') for layer_name, layer_params in self.layers: layer = getattr(keras_layer_module, layer_name) self.model.add(layer(**layer_params)) self.model.compile(loss=self.loss, optimizer=self.opt) self.batch_size = X.shape[ 0] if X.shape[0] < self.batch_size else self.batch_size self.model.fit(x=X, y=y, epochs=self.nepochs, batch_size=self.batch_size) def predict(self, X): """ Return prediction for test data X Parameters ---------- X: array_like, shape=[n_samples, n_features] Testing data Returns ------- float Predicted value from model """ return self.model.predict( X).squeeze() if self.is_regression else np.argmax( self.model.predict(X).squeeze()) def score(self, X, y): """ Predict results for test data X and compare with true targets y. Returns root mean square error if regression, accuracy if classification Parameters ---------- X: array_like, shape=[n_samples, n_features] Test data y: array_like, shape=[n_samples,] True targets Returns ------- float root mean square error if regression, accuracy if classification """ prediction = self.model.predict(X).squeeze() if self.is_regression: return np.mean((prediction - y)**2)**0.5 else: return np.sum(np.argmax(prediction, axis=1) == y) * 100. / len(y) def parse_layer_config(self, layer_config_file): """ Internal method to parse a layer config file Parameters ---------- layer_config_file: str Filepath that contains the layer configuration file - Refer MLP test to see a sample file Refer MLP test to see a sample file and https://keras.io/layers/about-keras-layers/ for all possible types of layers and corresponding layer parameters Returns ------- layers: list List of tuples containing layer type and dictionary of layer parameter arguments """ with open(layer_config_file, 'r') as f: layers = load(f) return layers def parse_opt_config(self, opt_config): """ Internal method to parse a optimizer config file Parameters ---------- opt_config: list optimizer configuration (for e.g., ["Adam",{"learning_rate":0.01}] or ["SGD",{"lr":0.01, "momentum":0.9, "lr_decay":0.0, nesterov=False) refer https://keras.io/optimizers/ for all possible types of optimizers and corresponding optimizer parameters Returns ------- opt: keras.optimizers keras optimizer created out of contents of optmizer configuration file """ if isinstance(opt_config, list): opt_name, opt_params = opt_config[0], opt_config[1] keras_opt_module = import_module('tensorflow.keras.optimizers') opt = getattr(keras_opt_module, opt_name)(**opt_params) return opt
class Pipeline: """ Parameters ---------- df : pd.Dataframe name : str A tag for the neural network. This name is used to save the model, figures and tables within a folder named after this string. Examples -------- >>> import pandas as pd >>> import rossml as rsml Importing and collecting data >>> df = pd.read_csv('seal_fake.csv') >>> df_val= pd.read_csv('xllaby_data-componentes.csv') >>> df_val.fillna(df.mean) >>> D = rsml.Pipeline(df) >>> D.set_features(0, 20) >>> D.set_labels(20, len(D.df.columns)) >>> D.feature_reduction(15) >>> D.data_scaling(0.1, scalers=[RobustScaler(), RobustScaler()], scaling=True) >>> D.build_Sequential_ANN(4, [50, 50, 50, 50]) >>> model, predictions = D.model_run(batch_size=300, epochs=1000) Get the model configurations to change it afterwards >>> # model.get_config() >>> D.model_history() >>> D.metrics() Post-processing data >>> results = D.postprocessing() >>> fig = results.plot_overall_results() >>> fig = results.plot_confidence_bounds(a = 0.01) >>> fig = results.plot_standardized_error() >>> fig = results.plot_qq() Displays the HTML report >>> url = 'results' >>> # results.report(url) >>> D.hypothesis_test() >>> D.save() >>> model = rsml.Model('Model') >>> X = Pipeline(df_val).set_features(0,20) >>> results = model.predict(X) """ def __init__(self, df, name="Model"): path_model = Path(__file__).parent / f"models/{name}" path_img = Path(__file__).parent / f"models/{name}/img" path_table = Path(__file__).parent / f"models/{name}/tables" if not path_model.exists(): path_model.mkdir() path_img.mkdir() path_table.mkdir() self.df = df self.df.dropna(inplace=True) self.name = name def set_features(self, start, end): """Select the features from the input DataFrame. This methods takes the DataFrame and selects all the columns from "start" to "end" values to indicate which columns should be treated as features. Parameters ---------- start : int Start column of dataframe features end : int End column of dataframe features Returns ------- x : pd.DataFrame DataFrame with features parameters Example ------- """ self.x = self.df[self.df.columns[start:end]] self.columns = self.x.columns return self.x def set_labels(self, start, end): """Select the labels from the input DataFrame. This methods takes the DataFrame and selects all the columns from "start" to "end" values to indicate which columns should be treated as labels. Parameters ---------- start : int Start column of dataframe labels end : int End column of dataframe labels Returns ------- y : pd.DataFrame DataFrame with labels parameters Example ------- """ self.y = self.df[self.df.columns[start:end]] return self.y def feature_reduction(self, n): """ Parameters ---------- n : int Number of relevant features. Returns ------- Minimum number of features that satisfies "n" for each label. """ # define the model model = DecisionTreeRegressor() # fit the model model.fit(self.x, self.y) # get importance importance = model.feature_importances_ # summarize feature importance featureScores = pd.concat( [pd.DataFrame(self.x.columns), pd.DataFrame(importance)], axis=1 ) featureScores.columns = ["Specs", "Score"] self.best = featureScores.nlargest(n, "Score")["Specs"].values self.x = self.x[self.best] return self.x def data_scaling(self, test_size, scaling=False, scalers=None): """ Parameters ---------- test_size : float Percentage of data destined for testing. scaling : boolean, optional Choose between scaling the data or not. The default is False. scalers : scikit-learn object scikit-learn scalers. Returns ------- x_train : array Features destined for training. x_test : array Features destined for test. y_train : array Labels destined for training. y_test : array Labels destined for test. Examples -------- """ if scalers is None: scalers = [] self.x_train, self.x_test, self.y_train, self.y_test = train_test_split( self.x, self.y, test_size=test_size ) if scaling: if len(scalers) >= 1: self.scaler1 = scalers[0] self.x_train = self.scaler1.fit_transform(self.x_train) self.x_test = self.scaler1.transform(self.x_test) if len(scalers) == 2: self.scaler2 = scalers[1] self.y_train = self.scaler2.fit_transform(self.y_train) self.y_test = self.scaler2.transform(self.y_test) else: self.scaler1 = None self.scaler2 = None return self.x_train, self.x_test, self.y_train, self.y_test def build_Sequential_ANN(self, hidden, neurons, dropout_layers=None, dropout=None): """ Parameters ---------- hidden : int Number of hidden layers. neurons : list Number of neurons per layer. dropout_layers : list, optional Dropout layers position. The default is []. dropout : list, optional List with dropout values. The default is []. Returns ------- model : keras neural network """ if dropout_layers is None: dropout_layers = [] if dropout is None: dropout = [] self.model = Sequential() self.model.add(Dense(len(self.x.columns), activation="relu")) j = 0 # Dropout counter for i in range(hidden): if i in dropout_layers: self.model.add(Dropout(dropout[j])) j += 1 self.model.add(Dense(neurons[i], activation="relu")) self.model.add(Dense(len(self.y.columns))) self.config = self.model.get_config() return self.model def model_run(self, optimizer="adam", loss="mse", batch_size=16, epochs=500): """ Parameters ---------- optimizer : string, optional Choose a optimizer. The default is 'adam'. loss : string, optional Choose a loss. The default is 'mse'. batch_size : int, optional batch_size . The default is 16. epochs : int, optional Choose number of epochs. The default is 500. Returns ------- model : keras neural network predictions : """ self.model.compile(optimizer=optimizer, loss=loss) self.history = self.model.fit( x=self.x_train, y=self.y_train, validation_data=(self.x_test, self.y_test), batch_size=batch_size, epochs=epochs, ) self.predictions = self.model.predict(self.x_test) self.train = pd.DataFrame( self.scaler2.inverse_transform(self.predictions), columns=self.y.columns ) self.test = pd.DataFrame( self.scaler2.inverse_transform(self.y_test), columns=self.y.columns ) return self.model, self.predictions def model_history(self): """Plot model history. Examples -------- """ path = Path(__file__).parent hist = pd.DataFrame(self.history.history) axes_default = dict( gridcolor="lightgray", showline=True, linewidth=1.5, linecolor="black", mirror=True, exponentformat="none", ) fig = go.Figure() fig.add_trace( go.Scatter( x=list(range(hist["loss"].size)), y=np.log10(hist["loss"]), mode="lines", line=dict(color="blue"), name="Loss", legendgroup="Loss", hoverinfo="none", ) ) fig.add_trace( go.Scatter( x=list(range(hist["val_loss"].size)), y=np.log10(hist["val_loss"]), mode="lines", line=dict(color="orange"), name="Val_loss", legendgroup="Val_loss", hoverinfo="none", ) ) fig.update_xaxes( title=dict(text="Epoch", font=dict(size=15)), **axes_default, ) fig.update_yaxes( title=dict(text="Log<sub>10</sub>Loss", font=dict(size=15)), **axes_default, ) fig.update_layout( plot_bgcolor="white", legend=dict( bgcolor="white", bordercolor="black", borderwidth=1, ), ) fig.write_html(str(path / f"models/{self.name}/img/history.html")) return fig def metrics(self, save=False): """Print model metrics. This function displays the model metrics while the neural network is being built. Prints ------ The mean absolute error (MAE). The mean squared error (MSE). The coefficient of determination (R-squared). The adjusted coefficient of determination (adjusted R-squared). The explained variance (discrepancy between a model and actual data). """ R2_a = 1 - ( (len(self.predictions) - 1) * (1 - r2_score(self.y_test, self.predictions)) / (len(self.predictions) - (1 + len(self.x.columns))) ) MAE = mean_absolute_error(self.y_test, self.predictions) MSE = mean_squared_error(self.y_test, self.predictions) R2 = r2_score(self.y_test, self.predictions) explained_variance = explained_variance_score(self.y_test, self.predictions) metrics = pd.DataFrame( np.round([MAE, MSE, R2, R2_a, explained_variance], 3), index=["MAE", "MSE", "R2", "R2_adj", "explained variance"], columns=["Metric"], ) if save: HTML_formater(metrics, self.name, "Metrics") print( "Scores:\nMAE: {}\nMSE: {}\nR^2:{}\nR^2 adjusted:{}\nExplained variance:{}".format( MAE, MSE, R2, R2_a, explained_variance ) ) def hypothesis_test(self, kind="ks", p_value=0.05, save=False): """Run a hypothesis test. Parameters ---------- kind : string, optional Hypothesis test kind. Options are: "w": Welch test Calculate the T-test for the means of two independent samples of scores. This is a two-sided test for the null hypothesis that 2 independent samples have identical average (expected) values. This test assumes that the populations have identical variances by default. "ks": Komolgorov-Smirnov test Compute the Kolmogorov-Smirnov statistic on 2 samples. This is a two-sided test for the null hypothesis that 2 independent samples are drawn from the same continuous distribution. The default is 'ks'. * See scipy.stats.ks_2samp and scipy.stats.ttest_ind documentation for more informations. p_value : float, optional Critical value. Must be within 0 and 1. The default is 0.05. save : boolean If True, saves the hypothesis test. If False, the hypothesis_test won't be saved. Returns ------- p_df : pd.DataFrame Hypothesis test results. Examples -------- """ if kind == "ks": p_values = np.round( [ ks_2samp(self.train[var], self.test[var]).pvalue for var in self.train.columns ], 3, ) p_df = pd.DataFrame( p_values, index=self.test.columns, columns=["p-value: train"] ) p_df["status"] = [ "Not Reject H0" if p > p_value else "Reject H0" for p in p_df["p-value: train"] ] if save: HTML_formater(p_df, self.name, "KS Test") elif kind == "w": p_values = np.round( [ ttest_ind(self.train[var], self.test[var], equal_var=False).pvalue for var in self.train.columns ], 3, ) p_df = pd.DataFrame( p_values, index=self.train.columns, columns=["p-value: acc"] ) p_df["status"] = [ "Not Reject H0" if p > p_value else "Reject H0" for p in p_df["p-value: acc"] ] if save: HTML_formater(p_df, self.name, "Welch Test") return p_df def validation(self, x, y): """ Parameters ---------- x : pd.DataFrame DESCRIPTION. y : pd.DataFrame DESCRIPTION. Returns ------- train : pd.DataFrame DESCRIPTION. test : pd.DataFrame DESCRIPTION. """ self.test = y if self.scaler1 is not None: x_scaled = self.scaler1.transform(x.values.reshape(-1, len(x.columns))) if self.scaler2 is not None: self.train = pd.DataFrame( self.scaler2.inverse_transform(self.model.predict(x_scaled)), columns=y.columns, ) else: self.train = pd.DataFrame(self.model.predict(x_scaled), columns=y.columns) return self.train, self.test def postprocessing(self): """Create an instance to plot results for neural networks. This method returns an instance from PostProcessing class. It allows plotting some analyzes for neural networks and a HTML report with a result summary. - plot_overall_results - plot_confidence_bounds - plot_qq - plot_standardized_error - plot_residuals_resume - show Returns ------- results : PostProcessing object An instance from PostProcessing class that allows plotting some analyzes for neural networks. Examples -------- """ results = PostProcessing(self.train, self.test, self.name) return results def save(self): """Save a neural netowork model. Examples -------- """ path = Path(__file__).parent / f"models/{self.name}" if not path.exists(): path.mkdir() self.model.save(path / r"{}.h5".format(self.name)) dump(self.y.columns, open(path / r"{}_columns.pkl".format(self.name), "wb")) dump(self.best, open(path / r"{}_best_features.pkl".format(self.name), "wb")) dump(self.columns, open(path / r"{}_features.pkl".format(self.name), "wb")) dump( self.df.describe(), open(path / r"{}_describe.pkl".format(self.name), "wb") ) if self.scaler1 is not None: dump(self.scaler1, open(path / r"{}_scaler1.pkl".format(self.name), "wb")) if self.scaler2 is not None: dump(self.scaler2, open(path / r"{}_scaler2.pkl".format(self.name), "wb"))
def train(type_name, n_hidden): # Initialize save path save_path = "/home/kevin/projects/exercise_pose_evaluation_machine/models/lstm_model/keras/" + type_name + "/" + type_name + "_lstm_model.h5" # Get original dataset x, y = get_dataset(type_name) # Fill original class type with the label 1 y = [1 for label in y] # Get negative dataset neg_x, neg_y = get_dataset("not-" + type_name) # Fill original class type with the label 1 neg_y = [0 for label in neg_y] x.extend(neg_x) y.extend(neg_y) # Flatten X coodinates and filter x = np.array(x) _x = [] _y = [] for idx, data in enumerate(x): data = [np.reshape(np.array(frames), (28)).tolist() for frames in data] _x.append(data) _y.append(y[idx]) x = _x y = _y # Split to training and test dataset x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=.3) x_train = np.array(x_train) x_test = np.array(x_test) y_train = np.array(y_train) y_test = np.array(y_test) # Define training parameters n_classes = 1 # Make LSTM Layer # Pair of lstm cell initialization through loop # use_bias -> Adding bias vector on each layer, by default is True so this line could be deleted # unit_forget_bias -> lstm_cells = [ LSTMCell(n_hidden, activation='relu', use_bias=True, unit_forget_bias=1.0) for _ in range(2) ] stacked_lstm = StackedRNNCells(lstm_cells) lstm_layer = RNN(stacked_lstm) learning_rate = 1e-2 lr_schedule = PolynomialDecay(initial_learning_rate=learning_rate, decay_steps=10, end_learning_rate=0.00001) optimizer = Adam(learning_rate=lr_schedule) # Initiate model # kernel_regularizers -> regularizing weights to avoid overfit training data on layer kernel # activity_regularizer -> regularizing weights to avoid overfit training data on layer output model = Sequential() model.add(lstm_layer) model.add(Dropout(0.3)) model.add( Dense(n_classes, activation='sigmoid', kernel_regularizer=regularizers.l2(0.01), activity_regularizer=regularizers.l1(0.01))) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # simple early stopping es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=50) # Train model # shufffle = True -> shuffle training data # validation_split -> portion of training data used for validation split # validation_data -> external data used for validation model.fit(x_train, y_train, epochs=450, batch_size=150, shuffle=True, validation_data=(x_test, y_test), validation_split=0.4, callbacks=[es]) # Print model stats print(model.summary()) print(model.get_config()) # Find accuracy _, accuracy = model.evaluate(x_test, y_test) print('Accuracy: %.2f' % (accuracy * 100)) # Save model model.save(save_path) print("Saved model!") # Generate predictions print("See prediction result") random_int = random.randint(0, len(x_test)) data = x_test[random_int] prediction = "1" if model.predict(np.array([data])) > 0.5 else "0" print("predictions result:", prediction) print("expected result: ", y_test[random_int])
class Pipeline: r"""Generate an artificial neural netowrk. This class is a pipeline for building neural network models. From the data spreadsheet to the model it self, each function for this class has to be called in an exact order to guarantee its the correct functioning. The basic order to follow: - Pipeline - set_features() - set_labels() - feature_reduction() - data_scaling() - build_Sequential_ANN() - model_run() Parameters ---------- df : pd.Dataframe name : str A tag for the neural network. This name is used to save the model, figures and tables within a folder named after this string. Examples -------- >>> import pandas as pd >>> import rossml as rsml >>> from pathlib import Path >>> from sklearn.preprocessing import RobustScaler Importing and collecting data >>> file = Path(__file__).parent / "tests/data/seal_data.csv" >>> df = pd.read_csv(file) Building the neural network model >>> name = "Model" # this name will be used to save your work >>> D = rsml.Pipeline(df, name) Selecting features and labels >>> features = D.set_features(1, 21) >>> labels = D.set_labels(21, len(D.df.columns)) >>> new_features = D.feature_reduction(15) Data scaling and running the model >>> x_train, x_test, y_train, y_test = D.data_scaling( ... 0.1, scalers=[RobustScaler(), RobustScaler()], scaling=True ... ) >>> model = D.build_Sequential_ANN(4, [50, 50, 50, 50]) >>> model, predictions = D.model_run(batch_size=300, epochs=200) # doctest: +ELLIPSIS Epoch 1/200... Get the model configurations to change it afterwards. These evaluations are important to decide whether the neural network meets or not the user requirements. >>> # model.get_config() >>> # fig = D.model_history() >>> # D.metrics() >>> df_test = D.hypothesis_test() Post-processing Data >>> results = PostProcessing(D.train, D.test, name) >>> fig = results.plot_overall_results() >>> fig = results.plot_confidence_bounds(a = 0.01) >>> fig = results.plot_standardized_error() >>> fig = results.plot_qq() Saving a model >>> # D.save() Displays the HTML report >>> # url = 'results' >>> # results.report(url) Loading a neural network model >>> # model = rsml.Model("Model") >>> # X = Pipeline(df).set_features(1, 21) >>> # results = model.predict(X) Removing models >>> rsml.remove_model('Model') """ def __init__(self, df, name="Model"): path_model = Path(__file__).parent / f"models/{name}" path_img = Path(__file__).parent / f"models/{name}/img" path_table = Path(__file__).parent / f"models/{name}/tables" if not path_model.exists(): path_model.mkdir() path_img.mkdir() path_table.mkdir() self.df = df self.df.dropna(inplace=True) self.name = name self.best = None def set_features(self, start, end): """Select the features from the input DataFrame. This methods takes the DataFrame and selects all the columns from "start" to "end" values to indicate which columns should be treated as features. Parameters ---------- start : int Start column of dataframe features end : int End column of dataframe features Returns ------- x : pd.DataFrame DataFrame with features parameters Example ------- """ self.x = self.df[self.df.columns[start:end]] self.columns = self.x.columns return self.x def set_labels(self, start, end): """Select the labels from the input DataFrame. This methods takes the DataFrame and selects all the columns from "start" to "end" values to indicate which columns should be treated as labels. Parameters ---------- start : int Start column of dataframe labels end : int End column of dataframe labels Returns ------- y : pd.DataFrame DataFrame with labels parameters Example ------- """ self.y = self.df[self.df.columns[start:end]] return self.y def feature_reduction(self, n): """Feature reduction using Decision Tree Regression method. This function uses Decision Tree Regression to select the "n" best features. Due it's random aspects, the selected best features may not be the same every time this function is called. Parameters ---------- n : int Number of relevant features. Returns ------- x : pd.DataFrame Minimum number of features that satisfies "n" for each label. """ # define the model model = DecisionTreeRegressor() # fit the model model.fit(self.x, self.y) # get importance importance = model.feature_importances_ # summarize feature importance featureScores = pd.concat( [pd.DataFrame(self.x.columns), pd.DataFrame(importance)], axis=1) featureScores.columns = ["Specs", "Score"] self.best = featureScores.nlargest(n, "Score")["Specs"].values self.x = self.x[self.best] return self.x def data_scaling(self, test_size, scaling=False, scalers=None): """Perform data scalling. This function scales the input and output data. The DataFrame provided may have multiple variables with different units and leading to completely distinguished magnitude values. Unscaled input variables can result in a slow or unstable learning process, whereas unscaled target variables on regression problems can result in exploding gradients causing the learning process to fail. Parameters ---------- test_size : float Percentage of data destined for testing. scaling : boolean, optional Choose between scaling the data or not. The default is False. scalers : scikit-learn object scikit-learn scalers method. Check sklearn.preprocessing for more informations about each scaler method. The default is None. Returns ------- x_train : array Features destined for training. x_test : array Features destined for test. y_train : array Labels destined for training. y_test : array Labels destined for test. """ if scalers is None: scalers = [] self.x_train, self.x_test, self.y_train, self.y_test = train_test_split( self.x, self.y, test_size=test_size) if scaling: if len(scalers) >= 1: self.scaler1 = scalers[0] self.x_train = self.scaler1.fit_transform(self.x_train) self.x_test = self.scaler1.transform(self.x_test) if len(scalers) == 2: self.scaler2 = scalers[1] self.y_train = self.scaler2.fit_transform(self.y_train) self.y_test = self.scaler2.transform(self.y_test) else: self.x_train = self.x_train.values self.x_test = self.x_test.values self.y_train = self.y_train.values self.y_test = self.y_test.values self.scaler1 = None self.scaler2 = None return self.x_train, self.x_test, self.y_train, self.y_test def build_Sequential_ANN(self, hidden, neurons, dropout_layers=None, dropout=None): """Construct a sequential Artificial Neural Network from Keras models. Parameters ---------- hidden : int Number of hidden layers. neurons : list Number of neurons per layer. dropout_layers : list, optional Dropout layers position. The default is []. dropout : list, optional List with dropout values. The default is []. Returns ------- model : keras neural network """ if dropout_layers is None: dropout_layers = [] if dropout is None: dropout = [] self.model = Sequential() self.model.add(Dense(len(self.x.columns), activation="relu")) j = 0 # Dropout counter for i in range(hidden): if i in dropout_layers: self.model.add(Dropout(dropout[j])) j += 1 self.model.add(Dense(neurons[i], activation="relu")) self.model.add(Dense(len(self.y.columns))) self.config = self.model.get_config() return self.model def model_run(self, optimizer="adam", loss="mse", batch_size=16, epochs=500): """Run the neural network model. Parameters ---------- optimizer : string, optional Choose a optimizer. The default is 'adam'. loss : string, optional Choose a loss. The default is 'mse'. batch_size : int, optional batch_size . The default is 16. epochs : int, optional Choose number of epochs. The default is 500. Returns ------- model : keras neural network """ self.model.compile(optimizer=optimizer, loss=loss) self.history = self.model.fit( x=self.x_train, y=self.y_train, validation_data=(self.x_test, self.y_test), batch_size=batch_size, epochs=epochs, ) self.predictions = self.model.predict(self.x_test) if self.scaler2 is None: self.train = pd.DataFrame(self.scaler2.inverse_transform( self.predictions), columns=self.y.columns) self.test = pd.DataFrame(self.scaler2.inverse_transform( self.y_test), columns=self.y.columns) else: self.train = pd.DataFrame(self.predictions, columns=self.y.columns) self.test = pd.DataFrame(self.y_test, columns=self.y.columns) return self.model, self.predictions def model_history(self): """Plot model history. Plots the history of loss and val_loss vs the number of epochs. Returns ------- fig : Plotly.figure Loss and Val_Loss data through the epochs. """ path = Path(__file__).parent hist = pd.DataFrame(self.history.history) axes_default = dict( gridcolor="lightgray", showline=True, linewidth=1.5, linecolor="black", mirror=True, exponentformat="none", ) fig = go.Figure() fig.add_trace( go.Scatter( x=list(range(hist["loss"].size)), y=np.log10(hist["loss"]), mode="lines", line=dict(color="blue"), name="Loss", legendgroup="Loss", hoverinfo="none", )) fig.add_trace( go.Scatter( x=list(range(hist["val_loss"].size)), y=np.log10(hist["val_loss"]), mode="lines", line=dict(color="orange"), name="Val_loss", legendgroup="Val_loss", hoverinfo="none", )) fig.update_xaxes( title=dict(text="Epoch", font=dict(size=15)), **axes_default, ) fig.update_yaxes( title=dict(text="Log<sub>10</sub>Loss", font=dict(size=15)), **axes_default, ) fig.update_layout( plot_bgcolor="white", legend=dict( bgcolor="white", bordercolor="black", borderwidth=1, ), ) fig.write_html(str(path / f"models/{self.name}/img/history.html")) fig.write_image(str(path / f"models/{self.name}/img/history.png")) return fig def metrics(self, save=False): """Print model metrics. This function displays the model metrics after the neural network is being built. Parameters ---------- save : bool, optional Key to decide if the table values should be saved in a HTML table or not. True saves the table; False do not. Prints ------ The mean absolute error (MAE). The mean squared error (MSE). The coefficient of determination (R-squared). The adjusted coefficient of determination (adjusted R-squared). The explained variance (discrepancy between a model and actual data). """ R2_a = 1 - ((len(self.predictions) - 1) * (1 - r2_score(self.y_test, self.predictions)) / (len(self.predictions) - (1 + len(self.x.columns)))) MAE = mean_absolute_error(self.y_test, self.predictions) MSE = mean_squared_error(self.y_test, self.predictions) R2 = r2_score(self.y_test, self.predictions) explained_variance = explained_variance_score(self.y_test, self.predictions) metrics = pd.DataFrame( np.round([MAE, MSE, R2, R2_a, explained_variance], 3), index=["MAE", "MSE", "R2", "R2_adj", "explained variance"], columns=["Metric"], ) if save: HTML_formater(metrics, self.name, "Metrics") print( "Scores:\nMAE: {}\nMSE: {}\nR^2:{}\nR^2 adjusted:{}\nExplained variance:{}" .format(MAE, MSE, R2, R2_a, explained_variance)) def hypothesis_test(self, kind="ks", p_value=0.05, save=False): """Run a hypothesis test. This function runs a hypothesis test based on the observed data modeled as the realised values taken by a collection of random variables. There are 2 options available to run these tests: "ks": Komolgorov-Smirnov test "w": Welch test Parameters ---------- kind : string, optional Hypothesis test kind. Options are: "w": Welch test Calculate the T-test for the means of two independent samples of scores. This is a two-sided test for the null hypothesis that 2 independent samples have identical average (expected) values. This test assumes that the populations have identical variances by default. "ks": Komolgorov-Smirnov test Compute the Kolmogorov-Smirnov statistic on 2 samples. This is a two-sided test for the null hypothesis that 2 independent samples are drawn from the same continuous distribution. The default is 'ks'. * See scipy.stats.ks_2samp and scipy.stats.ttest_ind documentation for more informations. p_value : float, optional Critical value. Must be within 0 and 1. The default is 0.05. save : boolean If True, saves the hypothesis test. If False, the hypothesis_test won't be saved. References ---------- Larry Wasserman. 2010. All of Statistics: A Concise Course in Statistical Inference. Springer Publishing Company, Incorporated. Returns ------- p_df : pd.DataFrame Hypothesis test results. The first column returns the p-value. The second column returns the status, which can reject or not the test result. If the calculated p-value is greater than "p_value" arg, the result shall be "Not Reject". Examples -------- """ if kind == "ks": p_values = np.round( [ ks_2samp(self.train[var], self.test[var]).pvalue for var in self.train.columns ], 3, ) p_df = pd.DataFrame(p_values, index=self.test.columns, columns=["p-value: train"]) p_df["status"] = [ "Not Reject H0" if p > p_value else "Reject H0" for p in p_df["p-value: train"] ] if save: HTML_formater(p_df, self.name, "KS Test") elif kind == "w": p_values = np.round( [ ttest_ind(self.train[var], self.test[var], equal_var=False).pvalue for var in self.train.columns ], 3, ) p_df = pd.DataFrame(p_values, index=self.train.columns, columns=["p-value: acc"]) p_df["status"] = [ "Not Reject H0" if p > p_value else "Reject H0" for p in p_df["p-value: acc"] ] if save: HTML_formater(p_df, self.name, "Welch Test") return p_df def validation(self, x, y): """Perform model validation. Parameters ---------- x : pd.DataFrame DataFrame with feature data. y : pd.DataFrame DataFrame with labels data. Returns ------- train : pd.DataFrame DataFrame with the train data. test : pd.DataFrame DataFrame with the test data. """ self.test = y if self.scaler1 is not None: x_scaled = self.scaler1.transform( x.values.reshape(-1, len(x.columns))) if self.scaler2 is not None: self.train = pd.DataFrame( self.scaler2.inverse_transform(self.model.predict(x_scaled)), columns=y.columns, ) else: self.train = pd.DataFrame(self.model.predict(x_scaled), columns=y.columns) return self.train, self.test def postprocessing(self): """Create an instance to plot results for neural networks. This method returns an instance from PostProcessing class. It allows plotting some analyzes for neural networks and a HTML report with a result summary. - plot_overall_results - plot_confidence_bounds - plot_qq - plot_standardized_error - plot_residuals_resume - show Returns ------- results : PostProcessing object An instance from PostProcessing class that allows plotting some analyzes for neural networks. """ results = PostProcessing(self.train, self.test, self.name) return results def save(self): """Save a neural netowork model. This function saves the required files for the neural network model. It creates a new folder named after the "name" argument passed to Pipeline initialization. This folder can be found within the rossml folder package. If the model has the same name as a previously saved neural network, the old files will be replaced with the files from the new model. """ path = Path(__file__).parent / f"models/{self.name}" if not path.exists(): path.mkdir() else: for child in path.glob("*"): if child.is_file(): child.unlink() self.model.save(path / r"{}.h5".format(self.name)) dump(self.y.columns, open(path / r"{}_columns.pkl".format(self.name), "wb")) if self.best is not None: dump(self.best, open(path / r"{}_best_features.pkl".format(self.name), "wb")) dump(self.columns, open(path / r"{}_features.pkl".format(self.name), "wb")) dump(self.df.describe(), open(path / r"{}_describe.pkl".format(self.name), "wb")) if self.scaler1 is not None: dump(self.scaler1, open(path / r"{}_scaler1.pkl".format(self.name), "wb")) if self.scaler2 is not None: dump(self.scaler2, open(path / r"{}_scaler2.pkl".format(self.name), "wb"))
# Compile the model lstm_model.compile(loss='categorical_crossentropy', optimizer='RMSProp', metrics=['accuracy']) from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.utils import plot_model plot_model(lstm_model, to_file='model_plot.png', show_shapes=True, show_layer_names=True) """# Model Summary""" # display(X_train.shape) # lstm_model.build( X_train.shape) lstm_model.summary() lstm_model.get_config() """# Check accuracy""" history = lstm_model.fit(X_train, train_label, batch_size=batch_size, epochs=no_epochs, validation_data=(X_test, test_label), shuffle=True, verbose=verbosity) test_loss, test_acc = lstm_model.evaluate(X_test, test_label, verbose=2) print('\nTest accuracy:', test_acc) history = lstm_model.fit(X_train, train_label,
# with open('json_model.json', 'w') as outfile: # json.dump(json_string[0], outfile) #%% JSON to Model # model reconstruction from JSON: from tensorflow.keras.models import model_from_json # with open('json_model.json','r') as json_file: # json_string_new = json.load(json_file) json_model = model_from_json(json_string) json_model.summary() #%% Model.save_weights() import os.path if os.path.isfile('models/ali_model_weights.h5') is False: model.save_weights('models/ali_model_weights.h5') model2 = Sequential([ Dense(units=16, input_shape=(1, ), activation='relu'), Dense(units=32, activation='relu'), Dense(units=2, activation='softmax') ]) model2.load_weights('models/ali_model_weights.h5') model2.get_weights() model2.get_config()
input_ = tf.random.uniform((1, 6, 128)) conv1d = Conv1D(filters=32, kernel_size=3) print(input_.shape) print(conv1d(input_).shape) # 6 timestep을 가진 128 길이의 벡터 # model_conv1.input_shape == (None, 6, 128) model_conv1 = Sequential() model_conv1.add(Conv1D(32, 3, input_shape=(6, 128))) print(model_conv1.input_shape) model_conv1.get_config() """###<font color='red'>잠깐 !</font> > Output shape 계산식 : [(input_size-Kernel_size + padding*2)/stride] + 1 = output_size """ print(model_conv1.get_weights()) # same as model_conv1.variables print(model_conv1.get_weights()[0].shape) # Weights print(model_conv1.get_weights()[1].shape) # Bias model_conv1.summary() tf.keras.utils.plot_model(model_conv1, show_shapes=True) conv1 = Conv1D(32, 3,input_shape=(6, 128))
model.add(Dense(1028, activation="relu")) # Add last layer, i.e. the output layer model.add(Dense(output_dim, activation="softmax")) # Compile the model for loss_metric in ["categorical_crossentropy", "categorical_hinge"]: print("-"*40) print(loss_metric) model.compile(optimizer="sgd", loss=loss_metric, metrics=['accuracy']) # Train the model for batch in [8, 16, 32, 64, 128]: print(batch) model.fit(x=x_train, y=y_train, batch_size=batch, epochs=nb_epoch, verbose=2) # Append each training around accuracy nn_model_train_results_one[model.get_config()['layers'][0]['config']['activation'] + '_' + str(batch) + '_' + model.loss] = model.history.history['accuracy'] # Evaluate the model using the test set score = model.evaluate(x=x_test, y=y_test, verbose=1) print(f"Test score: {score[0]}") print(f"Test accuracy: {score[1]}") # Append training accuracy of each model nn_model_test_results_one[model.get_config()['layers'][0]['config']['activation'] + '_' + str(batch) + '_' + model.loss] = [score[1]] # Create empty DataFrames to append results to nn_model_train_results_two = pd.DataFrame() nn_model_test_results_two = pd.DataFrame() # Create the model object
import data # Generating the data train_validation = 1 / 4 ti_train = data.e2_ti[0:int(np.round(train_validation * len(data.e2_ti)))] te_train = data.e2_te[0:int(np.round(train_validation * len(data.e2_ti)))] q_train = data.e2_q[0:int(np.round(train_validation * len(data.e2_ti)))] # Making the model tf.keras.backend.set_floatx('float64') merged_array = np.stack([ti_train, te_train], axis=1) input_shape = merged_array.shape target_shape = q_train.shape model = Sequential() model.add(layers.Dense(3, input_dim=2, activation='relu')) model.add(layers.Dense(1, activation='linear')) model.compile(loss='mse', optimizer='adam') model.fit(merged_array, q_train, epochs=2000) model.summary() model.get_config() filepath = './saved_model_e2_1_4_1l3' # ANN model 1_4, 1_2 or 2_3 save_model(model, filepath)
def test_CRF(): # data x = np.random.randint(1, embedding_num, nb_samples * timesteps) x = x.reshape((nb_samples, timesteps)) x[0, -4:] = 0 # right padding x[1, :5] = 0 # left padding y = np.random.randint(0, output_dim, nb_samples * timesteps) y = y.reshape((nb_samples, timesteps)) y_onehot = np.eye(output_dim)[y] y = np.expand_dims(y, 2) # .astype('float32') # test with no masking, onehot, fix length model = Sequential() model.add(Embedding(embedding_num, embedding_dim, input_length=timesteps)) crf = CRF(output_dim) model.add(crf) model.compile(optimizer='rmsprop', loss=crf_loss) model.fit(x, y_onehot, epochs=1, batch_size=10) model.save(MODEL_PERSISTENCE_PATH) load_model(MODEL_PERSISTENCE_PATH, custom_objects={ 'CRF': CRF, 'crf_loss': crf_loss, 'crf_viterbi_accuracy': crf_viterbi_accuracy }) # test with masking, sparse target, dynamic length; # test crf_viterbi_accuracy, crf_marginal_accuracy model = Sequential() model.add(Embedding(embedding_num, embedding_dim, mask_zero=True)) crf = CRF(output_dim, sparse_target=True) model.add(crf) model.compile(optimizer='rmsprop', loss=crf_loss, metrics=[crf_viterbi_accuracy, crf_marginal_accuracy]) model.fit(x, y, epochs=1, batch_size=10) # check mask y_pred = model.predict(x).argmax(-1) assert (y_pred[0, -4:] == 0).all() # right padding assert (y_pred[1, :5] == 0).all() # left padding # test viterbi_acc _, v_acc, _ = model.evaluate(x, y) np_acc = (y_pred[x > 0] == y[:, :, 0][x > 0]).astype('float32').mean() print(v_acc, np_acc) assert np.abs(v_acc - np_acc) < 1e-4 # test config model.get_config() # test marginal learn mode, fix length model = Sequential() model.add( Embedding(embedding_num, embedding_dim, input_length=timesteps, mask_zero=True)) crf = CRF(output_dim, learn_mode='marginal', unroll=True) model.add(crf) model.compile(optimizer='rmsprop', loss=crf_loss) model.fit(x, y_onehot, epochs=1, batch_size=10) # check mask (marginal output) y_pred = model.predict(x) assert_allclose(y_pred[0, -4:], 1. / output_dim, atol=1e-6) assert_allclose(y_pred[1, :5], 1. / output_dim, atol=1e-6) # test marginal learn mode, but with Viterbi test_mode model = Sequential() model.add( Embedding(embedding_num, embedding_dim, input_length=timesteps, mask_zero=True)) crf = CRF(output_dim, learn_mode='marginal', test_mode='viterbi') model.add(crf) model.compile(optimizer='rmsprop', loss=crf_loss, metrics=[crf_accuracy]) model.fit(x, y_onehot, epochs=1, batch_size=10) y_pred = model.predict(x) # check y_pred is onehot vector (output from 'viterbi' test mode) assert_allclose(np.eye(output_dim)[y_pred.argmax(-1)], y_pred, atol=1e-6) try: os.remove(MODEL_PERSISTENCE_PATH) except OSError: pass