How to print Recall and Accuracy along with Parameters used in a GridSearch in Sklearn? - pandas

I want to print the accuracy,recall along with each parameters used in Grid, How that can be done.
My Gridsearch code
from sklearn.grid_search import GridSearchCV
rf1=RandomForestClassifier(n_jobs=-1, max_features='sqrt')
#fit_rf1=rf.fit(X_train_res,y_train_res)
# Use a grid over parameters of interest
param_grid = {
"n_estimators" : [50, 100, 150, 200],
"max_depth" : [2, 5, 10],
"min_samples_leaf" : [10,20,30]}
from sklearn.metrics import make_scorer
from sklearn.metrics import precision_score,recall_score
scoring = {'precision': make_scorer(precision_score), 'Recall': make_scorer(recall_score)}
CV_rfc = GridSearchCV(estimator=rf1, param_grid=param_grid, cv= 10,scoring=scoring)
CV_rfc.fit(X_train_res, y_train_res)
My Expected Output
{'max_depth': 10, 'min_samples_leaf': 2, 'n_estimators': 50,'accuracy':.97,'recall':.89}
{'max_depth': 5, 'min_samples_leaf':10 , 'n_estimators': 100,'accuracy':.98,'recall':.92}

If you set scoring as a list of scorers, you can get the mean score for each scorer in CV_rfc.cv_results_.
For example:
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
X, y = make_classification()
base_clf = RandomForestClassifier()
param_grid = {
"n_estimators" : [50, 100, 150, 200],}
CV_rf = GridSearchCV(base_clf, param_grid, scoring=['accuracy', 'roc_auc'], refit=False)
CV_rf.fit(X, y)
print(CV_rf.cv_results_)
and you get output like:
{'mean_fit_time': array([ 0.05867839, 0.10268728, 0.15536443, 0.19937317]),
'mean_score_time': array([ 0.00600123, 0.01033529, 0.0146695 , 0.02000403]),
'mean_test_accuracy': array([ 0.9 , 0.91, 0.89, 0.91]),
'mean_test_roc_auc': array([ 0.91889706, 0.94610294, 0.94253676, 0.94308824]),
'mean_train_accuracy': array([ 1., 1., 1., 1.]),
'mean_train_roc_auc': array([ 1., 1., 1., 1.]),
[...]
}
So the mean_test_[scoring] is what you are after. Note that you can import cv_results_ as a Pandas DataFrame. That helps readability a lot!

Related

How to interpret get_weights for Keras GRU?

I am unable to interpret the results of get_weights from a GRU layer. Here's my code -
#Modified from - https://machinelearningmastery.com/understanding-simple-recurrent-neural-networks-in-keras/
from pandas import read_csv
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, SimpleRNN, GRU
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
import math
import matplotlib.pyplot as plt
model = Sequential()
model.add(GRU(units = 2, input_shape = (3,1), activation = 'linear'))
model.add(Dense(units = 1, activation = 'linear'))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
initial_weights = model.layers[0].get_weights()
print("Shape = ",initial_weights)
I am familiar with GRU concepts. In addition, I understand how the get_weights work for Keras Simple RNN layer, where the first array represents the input weights, the second the activation weights and the third the bias. However, I am lost with output of GRU, which is given below -
Shape = [array([[-0.64266175, -0.0870676 , -0.25356603, -0.03685969, 0.22260845,
-0.04923642]], dtype=float32), array([[ 0.01929092, -0.4932567 , 0.3723044 , -0.6559699 , -0.33790302,
0.27062896],
[-0.4214194 , 0.46456426, 0.27233726, -0.00461334, -0.6533575 ,
-0.32483965]], dtype=float32), array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]], dtype=float32)]
I am assuming it has something to do with GRU gates.
Update:7/4 - This page says that keras GRU has 3 gates, update, reset and output. However, based on this, GRU shouldn't have the output gate.
Best way I know would be to track the add_weight() calls in the build() function of the GRUCell.
Let's take an example model,
model = tf.keras.models.Sequential(
[
tf.keras.layers.GRU(32, input_shape=(5, 10), name='gru'),
tf.keras.layers.Dense(10)
]
)
How we'll print some metadata about what's returned by weights = model.get_layer('gru').get_weights(). Which gives,
Number of arrays in weights: 3
Shape of each array in weights: [(10, 96), (32, 96), (2, 96)]
Let's go back to what weights defined by the GRUCell. We got,
self.kernel = self.add_weight(
shape=(input_dim, self.units * 3),
...
)
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units * 3),
...
)
...
bias_shape = (2, 3 * self.units)
self.bias = self.add_weight(
shape=bias_shape,
...
)
This is what you're seeing as weights (in that order). Here's why they are shaped like this. GRU computations are outlined here.
The first matrix in weights (of shape [10, 96]) is a concatenation of Wz|Wr|Wh (in that order). Each of these is a [10, 32] sized tensor. Concatenation gives a [10, 32*3=96] sized tensor.
Similarly, the second matrix is a concatenation of Uz|Ur|Uh. Each of these is a [32, 32] sized tensor which becomes [32, 96] after concatenation.
You can see how they break this combined weight matrix to each of z, r and h components here.
Finally the bias. It contains 2 biases i.e. [2, 96] sized tensor; input_bias and recurrent_bias. Again, biases from all gates/weights are combined to a single tensor. Typically, only the input_bias is used. But if you have reset_after (decides how the reset gate is applied) set to True, then the recurrent_bias gets used. It's an implementation detail.

