Music classifier model giving same predictions - python

I'm trying to do a music classifier using a CNN model but im always getting same prediction which is wrong
I used the GTZAN dataset of songs
import librosa
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import csv
# Preprocessing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
#Keras
import keras
from keras import models
from keras import layers
# generating a dataset
header = 'filename chroma_stft rmse spectral_centroid spectral_bandwidth rolloff zero_crossing_rate'
for i in range(1, 21):
header += f' mfcc{i}'
header += ' label'
header = header.split()
file = open('data.csv', 'w', newline='')
with file:
writer = csv.writer(file)
writer.writerow(header)
genres = 'blues classical country disco hiphop jazz metal pop reggae rock'.split()
for g in genres:
for filename in os.listdir(f'C:/Users/USER/Desktop/sem8/AI/project/gtzan.keras/data/genres/{g}'):
songname = f'C:/Users/USER/Desktop/sem8/AI/project/gtzan.keras/data/genres/{g}/{filename}'
y, sr = librosa.load(songname, mono=True, duration=30)
chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)
rmse = librosa.feature.rms(y=y)
spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr)
spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr)
rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
zcr = librosa.feature.zero_crossing_rate(y)
mfcc = librosa.feature.mfcc(y=y, sr=sr)
to_append = f'{filename} {np.mean(chroma_stft)} {np.mean(rmse)} {np.mean(spec_cent)} {np.mean(spec_bw)} {np.mean(rolloff)} {np.mean(zcr)}'
for e in mfcc:
to_append += f' {np.mean(e)}'
to_append += f' {g}'
file = open('datatest3.csv', 'a', newline='')
with file:
writer = csv.writer(file)
writer.writerow(to_append.split())
# reading dataset from csv
data = pd.read_csv('datatest3.csv')
data.head()
# Dropping unneccesary columns
data = data.drop(['filename'],axis=1)
data.head()
genre_list = data.iloc[:, -1]
encoder = LabelEncoder()
y = encoder.fit_transform(genre_list)
print(y)
# normalizing
scaler = StandardScaler()
X = scaler.fit_transform(np.array(data.iloc[:, :-1], dtype = float))
# spliting of dataset into train and test dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# creating a model
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_shape=(X_train.shape[1],)))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
history = model.fit(X_train,
y_train,
epochs=20,
batch_size=128)
# calculate accuracy
test_loss, test_acc = model.evaluate(X_test,y_test)
print('test_acc: ',test_acc)
# predictions
predictions = model.predict(X_test)
np.argmax(predictions[0])
This is how i made the csv file
data = pd.read_csv('C:\\Users\\USER\\Desktop\\sem8\\AI\\project\\try\\datatest.csv')
data.head()
genre_list = data.iloc[:, -1]
encoder = LabelEncoder()
y = encoder.fit_transform(genre_list)
print(y)
# normalizing
scaler = StandardScaler()
X = scaler.fit_transform(np.array(data.iloc[:, :-1], dtype = float))
# spliting of dataset into train and test dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# creating a model
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_shape=(X_train.shape[1],)))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.summary()
history = model.fit(X_train,
y_train,
epochs=20,
batch_size=128)
# calculate accuracy
test_loss, test_acc = model.evaluate(X_test,y_test)
print('test_acc: ',test_acc)
# predictions
print(X_test[0])
predictions = model.predict(X_test)
print(np.argmax(predictions[0]))
# model.summary()
model.save("C:\\Users\\USER\\Desktop\\sem8\\AI\\project\\try\\mymodel.h5")
print("Saved model to disk")
Then i created and saved the model
genres = {
'metal': 0, 'disco': 1, 'classical': 2, 'hiphop': 3, 'jazz': 4,
'country': 5, 'pop': 6, 'blues': 7, 'reggae': 8, 'rock': 9
}
def majority_voting(scores, dict_genres):
preds = np.argmax(scores, axis = 1)
values, counts = np.unique(preds, return_counts=True)
counts = np.round(counts/np.sum(counts), 2)
votes = {k:v for k, v in zip(values, counts)}
votes = {k: v for k, v in sorted(votes.items(), key=lambda item: item[1], reverse=True)}
return [(get_genres(x, dict_genres), prob) for x, prob in votes.items()]
def get_genres(key, dict_genres):
# Transforming data to help on transformation
labels = []
tmp_genre = {v:k for k,v in dict_genres.items()}
return tmp_genre[key]
def prepare(filename):
# y, sr = librosa.load(filename, mono=True, duration=30)
# return y
# signal, sr = librosa.load(filename, sr=None)
y, sr = librosa.load(filename, mono=True, duration=30)
chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)
rmse = librosa.feature.rms(y=y)
spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr)
spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr)
rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
zcr = librosa.feature.zero_crossing_rate(y)
mfcc = librosa.feature.mfcc(y=y, sr=sr)
to_append = f'{np.mean(chroma_stft)} {np.mean(rmse)} {np.mean(spec_cent)} {np.mean(spec_bw)} {np.mean(rolloff)} {np.mean(zcr)}'
for e in mfcc:
to_append += f' {np.mean(e)}'
# Append the result to the data structure
# features = get_features(signal, sr)
song = pd.DataFrame([to_append.split()])
return song
model=models.load_model("C:\\Users\\USER\\Desktop\\sem8\\AI\\project\\try\\mymodel.h5")
print(prepare("C:\\Users\\USER\\Desktop\\sem8\\AI\\project\\try\\song1.mp3"))
newsong=prepare("C:\\Users\\USER\\Desktop\\sem8\\AI\\project\\try\\song1.mp3")
song = (np.array(newsong)).reshape(26)
print(song.shape)
print(song)
prediction = model.predict(song)
votes = majority_voting(prediction, genres)
print("This song is a {} song".format(votes[0][0]))
print("most likely genres are: {}".format(votes[:3]))
print(prediction)
This is how im trying to predict
and im always getting same result
And i think everything i did is correct
This song is a hiphop song
most likely genres are: [('hiphop', 1.0)]
[[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]]

