My goal is to achieve a pooling layer prototxt from code as follows:
layer {
name: "my_pooling"
type: "Pooling_Custom"
bottom: "conv1"
top: "my_pooling"
pooling_custom_param {
pool: MAX
kernel_size: 2
stride: 2
engine : CAFFE
}
}
where Pooking_Custom and pooling_custom_param are my modify Pooling. I want to use python to generate above output. I am using NetSpec to do it:
from caffe import params as P
n = caffe.NetSpec()
my_pooling = L.Pooling(conv1, type="Pooling_Custom", pool=P.Pooling.MAX, kernel_size=2, stride=2, engine=1)
However, I cannot generate pooling_custom_param. How can I do it? My current result is
layer {
name: "my_pooling"
type: "Pooling_Custom"
bottom: "conv1"
top: "my_pooling"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
engine : CAFFE
}
}
If you're doing this as a subtype of Pooling, you can't: those attribute names are defined by the parent template. All you can change are the values (right side of each item, after the colon).
The functional reason is that you're incorporating methods from the parent class in which those field names are hard-coded. For instance, there will be something that refers to pooling_param["kernel_size"]. If you have changed the name to pooling_custom_param, you need to also reconfigure that software ... and that's outside the language's software implementation.
If you really need to change that attribute name, you're welcome to clone the entire Pooling class, make the change, and instantiate layers of that new class.
Related
I am doing the kmean clustering through sklearn in python. I am wondering how to change the generated label name for kmean clusters. For example:
data Cluster
0.2344 1
1.4537 2
2.4428 2
5.7757 3
And I want to achieve to
data Cluster
0.2344 black
1.4537 red
2.4428 red
5.7757 blue
I am not meaning to directly set1 -> black; 2 -> redby printing. I am wondering is it possible to set different cluster names in kmean clustering model in default.
No
There isn't any way to change the default labels.
You have to map them separately using a dictionary.
You can take look at all available methods in the documentation here.
None of the available methods or attributes allows you to change the default labels.
Solution using dictionary:
# Code
a = [0,0,1,1,2,2]
mapping = {0:'black', 1:'red', 2:'blue'}
a = [mapping[i] for i in a]
# Output
['black', 'black', 'red', 'red', 'blue', 'blue']
If you change your data or number of clusters:
First we will see the visualizations:
Code:
Importing and generating random data:
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(100, size =(10,2))
Applying Kmeans algorithm
kmeans = KMeans(n_clusters=3, random_state=0).fit(x)
Getting cluster centers
arr = kmeans.cluster_centers_
Your cluster centroids look like this:
array([[23.81072765, 77.21281171],
[ 8.6140551 , 23.15597377],
[93.37177176, 32.21581703]])
Here, 1st row is the centroid of cluster 0, 2nd row is centroid of cluster 1 and so on.
Visualizing centroids and data:
plt.scatter(x[:,0],x[:,1])
plt.scatter(arr[:,0], arr[:,1])
You get a graph that looks like this:
.
As you can see, you have access to centroids as well as training data. If your training data and number of clusters is constant these centroids dont really change.
But if you add more training data or more number of clusters then you will have to create new mapping according to the centroids that are generated.
check out the top response on this related post
sklearn doesn't include this functionality but you can map the values to your dataframe in a fairly straightforward manner.
current_labels = [1, 2, 3]
desired_labels = ['black', 'red', 'blue']
# create a dictionary for your corresponding values
map_dict = dict(zip(current_labels, desired_labels))
map_dict
>>> {1: 'black', 2: 'red', 3: 'blue'}
# map the desired values back to the dataframe
# note this will replace the original values
data['Cluster'] = data['Cluster'].map(map_dict)
# alternatively you can map to a new column if you want to preserve the old values
data['NewNames'] = data['Cluster'].map(map_dict)
This is part of the code of grad-cam:
def generate_grad_cam(img_tensor, model, class_index, activation_layer):
inp = model.input
y_c = model.output.op.inputs[0][0, class_index]
A_k = model.get_layer(activation_layer).output
What does model.output.op.inputs[0][0,class_index] do? What is model.output.op?
In this picture which one is the
model.output.op.inputs[0][0, class_index]??
I did a bit of exploring in the TF/Keras code, and based on that investigation I believe what
model.output.op
provides is the mathematical "operation" at the output layer of the model. The inputs provide the list of input tensors to that operation (for example in your case inputs[0] is the first input to whatever the actual op is). The remaining part is slicing into that tensor to extract a certain element.
After running this code for the VGG16 example model:
import tensorflow as tf
tf.keras.backend.clear_session() # For easy reset of notebook state.
myNewModel = tf.keras.applications.VGG16()
print('myNewModel.output.op:')
print(myNewModel.output.op)
print('myNewModel.output.op.inputs[0]:')
print(myNewModel.output.op.inputs[0])
print('myNewModel.output.op.inputs[0][0,3]:')
print(myNewModel.output.op.inputs[0][0,3])
I get this output - Note that I used 3 for the class_index just for an example:
myNewModel.output.op:
name: "predictions/Softmax"
op: "Softmax"
input: "predictions/BiasAdd"
attr {
key: "T"
value {
type: DT_FLOAT
}
}
myNewModel.output.op.inputs[0]:
Tensor("predictions/BiasAdd:0", shape=(?, 1000), dtype=float32)
myNewModel.output.op.inputs[0][0,3]:
Tensor("strided_slice:0", shape=(), dtype=float32)
I hope this helps.
I known that almost layer in CAFFE can run in CPU/GPU. In case of GPU, it has some mode, called engine. If engine=CAFFE, it will run with GPU and engine=CUDNN, it will run based on CUDA code. The default is DEFAULT mode
In my Makefile.config, I turn on CUDNN mode when build caffe
# cuDNN acceleration switch (uncomment to build with cuDNN).
USE_CUDNN := 1
In my prototxt, I have a layer, for example, Deconvolution layer
layer {
name: "DeconvolutionLayer"
type: "Deconvolution"
bottom: "conv1"
top: "DeconvolutionLayer"
param {
lr_mult: 1
decay_mult: 1
}
convolution_param {
num_output: 128
bias_term: false
pad: 0
kernel_size: 2
stride: 2
weight_filler {
type: "msra"
}
}
}
Note that, I did not set any value for engine flag. When I run, which mode will be use, GPU or CUDNN? The training script is
caffe/build/tools/caffe train --solver=solver.prototxt -gpu 0
If you look into the caffe.proto it says "The default for the engine is set by the ENGINE switch at compile-time.". If you look into the layer_factory.cpp if USE_CUDNN is set then the default engine is set to cuDNN. So in your case it is CUDNN.
I used hdf5 file as caffe input data, and the error occured:
hdf5_data_layer.cpp:75] Check failed: !this->layer_param_.has_transform_param() HDF5Data does not transform data.
This is my defination:
layer {
name: "weight28"
type: "HDF5Data"
include { phase : TRAIN }
transform_param { scale: 0.00392156862745098 }
hdf5_data_param {
source: "/home/zhangyu/codes/unsupervised/data/weight28.h5"
batch_size: 8
}
top: "weight28"
}
Here is some information of my h5 file:
HDF5 weight28.h5
Group '/'
Dataset 'data'
Size: 2555000x28
MaxSize: Infx28
Datatype: H5T_IEEE_F64LE (double)
ChunkSize: 28x28
Filters: none
FillValue: 0.000000
I find a similar question and the answer said You cannot use transform param in the hdf5data layer.
What dose data transform in caffe do? Can I just cancel it?
In response to the error mentioned by user6931072 Check failed: H5LTfind_dataset(file_id, dataset_name_) Failed to find HDF5 dataset:
You should provide a text file as the source, not an hdf5 file. So, instead of source: "/home/zhangyu/codes/unsupervised/data/weight28.h5", make a text file that lists the hdf5 file and then use source: "/home/zhangyu/codes/unsupervised/data/myhdf5data.txt".
As you already spotted yourself, you cannot have transformation_param in a "HDF5Data" layer - caffe does not support this.
As for the transformation parameters themselves, look at caffe.proto:
// For data pre-processing, we can do simple scaling and subtracting the
// data mean, if provided. Note that the mean subtraction is always carried
// out before scaling.
optional float scale = 1 [default = 1];
Having transform_param { scale: 0.00392156862745098 } means your net expects your input to be scaled by 0.0039.. (1/254).
You can (and probably should) scale the data by 1/254 when you create the hdf5 data files for training and then remove the transform_param from the "HDF5Data" layer.
After training LeNet model in Caffe framework using 10k images with 2 categories, I got the model lenet_iter_4000.caffemodel which contains weights and biases. I want to check the accuracy of 5k new test images(which are not part of testing images while training) at a time.I created lmdb file for all these 5k images. I know how to test the images using the following.
./build/tools/caffe test --model=examples/mnist/lenet_train_test.prototxt --weights=examples/mnist/lenet_iter_4000.caffemodel
But I am not able to get accuracy at a time like while training we will get accuracy if we put test_interval 3000, we will get the accuracy of all testing images after 3000 iterations. If I want to test accuracy at a time after training where I have to do changes in prototxt.
My question is: how to get accuracies for multiple data sets after training using trained model?
One fast solution is to get accuracies for multiple Data sets while training. You can achieve this by modifying your solver.prototxt and net.prototxt like the following, which more specifically is to use multiple "test_state" in solver.prototxt and multiple Data layers with different "include: {stage: "xxx"}" in net.prototxt for testing of muliple Data sets:
solver.prototxt:
net: "lenet_train_test.prototxt"
#testing stage for your orininal test images
test_state: { stage: "original test" }
#testing stage for your new test images
test_state: { stage: "new 5k test" }
#iterations for original testing
test_iter: xxx
#iterations for your new 5k testing
test_iter: xxx
#Those 2 testings use the same test_interval
test_interval: 500
Corresponding net.prototxt:
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 32
backend: LMDB
shuffle: true
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
stage: "original test"
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
stage: "new 5k test"
}
transform_param {
scale: 0.00390625
}
data_param {
source: "path/to/your/5k_images_test_lmdb"
batch_size: 100
backend: LMDB
}
}
.
.
.
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
And use them like a way of finetune:
./build/tools/caffe train --solver=examples/mnist/solver.prototxt --weights=examples/mnist/lenet_iter_4000.caffemodel
At iteration 0, the solver will test the multiple Data sets and you will get the multiple accuracies of them and then can stop the solver.
Just use the test tool of caffe, check the interface examples
I am here a bit late but those of you wondering how to use trained model only for testing purposes can use the test tool of caffe. If you trained your model, and was planning to use it after, you should have saved the weights at each iteration. Let's name the final saved weights model_iter_xxxx.caffemodel.
Copy your model into a model_test.prototxt (for example)
Add layers to be considered in the test phase i.e input layer for testing data and accuracy layer.
Run: caffe test -model path/to/model_test.prototxt -weights path/to/model_iter_xxxx.caffemodel -iterations 100