How to Calculate Cosine Similarity Using TensorFlow

import pandas as pd
import numpy as np
df = pd.read_csv('shops.csv', sep='|')
df.columns = ['name', # 상호명
'cate_1', # 중분류명
'cate_2', # 소분류명
'cate_3', # 표준산업분류명
'dong', # 행정동명
'lon', # 위도
'lat' # 경도
]
df['cate_mix'] = df['cate_1'] + df['cate_2'] + df['cate_3']
df['cate_mix'] = df['cate_mix'].str.replace("/", " ")
from sklearn.feature_extraction.text import CountVectorizer # 피체 벡터화
from sklearn.metrics.pairwise import cosine_similarity # 코사인 유사도
count_vect_category = CountVectorizer(min_df=0, ngram_range=(1,2))
place_category = count_vect_category.fit_transform(df['cate_mix'])
place_simi_cate = cosine_similarity(place_category, place_category)
place_simi_cate_sorted_ind = place_simi_cate.argsort()[:, ::-1]
At this time, I want to calculate the cosine similarity as above,
via tensorflow
Is there any way to calculate it?
Example:
y_true = [[0., 1.], [1., 1.]]
y_pred = [[1., 0.], [1., 1.]]
cosine_loss = tf.keras.losses.CosineSimilarity(axis=1)
cosine_loss(y_true, y_pred).numpy()
Source: TensorFlow docs

tf.keras.losses.CategoricalCrossentropy gives different values than plain implementation