The problem is in normalizing the data for prediction, it should be shaped just like the data that is used for training with the standardscaler

Related

Cannot transform list into tensor: ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list)

I really need your help, I have been trying to figure it out but still no way out of the problem.. I can read the dataset(like the picture, using pandas), but cant make this turns into a tensor, tried lots of different ways to make the list to tensor, or array, matrix.., but none worked..
Do you have some idea how can I change my csv reading to make the data fit into the tensodflow?
import sys
import numpy as np
from numpy import array
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from scipy.sparse import csr_matrix
import re
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from pandas import Series
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from numpy import array
from keras.models import load_model
from sklearn import datasets
df = pd.read_csv('set1.csv')
#conversão lista em tensor
def my_func(arg):
arg = tf.convert_to_tensor(arg, dtype=tf.float32)
return arg
#Uma vgez, e a lista STR é convertida em lista
s1 = df["sensor1"].apply(eval)
s2 = df["sensor2"].apply(eval)
s3 = df["sensor3"].apply(eval)
X = (s1, s2, s3)
X = np.matrix(X)
X = X.transpose()
Y = pd.get_dummies(data=df.categoria).values
#print("shape Y:",(Y.shape), " tipo Y:" ,(type(Y)), "len Y:", len(Y))
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.1, random_state = 42)
print("Train Shape:", X_train.shape,Y_train.shape)
print("Test Shape:", X_test.shape,Y_test.shape)
def model():
if pre_trained_wv is True:
print("USE PRE TRAINED")
#num_words = min(max_features, len(word_index) + 1)
#num_words
weights_embedding_matrix = load_pre_trained_wv(word_index, num_words, word_embedding_dim)
input_shape = (max_sequence_length,)
model_input = Input(shape=input_shape, name="input", dtype='float64')
embedding = Embedding(
num_words,
word_embedding_dim,
input_length=max_sequence_length,
name="embedding",
weights=[weights_embedding_matrix],
trainable=False)(model_input)
#if bilstm is True:
# lstm = Bidirectional(LSTM(word_embedding_dim, dropout=0.2, recurrent_dropout=0.2, name="lstm"))(embedding)
#else:
lstm = LSTM(word_embedding_dim, dropout=0.2, recurrent_dropout=0.2, name="lstm")(embedding)
else:
input_shape = (max_sequence_length,)
#model_input = Input(shape=input_shape, name="input", dtype='int32')
model_input = Input(shape=input_shape, name="input")
embedding = Embedding(max_features, embed_dim, input_length=max_sequence_length, name="embedding")(model_input)
#if bilstm is True:
# lstm = Bidirectional(LSTM(embed_dim, dropout=0.2, recurrent_dropout=0.2, name="lstm"))(embedding)
#else:
lstm = LSTM(embed_dim, dropout=0.2, recurrent_dropout=0.2, name="lstm")(embedding)
model_output = Dense(2, activation='softmax', name="softmax")(lstm)
model = Model(inputs=model_input, outputs=model_output)
return model
model = model()
model.compile(loss = 'binary_crossentropy', optimizer='adam', metrics = ['accuracy'])
print(model.summary())
if not os.path.exists('./{}'.format(filename) ):
hist = model.fit(
X_train,
Y_train,
validation_data=(X_test, Y_test),
epochs=epochs,
batch_size=batch_size,
shuffle=True,
verbose=1)
model.save_weights(filename)
# Plot
plt.figure()
plt.plot(hist.history['loss'], lw=2.0, color='b', label='train')
plt.plot(hist.history['val_loss'], lw=2.0, color='r', label='val')
plt.title('Classificador de Gestos')
plt.xlabel('Epochs')
plt.ylabel('Cross-Entropy')
plt.legend(loc='upper right')
plt.show()
plt.figure()
plt.plot(hist.history['acc'], lw=2.0, color='b', label='train')
plt.plot(hist.history['val_acc'], lw=2.0, color='r', label='val')
plt.title('Classificador de Gestos')
plt.xlabel('Epochs')
plt.ylabel('Acurácia')
plt.legend(loc='upper left')
plt.show()
else:
model.load_weights('./{}'.format(filename) )
scores = model.evaluate(X_test, Y_test, verbose = 0, batch_size = batch_size)
print("Acc: %.2f%%" % (scores[1]*100))
while True:
sentence = input("input> ")
if sentence == "exit":
break
new_text = pad_sequences(new_text, maxlen=max_sequence_length, dtype='float64', value=0)
#new_text = pad_sequences(new_text, maxlen=max_sequence_length, value=0)
sentiment = model.predict(new_text,batch_size=1,verbose = 2)[0]
if(np.argmax(sentiment) == 0):
pred_proba = "%.2f%%" % (sentiment[0]*100)
print("movimento para direita => ", pred_proba)
elif (np.argmax(sentiment) == 1):
pred_proba = "%.2f%%" % (sentiment[1]*100)
print("movimento para esquerda => ", pred_proba)
this is the csv file:
CSV

