Related
I am attempting to implement a neural network using Keras with a problem that involves multilabel classification. I understand that one way to tackle the problem is to transform it to several binary classification problems. I have implemented one of these, but am not sure how to proceed with the others, mostly how do I go about combining them? My data set has 5 input variables and 5 labels. Generally a single sample of data would have 1-2 labels. It is rare to have more than two labels.
Here is my code (thanks to machinelearningmastery.com):
import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load dataset
dataframe = pandas.read_csv("Realdata.csv", header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:5].astype(float)
Y = dataset[:,5]
# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# baseline model
def create_baseline():
# create model
model = Sequential()
model.add(Dense(5, input_dim=5, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
scores = model.evaluate(X, encoded_Y)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
#Make predictions....change the model.predict to whatever you want instead of X
predictions = model.predict(X)
# round predictions
rounded = [round(x[0]) for x in predictions]
print(rounded)
return model
# evaluate model with standardized dataset
estimator = KerasClassifier(build_fn=create_baseline, epochs=100, batch_size=5, verbose=0)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(estimator, X, encoded_Y, cv=kfold)
print("Results: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
The approach you are referring to is the one-versus-all or the one-versus-one strategy for multi-label classification. However, when using a neural network, the easiest solution for a multi-label classification problem with 5 labels is to use a single model with 5 output nodes. With keras:
model = Sequential()
model.add(Dense(5, input_dim=5, kernel_initializer='normal', activation='relu'))
model.add(Dense(5, kernel_initializer='normal', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='sgd')
You can provide the training labels as binary-encoded vectors of length 5. For instance, an example that corresponds to classes 2 and 3 would have the label [0 1 1 0 0].
I'm working my way through the Deep Learning with Python book where there is an example for learning word embeddings for sentiment:
from keras.datasets import imdb
from keras import preprocessing
max_features = 10000
maxlen = 20
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)
from keras.models import Sequential
from keras.layers import Flatten, Dense
model = Sequential()
model.add(Embedding(10000, 8, input_length=maxlen))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary()
history = model.fit(x_train, y_train,
epochs=10,
batch_size=32,
validation_split=0.2)
I would like to pass in a sentence and make a prediction on the sentiment. My first thought was to pass in an array of indices (because that's how the works are represented in the model if I have understood correctly) such as:
import numpy as np
# does this reflect a really bad review?
model.predict(np.array([[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]]))
[out] array([[ 0.0066505]], dtype=float32)
# does this reflect a really good review?
model.predict(np.array([[9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999 ]]))
[out] array([[ 0.64767915]], dtype=float32)
How can I pass in a list of words instead of indices? I.e. how can I retrieve a list of word indices for my new sentence?
Update - I tried to tokenize some words:
def index(word):
if word in word_index:
return word_index[word]
else:
return "0"
def sequences(words):
words = text_to_word_sequence(words)
seqs = [[index(word) for word in words if word != "0"]]
return preprocessing.sequence.pad_sequences(seqs, maxlen=maxlen)
bad_seq = sequences("Rubbish terrible awful dreadful hate stinks")
good_seq = sequences("Awesome recommended brilliant best")
print("bad movie: " + str(model.predict(bad_seq))) # 0.00759153
print("good movie: " + str(model.predict(good_seq))) # 0.00423771
The sentiment is very similar which suggests that the tokenizing approach does not work.
i am trying to build a deep learning network based on LSTM RNN
here is what is tried
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import LSTM
import numpy as np
train = np.loadtxt("TrainDatasetFinal.txt", delimiter=",")
test = np.loadtxt("testDatasetFinal.txt", delimiter=",")
y_train = train[:,7]
y_test = test[:,7]
train_spec = train[:,6]
test_spec = test[:,6]
model = Sequential()
model.add(LSTM(32, input_shape=(1415684, 8)))
model.add(LSTM(64, input_dim=1, input_length=1415684, return_sequences=True))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop')
model.fit(train_spec, y_train, batch_size=2000, nb_epoch=11)
score = model.evaluate(test_spec, y_test, batch_size=2000)
but it gets me the following error
ValueError: Input 0 is incompatible with layer lstm_2: expected ndim=3, found ndim=2
Here is a sample from the dataset
(Patient Number, time in millisecond, accelerometer x-axis,y-axis, z-axis,magnitude, spectrogram,label (0 or 1))
1,15,70,39,-970,947321,596768455815000,0
1,31,70,39,-970,947321,612882670787000,0
1,46,60,49,-960,927601,602179976392000,0
1,62,60,49,-960,927601,808020878060000,0
1,78,50,39,-960,925621,726154800929000,0
in the dataset i am using the only the spectrogram as input feature and the label (0 or 1) as the output
the total traing samples is 1,415,684
I am new to Keras and RNN
I need to build a Classifier Model using LSTM RNN in Keras for a Dataset that contain a train set of shape (1795575, 6) and labels array of shape (1795575, 1).The labels is 11 class (from 0 to 10)
The test set of shape (575643, 6) and Labels array of shape (575643, 1.Again, the labels is 11 (from 0 to 10)
How can I shape the following Keras Model to satisfy my Dataset.What Values should I put for ?
from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.optimizers import SGD
import numpy as np
data_dim = ?
timesteps = ?
num_classes = ?
batch_size = ?
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model = Sequential()
model.add(LSTM(32, return_sequences=True, stateful=True,batch_input_shape=
(batch_size, timesteps, data_dim)))
model.add(LSTM(32, return_sequences=True, stateful=True))
model.add(LSTM(32, stateful=True))
model.add(Dense(?, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy',optimizer='sgd',
metrics=['accuracy'])
model.fit(train_X_arr, train_y_arr,batch_size=batch_size, epochs=epochs,
shuffle=False,validation_data=(test_X_arr, test_y_arr))
I appreciate your help and Thanks in advance
What you would like to do is this:
from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.optimizers import SGD
import numpy as np
data_dim = 1 # EACH TIMESTAMP IS SCALAR SO SHAPE=1
timesteps = 6 # EACH EXAMPLE CONTAINS 6 TIMESTAMPS
num_classes = 1 # EACH LABEL IS ONE NUMBER SO SHAPE=1
batch_size = 1 # TAKE SIZE THAT CAN DIVIDE THE NUMBER OF EXAMPLES IN THE TRAIN DATA. THE HIGHER THE BATCH SIZE THE BETTER!
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model = Sequential()
model.add(LSTM(32, return_sequences=True, stateful=True,batch_input_shape=
(batch_size, timesteps, data_dim)))
model.add(LSTM(32, return_sequences=True, stateful=True))
model.add(LSTM(32, stateful=True))
model.add(Dense(1, activation='softmax')) # AT THE END YOU WANT ONE VALUE (LIKE THE LABELS) -> SO DENSE SHOULD OUTPUT 1 NODE
model.compile(loss='sparse_categorical_crossentropy',optimizer='sgd',
metrics=['accuracy'])
model.fit(train_X_arr, train_y_arr,batch_size=batch_size, epochs=epochs,
shuffle=False,validation_data=(test_X_arr, test_y_arr))
and that's it.
EDIT: In addition, make sure that you reshape your train data to be: (1795575, 6,1) -> 1795575 examples, each has 6 timestamps, each timestamps is scalar.
You can achieve that easily by using np.expand_dims(train_data,-1).
I am running keras over tensorflow, trying to implement a multi-dimensional LSTM network to predict a linear continuous target variable , a single value for each example(return_sequences = False).
My sequence length is 10 and number of features (dim) is 11.
This is what I run:
import pprint, pickle
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
# Input sequence
wholeSequence = [[0,0,0,0,0,0,0,0,0,2,1],
[0,0,0,0,0,0,0,0,2,1,0],
[0,0,0,0,0,0,0,2,1,0,0],
[0,0,0,0,0,0,2,1,0,0,0],
[0,0,0,0,0,2,1,0,0,0,0],
[0,0,0,0,2,1,0,0,0,0,0],
[0,0,0,2,1,0,0,0,0,0,0],
[0,0,2,1,0,0,0,0,0,0,0],
[0,2,1,0,0,0,0,0,0,0,0],
[2,1,0,0,0,0,0,0,0,0,0]]
# Preprocess Data:
wholeSequence = np.array(wholeSequence, dtype=float) # Convert to NP array.
data = wholeSequence
target = np.array([20])
# Reshape training data for Keras LSTM model
data = data.reshape(1, 10, 11)
target = target.reshape(1, 1, 1)
# Build Model
model = Sequential()
model.add(LSTM(11, input_shape=(10, 11), unroll=True, return_sequences=False))
model.add(Dense(11))
model.add(Activation('linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(data, target, nb_epoch=1, batch_size=1, verbose=2)
and get the error ValueError: Error when checking target: expected activation_1 to have 2 dimensions, but got array with shape (1, 1, 1)
Not sure what should the activation layer should get (shape wise)
Any help appreciated
thanks
If you just want to have a single linear output neuron, you can simply use a dense layer with one hidden unit and supply the activation there. Your output then can be a single vector without the reshape- I adjusted your given example code to make it work:
wholeSequence = np.array(wholeSequence, dtype=float) # Convert to NP array.
data = wholeSequence
target = np.array([20])
# Reshape training data for Keras LSTM model
data = data.reshape(1, 10, 11)
# Build Model
model = Sequential()
model.add(LSTM(11, input_shape=(10, 11), unroll=True, return_sequences=False))
model.add(Dense(1, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(data, target, nb_epoch=1, batch_size=1, verbose=2)