Any one knows why raw implementation of Categorical Crossentropy function is so different from the tf.keras's api function?
import tensorflow as tf
import math
tf.enable_eager_execution()
y_true =np.array( [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
y_pred = np.array([[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]])
ce = tf.keras.losses.CategoricalCrossentropy()
res = ce(y_true, y_pred).numpy()
print("use api:")
print(res)
print()
print("implementation:")
step1 = -y_true * np.log(y_pred )
step2 = np.sum(step1, axis=1)
print("step1.shape:", step1.shape)
print(step1)
print("sum step1:", np.sum(step1, ))
print("mean step1", np.mean(step1))
print()
print("step2.shape:", step2.shape)
print(step2)
print("sum step2:", np.sum(step2, ))
print("mean step2", np.mean(step2))
Above gives:
use api:
0.3239681124687195
implementation:
step1.shape: (3, 3)
[[0.10536052 0. 0. ]
[0. 0.11653382 0. ]
[0. 0. 0.0618754 ]]
sum step1: 0.2837697356318653
mean step1 0.031529970625762814
step2.shape: (3,)
[0.10536052 0.11653382 0.0618754 ]
sum step2: 0.2837697356318653
mean step2 0.09458991187728844
If now with another y_true and y_pred:
y_true = np.array([[0, 1]])
y_pred = np.array([[0.99999999999, 0.00000000001]])
It gives:
use api:
16.11809539794922
implementation:
step1.shape: (1, 2)
[[-0. 25.32843602]]
sum step1: 25.328436022934504
mean step1 12.664218011467252
step2.shape: (1,)
[25.32843602]
sum step2: 25.328436022934504
mean step2 25.328436022934504
The difference is because of these values: [.5, .89, .6], since it's sum is not equal to 1. I think you have made a mistake and you meant this instead: [.05, .89, .06].
If you provide the values with sum equal to 1, then both formulas results will be the same:
import tensorflow as tf
import numpy as np
y_true = np.array( [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
y_pred = np.array([[.9, .05, .05], [.05, .89, .06], [.05, .01, .94]])
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred).numpy())
print(np.sum(-y_true * np.log(y_pred), axis=1))
#output
#[0.10536052 0.11653382 0.0618754 ]
#[0.10536052 0.11653382 0.0618754 ]
However, let's explore how is calculated if the y_pred tensor is not scaled (the sum of values is not equal to 1)? If you look at the source code of categorical cross entropy here, you will see that it scales y_pred so that the class probas of each sample sum to 1:
if not from_logits:
# scale preds so that the class probas of each sample sum to 1
output /= tf.reduce_sum(output,
reduction_indices=len(output.get_shape()) - 1,
keep_dims=True)
since we passed a pred which the sum of probas is not 1, let's see how this operation changes our tensor [.5, .89, .6]:
output = tf.constant([.5, .89, .6])
output /= tf.reduce_sum(output,
axis=len(output.get_shape()) - 1,
keepdims=True)
print(output.numpy())
# array([0.2512563 , 0.44723618, 0.30150756], dtype=float32)
So, it should be equal if we replace the above operation output (scaled y_pred), and pass it to your own implemented categorical cross entropy, with the unscaled y_pred passing to tensorflow implementation:
y_true =np.array( [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
#unscaled y_pred
y_pred = np.array([[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]])
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred).numpy())
#scaled y_pred (categorical_crossentropy scales above tensor to this internally)
y_pred = np.array([[.9, .05, .05], [0.2512563 , 0.44723618, 0.30150756], [.05, .01, .94]])
print(np.sum(-y_true * np.log(y_pred), axis=1))
Output:
[0.10536052 0.80466845 0.0618754 ]
[0.10536052 0.80466846 0.0618754 ]
Now, let's explore the results of your second example. Why your second example shows different output?
If you check the source code again, you will see this line:
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
which clips values below than a threshold. Your input [0.99999999999, 0.00000000001] will be converted to [0.9999999, 0.0000001] in this line, so it gives you a different result:
y_true = np.array([[0, 1]])
y_pred = np.array([[0.99999999999, 0.00000000001]])
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred).numpy())
print(np.sum(-y_true * np.log(y_pred), axis=1))
#now let's first clip the values less than epsilon, then compare loss
epsilon=1e-7
y_pred = tf.clip_by_value(y_pred, epsilon, 1. - epsilon)
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred).numpy())
print(np.sum(-y_true * np.log(y_pred), axis=1))
Output:
#results without clipping values
[16.11809565]
[25.32843602]
#results after clipping values if there is a value less than epsilon (1e-7)
[16.11809565]
[16.11809565]

From softmax output to class prediction

Is there an easy way to go from a Softmax output to a class prediction?
For instance,
from this:
[0.83128697, 0.06161868, 0.10709436]
to this:
[1, 0, 0]
You can use np.argmax to retrieve the index of max value:
import numpy as np
a = [0.83128697, 0.06161868, 0.10709436]
r = np.zeros(len(a)) # a.size if a is a numpy array
r[np.argmax(a)]=1
r
array([1., 0., 0.])

tflearn to_categorical type error

I keep getting a typeError when I try to use to_categorical from tflearn. The output error is:`
trainY = to_categorical(y = trainY, nb_classes=2)
File "C:\Users\saleh\Anaconda3\lib\site-packages\tflearn\data_utils.py", line 46, in to_categorical
return (y[:, None] == np.unique(y)).astype(np.float32)
TypeError: list indices must be integers or slices, not tuple
This is the reproducible code that I am trying to run:
import tflearn
from tflearn.data_utils import to_categorical
from tflearn.datasets import imdb
#IMDB dataset loading
train, test, _ = imdb.load_data(path = 'imdb.pkl', n_words = 10000, valid_portion = 0.1)
trainX, trainY = train
testX, testY = test
#converting labels to binary vectors
trainY = to_categorical(y = trainY, nb_classes=2) # **This is where I get the error**
testY = to_categorical(y = testY, nb_classes=2)
Cannot reproduce your error:
import tflearn
from tflearn.data_utils import to_categorical
from tflearn.datasets import imdb
train, test, _ = imdb.load_data(path = 'imdb.pkl', n_words = 10000, valid_portion = 0.1)
trainX, trainY = train
testX, testY = test
trainY[0:5]
# [0, 0, 0, 1, 0]
trainY = to_categorical(y = trainY, nb_classes=2)
trainY[0:5]
# array([[ 1., 0.],
# [ 1., 0.],
# [ 1., 0.],
# [ 0., 1.],
# [ 1., 0.]])
System configuration:
Python 2.7.12
Tensorflow 1.3.0
TFLearn 0.3.2
Ubuntu 16.04
UPDATE: It seems that some recent TFLearn commit has broken to_categorical - see here and here. I suggest to uninstall your current version and install the latest stable one with pip install tflearn (this is actually what I have done myself above).