How do I use custom CSV in my code instead of Yahoo Finance data?

I'm building a stock prediction neural network. The tutorial i was watching was importing the stock data from yahoo finance. I want to improve the code by making it fetch the data from a CSV file so the code can be used even if you are not connected to the internet.
What do I need to change In my code to have it use custom data from a CSV file?
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pandas_datareader as web
import datetime as dt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, LSTM
company = '^GDAXI'
start = dt.datetime(2012,1,1)
end = dt.datetime(2021,1,1)
data = web.DataReader(company, 'yahoo', start, end)
scaler = MinMaxScaler(feature_range=(0,1))
scaled_data = scaler.fit_transform(data['Close'].values.reshape(-1, 1))
prediction_days = 60
x_train = []
y_train = []
for x in range(prediction_days, len(scaled_data)):
x_train.append(scaled_data[x-prediction_days:x, 0])
y_train.append(scaled_data[x, 0])
x_train, y_train = np.array(x_train), np.array(y_train)
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
#BUILD MODEL
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape[1], 1)))
model.add(Dropout(0.2))
model.add(LSTM(units=50, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=50))
model.add(Dropout(0.2))
model.add(Dense(units=1)) #next day prediction
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(x_train, y_train, epochs=25, batch_size=32)
#TEST ON EXISTING DATA
test_start = dt.datetime(2020,1,1)
test_end = dt.datetime.now()
test_dataset = web.DataReader(company, 'yahoo', test_start, test_end)
actual_prices = test_dataset['Close'].values
total_dataset = pd.concat((data['Close'], test_dataset['Close']), axis=0)
model_inputs = total_dataset[len(total_dataset)-len(test_dataset)-prediction_days:].values
model_inputs = model_inputs.reshape(-1,1)
model_inputs = scaler.transform(model_inputs)
#PREDICTIONS ON TEST DATA
x_test = []
for x in range(prediction_days, len(model_inputs)):
x_test.append(model_inputs[x-prediction_days:x, 0])
x_test = np.array(x_test)
x_test = np.reshape(x_test,(x_test.shape[0], x_test.shape[1],1))
predicted_prices = model.predict(x_test)
predicted_prices = scaler.inverse_transform(predicted_prices)
#PLOT
plt.plot(actual_prices, color="green", label="Actual Price")
plt.plot(predicted_prices, color="blue", label="Predicted Price")
plt.title("GER40 Share Price")
plt.xlabel('Time')
plt.ylabel('GER40 Price')
plt.legend()
plt.show()
#Predict Next Day
real_dataset = [model_inputs[len(model_inputs)+1-prediction_days:len(model_inputs+1), 0]]
real_dataset = np.array(real_dataset)
real_dataset = np.reshape(real_dataset, (real_dataset.shape[0], real_dataset.shape[1], 1))
prediction = model.predict(real_dataset)
prediction = scaler.inverse_transform(prediction)
print(f"Close: {prediction}")
The CSV file i'm using doesn't have headings, but i think i can add those using excel
I think you should consider doing it this way.
from pandas_datareader import data as wb
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pylab import rcParams
from sklearn.preprocessing import MinMaxScaler
start = '2019-06-30'
end = '2020-06-30'
tickers = ['GOOG']
thelen = len(tickers)
price_data = []
for ticker in tickers:
prices = wb.DataReader(ticker, start = start, end = end, data_source='yahoo')[['Open','Adj Close']]
price_data.append(prices.assign(ticker=ticker)[['ticker', 'Open', 'Adj Close']])
#names = np.reshape(price_data, (len(price_data), 1))
df = pd.concat(price_data)
df.reset_index(inplace=True)
for col in df.columns:
print(col)
#used for setting the output figure size
rcParams['figure.figsize'] = 20,10
#to normalize the given input data
scaler = MinMaxScaler(feature_range=(0, 1))
#to read input data set (place the file name inside ' ') as shown below
df['Adj Close'].plot()
plt.legend(loc=2)
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()
ntrain = 80
df_train = df.head(int(len(df)*(ntrain/100)))
ntest = -80
df_test = df.tail(int(len(df)*(ntest/100)))
#importing the packages
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM
#dataframe creation
seriesdata = df.sort_index(ascending=True, axis=0)
new_seriesdata = pd.DataFrame(index=range(0,len(df)),columns=['Date','Adj Close'])
length_of_data=len(seriesdata)
for i in range(0,length_of_data):
new_seriesdata['Date'][i] = seriesdata['Date'][i]
new_seriesdata['Adj Close'][i] = seriesdata['Adj Close'][i]
#setting the index again
new_seriesdata.index = new_seriesdata.Date
new_seriesdata.drop('Date', axis=1, inplace=True)
#creating train and test sets this comprises the entire data’s present in the dataset
myseriesdataset = new_seriesdata.values
totrain = myseriesdataset[0:255,:]
tovalid = myseriesdataset[255:,:]
#converting dataset into x_train and y_train
scalerdata = MinMaxScaler(feature_range=(0, 1))
scale_data = scalerdata.fit_transform(myseriesdataset)
x_totrain, y_totrain = [], []
length_of_totrain=len(totrain)
for i in range(60,length_of_totrain):
x_totrain.append(scale_data[i-60:i,0])
y_totrain.append(scale_data[i,0])
x_totrain, y_totrain = np.array(x_totrain), np.array(y_totrain)
x_totrain = np.reshape(x_totrain, (x_totrain.shape[0],x_totrain.shape[1],1))
#LSTM neural network
lstm_model = Sequential()
lstm_model.add(LSTM(units=50, return_sequences=True, input_shape=(x_totrain.shape[1],1)))
lstm_model.add(LSTM(units=50))
lstm_model.add(Dense(1))
lstm_model.compile(loss='mean_squared_error', optimizer='adadelta')
lstm_model.fit(x_totrain, y_totrain, epochs=10, batch_size=1, verbose=2)
#predicting next data stock price
myinputs = new_seriesdata[len(new_seriesdata) - (len(tovalid)+1) - 60:].values
myinputs = myinputs.reshape(-1,1)
myinputs = scalerdata.transform(myinputs)
tostore_test_result = []
for i in range(60,myinputs.shape[0]):
tostore_test_result.append(myinputs[i-60:i,0])
tostore_test_result = np.array(tostore_test_result)
tostore_test_result = np.reshape(tostore_test_result,(tostore_test_result.shape[0],tostore_test_result.shape[1],1))
myclosing_priceresult = lstm_model.predict(tostore_test_result)
myclosing_priceresult = scalerdata.inverse_transform(myclosing_priceresult)
totrain = df_train
tovalid = df_test
#predicting next data stock price
myinputs = new_seriesdata[len(new_seriesdata) - (len(tovalid)+1) - 60:].values
# Printing the next day’s predicted stock price.
print(len(tostore_test_result));
print(myclosing_priceresult);
Final Result:
[[1396.532]]

Converting numeric labels back to original strings

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
data = pd.read_csv('data/TrainingData_unsubscribe.csv')
data['labels'] = data['Category'].factorize()[0]
#vectorize the features
tfidf = TfidfVectorizer(sublinear_tf=True, min_df=5, norm='l2', encoding='latin-1', stop_words='english')
x_vectors = tfidf.fit_transform(data.msgContent)
#split the data
x = x_vectors
y = data.labels
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size=0.2, random_state=42)
x_train = x_train.toarray()
x_train.shape
x.shape
x_test = x_test.toarray()
preds = x_vectors.toarray()
#Random seed and callback
stop = tf.keras.callbacks.EarlyStopping(monitor='accuracy', patience=10)
#create the model
model = tf.keras.Sequential([
tf.keras.layers.Dense(100, activation='relu'),
tf.keras.layers.Dense(100, activation='relu'),
tf.keras.layers.Dense(100, activation='relu'),
tf.keras.layers.Dense(len(pd.unique(y)), activation='softmax')
])
#compile the model
model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(),
optimizer = tf.keras.optimizers.Adam(),
metrics=['accuracy'])
#fit the model
model.fit(x_train,y_train, epochs=500, verbose=0, callbacks=[stop])
#elavuation
print('\nEvaluation: ')
model.evaluate(x_test,y_test)
predictions = model.predict(preds)
len(pd.unique(y))
data["Prediction"] = predictions.argmax(axis=1)
output = data.drop(["labels"], axis=1)
category_ids = data[["Category", "labels"]].drop_duplicates()
output['Prediction'] =
Originally converted string labels to numeric ones using factorize():
data['labels'] = data['Category'].factorize()[0]
Now I'm trying to convert the labels back to their initial string variables. I've created a DF with the mapped values
Category
labels
HardBounce
0
SoftBounce
1
etc...
is it possible to map a df column using another df as a reference for the map?
I've been unable to find any docs that show how to do this.

How to loop through various train and test splits

I have various train and test splits that I create using TimeSeriesSplit(). My dataframe has 377 observations with 6 input variables and 1 target variable.
I split my dataframe into train and test using the following code:
#train set
i=0
for X_train, X_test in tscv.split(data):
i=i+1
print ("No of observations under train%s=%s"%(i,len(X_train)))
print ("No of observations under test%s=%s" % (i, len(X_test)))
X_train1, X_test1 = data[:67, :-1], data[67:129,:-1]
X_train2, X_test2 = data[:129,:-1], data[129:191,:-1]
X_train3, X_test3 = data[:191,:-1], data[191:253,:-1]
X_train4, X_test4 = data[:253,:-1], data[253:315,:-1]
X_train5, X_test5 = data[:315,:-1], data[315:377,:-1]
#test set
i=0
for y_train, y_test in tscv.split(data):
i=i+1
print ("No of observations under train%s=%s"%(i,len(y_train)))
print ("No of observations under test%s=%s" % (i, len(y_test)))
y_train1, y_test1 = data[:67, -1], data[67:129 ,-1]
y_train2, y_test2 = data[:129,-1], data[129:191,-1]
y_train3, y_test3 = data[:191,-1], data[191:253,-1]
y_train4, y_test4 = data[:253,-1], data[253:315,-1]
y_train5, y_test5 = data[:315,-1], data[315:377,-1]
So i have 5 splits in total. I want to train my lstm model looping through these splits but I am not sure how best I can do that. Here’s the code for my lstm:
# split into input and outputs
train_X, train_y = X_train, y_train
test_X, test_y = X_test, y_test
#reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,LSTM, Flatten
import matplotlib.pyplot as pyplot
# design network
model = Sequential()
model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
history = model.fit(train_X, train_y, epochs=700
, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# plot history
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()
#predictions
y_lstm = model.predict(test_X)
#metrics for test set
mse_lstm = mean_squared_error(y_test, y_lstm)
rmse_lstm = np.sqrt(mse_lstm)
r2_lstm = r2_score(y_test, y_lstm)
mae_lstm = mean_absolute_error(y_test, y_lstm)
#train metics
train = model.predict(X_t_reshaped)
msetrain = mean_squared_error(y_train, train)
rmsetrain = np.sqrt(msetrain)
r2train = r2_score(y_train, train)
What can I do to use the above code to loop through all my different splits and store the results in a list or dataframe?
I want to also plot the predicted results as shown below
This is the grapgh am getting based on #Ashraful answer
Replace your last Code block using this,
from sklearn.metrics import mean_squared_error
from sklearn.metrics import *
import numpy as np
import csv
Round = 3 # define the number of digits after decimal point you want
fields = ['Fold_No', 'mse_lstm', 'rmse_lstm', 'r2_lstm','mae_lstm']
csvfile = open('Summary.csv', 'w')
csvwriter = csv.writer(csvfile)
csvwriter.writerow(fields)
for fold in range(1,6):
print(f'Running fold {fold}')
# split into input and outputs
train_X, train_y = eval(f'X_train{fold}'),eval(f'y_train{fold}')
test_X, test_y = eval(f'X_test{fold}'),eval(f'y_test{fold}')
print(train_X.shape)
#reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,LSTM, Flatten
import matplotlib.pyplot as pyplot
# design network
model = Sequential()
model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
history = model.fit(train_X, train_y, epochs=2
, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# plot history
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()
#predictions
train_output = model.predict(train_X)
y_lstm = model.predict(test_X)
pyplot.plot(train_output, label='Training output')
pyplot.plot(train_y, label='Obesrved Training Target')
# pyplot.plot(train_y, label='Training value')
pyplot.plot(test_y, label='Obesrved Predic. Target')
pyplot.plot(y_lstm, label='Predicted Output')
pyplot.legend(loc='upper right')
# pyplot.legend()
pyplot.show()
#metrics for test set
mse_lstm = mean_squared_error(y_test1, y_lstm)
rmse_lstm = np.sqrt(mse_lstm)
r2_lstm = r2_score(y_test1, y_lstm)
mae_lstm = mean_absolute_error(y_test1, y_lstm)
csvwriter.writerow([f'Fold_{fold}',round(mse_lstm,Round), round(rmse_lstm,Round), round(r2_lstm,Round),round(mae_lstm,Round)])
csvfile.close()
#read stored CSV file
summary= pd.read_csv('Summary.csv')
print(summary)
Also, my implementatin in colab file you can find here.

Prediction with LSTM using Keras

I am predicting Y based on X from past values. Our formatted CSV dataset has three columns (time_stamp, X and Y - where Y is the actual value) whose sample format is
time,X,Y
0.000561,0,10
0.000584,0,10
0.040411,5,10
0.040437,10,10
0.041638,12,10
0.041668,14,10
0.041895,15,10
0.041906,19,10
... ... ...
Before training the prediction model, here is how the plots of X and Y respectively look like the following.
Here is how I approached the problem with LSTM Recurrent Neural Networks in Python with Keras.
import numpy as np
from keras.models import Sequential
from keras.layers import LSTM, Dense
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
np.random.seed(7)
# Load data
df = pd.read_csv('test32_C_data.csv')
n_features = 100
def create_sequences(data, window=15, step=1, prediction_distance=15):
x = []
y = []
for i in range(0, len(data) - window - prediction_distance, step):
x.append(data[i:i + window])
y.append(data[i + window + prediction_distance][1])
x, y = np.asarray(x), np.asarray(y)
return x, y
# Scaling prior to splitting
scaler = MinMaxScaler(feature_range=(0.01, 0.99))
scaled_data = scaler.fit_transform(df.loc[:, ["X", "Y"]].values)
# Build sequences
x_sequence, y_sequence = create_sequences(scaled_data)
# Create test/train split
test_len = int(len(x_sequence) * 0.90)
valid_len = int(len(x_sequence) * 0.90)
train_end = len(x_sequence) - (test_len + valid_len)
x_train, y_train = x_sequence[:train_end], y_sequence[:train_end]
x_valid, y_valid = x_sequence[train_end:train_end + valid_len], y_sequence[train_end:train_end + valid_len]
x_test, y_test = x_sequence[train_end + valid_len:], y_sequence[train_end + valid_len:]
# Initialising the RNN
model = Sequential()
# Adding the input layerand the LSTM layer
model.add(LSTM(15, input_shape=(15, 2)))
# Adding the output layer
model.add(Dense(1))
# Compiling the RNN
model.compile(loss='mse', optimizer='rmsprop')
# Fitting the RNN to the Training set
model.fit(x_train, y_train, epochs=5)
# Getting the predicted values
y_pred = model.predict(x_test)
#y_pred = scaler.inverse_transform(y_pred)
plot_colors = ['#332288', '#3cb44b']
# Plot the results
pd.DataFrame({"Actual": y_test, "Predicted": np.squeeze(y_pred)}).plot(color=plot_colors)
plt.xlabel('Time [Index]')
plt.ylabel('Values')
Finally, when I run the code - the neural model seems to capture the pattern of the signal well as it is shown below.
However, one problem that I encountered in this output is the ranges of Y. As it is shown in the first two plots, the ranges should be 0-400 as shown above and to solve that I tried to use the scaler to inverse_transform as y_pred = scaler.inverse_transform(y_pred) but this throws an error: ValueError: non-broadcastable output operand with shape (7625,1) doesn't match the broadcast shape (7625,2). How can we solve this broadcast shape error?
Basically, the scaler has remembered that it was fed 2 features(/columns). So it is expecting 2 features to invert the transformation.
Two options here.
1) You make two different scalers: scaler_x and scaler_y like this :
# Scaling prior to splitting
scaler_x = MinMaxScaler(feature_range=(0.01, 0.99))
scaler_y = MinMaxScaler(feature_range=(0.01, 0.99))
scaled_x = scaler_x.fit_transform(df.loc[:, "X"].reshape([-1, 1]))
scaled_y = scaler_y.fit_transform(df.loc[:, "Y"].reshape([-1, 1]))
scaled_data = np.column_stack((scaled_x, scaled_y))
Then you will be able to do :
y_pred = scaler_y.inverse_transform(y_pred)
2) You fake the X column in your output like this :
y_pred_reshaped = np.zeros((len(y_pred), 2))
y_pred_reshaped[:,1] = y_pred
y_pred = scaler.inverse_transform(y_pred_reshaped)[:,1]
Does that help?
EDIT
here is the full code as required
import numpy as np
from keras.models import Sequential
from keras.layers import LSTM, Dense
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
np.random.seed(7)
# Load data
#df = pd.read_csv('test32_C_data.csv')
df = pd.DataFrame(np.random.randint(0,100, size=(100,3)), columns = ['time', 'X', 'Y'])
n_features = 100
def create_sequences(data, window=15, step=1, prediction_distance=15):
x = []
y = []
for i in range(0, len(data) - window - prediction_distance, step):
x.append(data[i:i + window])
y.append(data[i + window + prediction_distance][1])
x, y = np.asarray(x), np.asarray(y)
return x, y
# Scaling prior to splitting
scaler_x = MinMaxScaler(feature_range=(0.01, 0.99))
scaler_y = MinMaxScaler(feature_range=(0.01, 0.99))
scaled_x = scaler_x.fit_transform(df.loc[:, "X"].reshape([-1,1]))
scaled_y = scaler_y.fit_transform(df.loc[:, "Y"].reshape([-1,1]))
scaled_data = np.column_stack((scaled_x, scaled_y))
# Build sequences
x_sequence, y_sequence = create_sequences(scaled_data)
test_len = int(len(x_sequence) * 0.90)
valid_len = int(len(x_sequence) * 0.90)
train_end = len(x_sequence) - (test_len + valid_len)
x_train, y_train = x_sequence[:train_end], y_sequence[:train_end]
x_valid, y_valid = x_sequence[train_end:train_end + valid_len], y_sequence[train_end:train_end + valid_len]
x_test, y_test = x_sequence[train_end + valid_len:], y_sequence[train_end + valid_len:]
# Initialising the RNN
model = Sequential()
# Adding the input layerand the LSTM layer
model.add(LSTM(15, input_shape=(15, 2)))
# Adding the output layer
model.add(Dense(1))
# Compiling the RNN
model.compile(loss='mse', optimizer='rmsprop')
# Fitting the RNN to the Training set
model.fit(x_train, y_train, epochs=5)
# Getting the predicted values
y_pred = model.predict(x_test)
y_pred = scaler_y.inverse_transform(y_pred)

Categories