Pytorch tensor dimension multiplication - computer-vision

I'm trying to implement the grad-camm algorithm:
https://arxiv.org/pdf/1610.02391.pdf
My arguments are:
activations: Tensor with shape torch.Size([1, 512, 14, 14])
alpha values : Tensor with shape torch.Size([512])
I want to multiply each activation (in dimension index 1 (sized 512)) in each corresponding alpha value: for example if the i'th index out of the 512 in the activation is 4 and the i'th alpha value is 5, then my new i'th activation would be 20.
The shape of the output should be torch.Size([1, 512, 14, 14])

Assuming the desired output is of shape (1, 512, 14, 14).
You can achieve this with torch.einsum:
torch.einsum('nchw,c->nchw', x, y)
Or with a simple dot product, but you will first need to add a couple of additional dimensions on y:
x*y[None, :, None, None]
Here's an example with x.shape = (1, 4, 2, 2) and y = (4,):
>>> x = torch.arange(16).reshape(1, 4, 2, 2)
tensor([[[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15]]]])
>>> y = torch.arange(1, 5)
tensor([1, 2, 3, 4])
>>> x*y[None, :, None, None]
tensor([[[[ 0, 1],
[ 2, 3]],
[[ 8, 10],
[12, 14]],
[[24, 27],
[30, 33]],
[[48, 52],
[56, 60]]]])

Related

How to select rows by a column value in D with mir.ndslice?

I am browsing through mir.ndslice docs trying to figure out how to do a simple row selection by column.
In numpy I would do:
a = np.random.randint(0, 20, [4, 6])
# array([[ 8, 5, 4, 18, 1, 4],
# [ 2, 18, 15, 7, 18, 19],
# [16, 5, 4, 6, 11, 11],
# [15, 1, 14, 6, 1, 4]])
a[a[:,2] > 10] # select rows where the second column value is > 10
# array([[ 2, 18, 15, 7, 18, 19],
# [15, 1, 14, 6, 1, 4]])
Using mir library I naively tried:
import std.range;
import std.random;
import mir.ndslice;
auto a = generate!(() => uniform(0, 20)).take(24).array.sliced(4,6);
// [[12, 19, 3, 10, 19, 11],
// [19, 0, 0, 13, 9, 1],
// [ 0, 0, 4, 13, 1, 2],
// [ 6, 19, 14, 18, 14, 18]]
a[a[0..$,2] > 10];
But got
Error: incompatible types for `((ulong __dollar = a.length();) , a.opIndex(a.opSlice(0LU, __dollar), 2)) > (10)`: `Slice!(int*, 1LU, cast(mir_slice_kind)0)` and `int`
dmd failed with exit code 1.
So, I went through the docs and couldn't find anything that would look like np.where or similar. Is it even possible in mir?

Plotting graph of items in list into corresponding category using PyPlot in Python 2.7

I have a list with 10 records, and each record has one or more elements with 3 categories like below:
list = [('0.4', 2, 'doc4.txt'),('0.04', 13, 'doc4.txt'), ('0.5', 4, 'doc4.txt')]
[('0.5', 6, 'doc3.txt'),('0.04', 13, 'doc3.txt'), ('0.5', 4, 'doc3.txt')]
[('0.6', 8, 'doc2.txt')]
[('0.4', 2, 'doc5.txt'), ('1.0', 7, 'doc5.txt')]
[('0.2', 2, 'doc6.txt'), ('0.4', 2, 'doc6.txt'),('0.8', 2, 'doc6.txt'), ('0.34', 5, 'doc6.txt'),('0.76', 4, 'doc6.txt'), ('0.5', 3, 'doc6.txt')]
[('0.3', 7, 'doc9.txt')]
[('0.1', 8, 'doc12.txt')]
[('0.3', 9, 'doc11.txt'),('1.0', 8, 'doc11.txt')]
[('0.9', 7, 'doc22.txt')]
[('0.3', 7, 'doc24.txt')]
You many notice the third category of every record has the same text for each record. There are 10 categories as the list consists of 10 records.
According to the structure of the list:
For example, [('0.6', 8, 'doc2.txt')]
First element, '0.6' represents X-axis value in the range of [0.1 -> 1.0]
Second element of an integer represents Y-axis value in graph
Third element, 'doc2.txt' represents the Category name in graph
The list should be plotted as the image below,
I've been trying with several approaches, but still couldn't figure that out
>>> plt.scatter(*zip(*list))
>>> plt.xlabel('X-Axis')
>>> plt.ylabel('Y-Axis')
>>> plt.show()
I think you can just keep the list as it is and iterate over it. You'd then produce a scatter plot for each sublist in the outer list, as the items from the sublist should share the same marker, color and legend label.
import matplotlib.pyplot as plt
#don't call a variable "list" or "print" or any other python command's name
liste=[[('0.4', 2, 'doc4.txt'),('0.04', 13, 'doc4.txt'), ('0.5', 4, 'doc4.txt')],
[('0.5', 6, 'doc3.txt'),('0.04', 13, 'doc3.txt'), ('0.5', 4, 'doc3.txt')],
[('0.6', 8, 'doc2.txt')],
[('0.4', 2, 'doc5.txt'), ('1.0', 7, 'doc5.txt')],
[('0.2', 2, 'doc6.txt'), ('0.4', 2, 'doc6.txt'),('0.8', 2, 'doc6.txt'), ('0.34', 5, 'doc6.txt'),('0.76', 4, 'doc6.txt'), ('0.5', 3, 'doc6.txt')],
[('0.3', 7, 'doc9.txt')],
[('0.1', 8, 'doc12.txt')],
[('0.3', 9, 'doc11.txt'),('1.0', 8, 'doc11.txt')],
[('0.9', 7, 'doc22.txt')],
[('0.3', 7, 'doc24.txt')]]
markers=[ur"$\u25A1$", ur"$\u25A0$", ur"$\u25B2$", ur"$\u25E9$"]
colors= ["k", "crimson", "#112b77"]
fig, ax = plt.subplots()
for i, l in enumerate(liste):
x,y,cat = zip(*l)
ax.scatter(list(map(float, x)),y, s=64,c=colors[(i//4)%3],
marker=markers[i%4], label=cat[0])
ax.legend(bbox_to_anchor=(1.01,1), borderaxespad=0)
plt.subplots_adjust(left=0.1,right=0.8)
plt.show()
There are multiple issues. You assignment of list makes no sense (presumably you forgot some parentheses). Also, you really shouldn't reuse built-in names like "list". You should not represent floats as strings (your x coordinates). You cannot simply unpack a list into plt.scatter and hope that magically all of these issues work themselves out.
Below some code how to properly pass your data to scatter (I use plot instead of scatter as you can pass plot proper colour names).
import numpy as np
import matplotlib.pyplot as plt
# 'list' is a bad name for a variable as it overwrites the list() built-in function
# -> rename to data
data = [
[('0.4', 2, 'doc4.txt'),('0.04', 13, 'doc4.txt'), ('0.5', 4, 'doc4.txt')],
[('0.5', 6, 'doc3.txt'),('0.04', 13, 'doc3.txt'), ('0.5', 4, 'doc3.txt')],
[('0.6', 8, 'doc2.txt')],
[('0.4', 2, 'doc5.txt'), ('1.0', 7, 'doc5.txt')],
[('0.2', 2, 'doc6.txt'), ('0.4', 2, 'doc6.txt'),('0.8', 2, 'doc6.txt'), ('0.34', 5, 'doc6.txt'),('0.76', 4, 'doc6.txt'), ('0.5', 3, 'doc6.txt')],
[('0.3', 7, 'doc9.txt')],
[('0.1', 8, 'doc12.txt')],
[('0.3', 9, 'doc11.txt'),('1.0', 8, 'doc11.txt')],
[('0.9', 7, 'doc22.txt')],
[('0.3', 7, 'doc24.txt')]
]
# flatten nested list
flat = [item for sublist in data for item in sublist]
# convert strings to numbers
numeric = [(float(x), y, label) for (x, y, label) in flat]
# create a dictionary that maps a label to a set of x,y coordinates
data = dict()
for (x, y, label) in numeric:
if label in data:
data[label].append((x,y))
else:
data[label] = [(x,y)]
# initialise figure
fig, ax = plt.subplots(1,1)
colors = ['blue', 'red', 'yellow', 'green', 'orange', 'brown', 'violet', 'magenta', 'white', 'black']
# populate figure
for color, (label, xy) in zip(colors, data.iteritems()):
x, y = np.array(xy).T
ax.plot(x, y, 'o', label=label, color=color)
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 16)
ax.legend(numpoints=1)
plt.show()

Sorting HashMap on values of type List

I have a map with keys as String and values as a List, Need to sort the map on values
HashMap<String, List<Integer>> data = new HashMap<String, List<Integer>>();
Where List is of size 3 and need to sort on item1, item2 and then item3 of list in asc order
for example if i have a map like below
K1=[3, 1, 96],
K2=[0, 4, 4],
K3=[3, 2, 88],
K4=[2, 2, 12],
K5=[3, 3, 64],
K6=[2, 4, 12],
K7=[3, 4, 64],
K8=[2, 1, 12],
K9=[2, 3, 12],
K10=[1, 2, 33],
K11=[3, 1, 45],
K12=[1, 1, 12],
K13=[0, 1, 6],
K14=[0, 1, 3],
K15=[2, 1, 12],
K16=[3, 4, 22],
After Sort :
K14=[0, 1, 3],
K13=[0, 1, 6],
K2=[0, 4, 4],
K12=[1, 1, 12],
K10=[1, 2, 33],
K8=[2, 1, 12],
K15=[2, 1, 12],
K4=[2, 2, 12],
K9=[2, 3, 12],
K6=[2, 4, 12],
K11=[3, 1, 45],
K1=[3, 1, 96],
K3=[3, 2, 88],
K5=[3, 3, 64],
K16=[3, 4, 22],
K7=[3, 4, 64]
How can this be done?
Thanks
My suggestion is that you transfer your elements to a List<Map.Entry<String, List<Integer>>> (for example by calling new ArrayList<>(data.entrySet())) which can then be sorted using a Comparator<Map.Entry<String, List<Integer>>>.
The horrible parameter types can of course be simplified for example if you don't need the map keys.
It would go something like this(at least in Java 8. Java 7 would require slightly more boilerplate code):
List<Map.Entry<String, List<Integer>>> dataList;
dataList = new ArrayList<>(data.entrySet());
dataList.sort((x, y) -> {
int comparison = Integer.compare(x.getValue().get(0), y.getValue().get(0));
if (comparison != 0) return comparison;
comparison = Integer.compare(x.getValue().get(1), y.getValue().get(1));
if (comparison != 0) return comparison;
return Integer.compare(x.getValue().get(2), y.getValue().get(2));
});
Edit: If you just want to sort a List<List<Integer>> list it gets as simple as this(Java 7 this time):
Collections.sort(list, new Comparator<List<Integer>>(){
public int compare(List<Integer> a, List<Integer> b) {
int comparison = a.get(0).compareTo(b.get(0));
if (comparison != 0) return comparison;
comparison = a.get(1).compareTo(b.get(1));
if (comparison != 0) return comparison;
return a.get(2).compareTo(b.get(2));
}
});

How to avoid using "no data" in image stacking

I am new in using python. My problem might seems easy but unfortunately I could not find a solution for it. I have a set of images in Geotiff format which are at the same size, their pixel values range between 0 to 5 and their non values are -9999. I would like to do kind of image stacking using Numpy and Gdal. I am looking for an stacking algorithm in which those pixels of each image that have a value between 0 to 5 are used and the no data values are not used in computing the average. For example if I have 30 images and for two of them the value at the index Image[20,20] are 2 & 3 respectively and for the rest of images it is -9999 at this index. I want the single band output image to be 2.5 at this index. I am wondering if anyone knows the way to do it?
Any suggestions or hints are highly appreciated.
Edit:
let me clarify it a bit more. Here is a sample :
import numpy as np
myArray = np.random.randint(5,size=(3,3,3))
myArray [1,1,1] = -9999
myArray
>> array([[[ 0, 2, 1],
[ 1, 4, 1],
[ 1, 1, 2]],
[[ 4, 2, 0],
[ 3, -9999, 0],
[ 1, 0, 3]],
[[ 2, 0, 3],
[ 1, 3, 4],
[ 2, 4, 3]]])
suppose that myArray is an ndarray which contains three images as follow:
Image_01 = myArray[0]
Image_02 = myArray[1]
Image_03 = myArray[2]
the final stacked image is :
stackedImage = myArray.mean(axis=0)
>> array([[ 2.00000000e+00, 1.33333333e+00, 1.33333333e+00],
[ 1.66666667e+00, -3.33066667e+03, 1.66666667e+00],
[ 1.33333333e+00, 1.66666667e+00, 2.66666667e+00]])
But I want it to be this :
array([[ 2.00000000e+00, 1.33333333e+00, 1.33333333e+00],
[ 1.66666667e+00, 3.5, 1.66666667e+00],
[ 1.33333333e+00, 1.66666667e+00, 2.66666667e+00]])
Masked arrays are a good way to deal with missing or invalid values. Masked arrays have a .data attribute, which contains the numerical value for each element, and a .mask attribute that specifies which values should be considered 'invalid' and ignored.
Here's a full example using your data:
import numpy as np
# your example data, with a bad value at [1, 1, 1]
M = np.array([[[ 0, 2, 1],
[ 1, 4, 1],
[ 1, 1, 2]],
[[ 4, 2, 0],
[ 3, -9999, 0],
[ 1, 0, 3]],
[[ 2, 0, 3],
[ 1, 3, 4],
[ 2, 4, 3]]])
# create a masked array where all of the values in `M` that are equal to
# -9999 are masked
masked_M = np.ma.masked_equal(M, -9999)
# take the mean over the first axis
masked_mean = masked_M.mean(0)
# `masked_mean` is another `np.ma.masked_array`, whose `.data` attribute
# contains the result you're looking for
print masked_mean.data
# [[ 2. 1.33333333 1.33333333]
# [ 1.66666667 3.5 1.66666667]
# [ 1.33333333 1.66666667 2.66666667]]

How to replace values in a list at indexed positions?

I have following list of text positions with all values being set to '-999' as default:
List = [(70, 55), (170, 55), (270, 55), (370, 55),
(70, 85), (170, 85), (270, 85), (370, 85)]
for val in List:
self.depth = wx.TextCtrl(panel, -1, value='-999', pos=val, size=(60,25))
I have indexed list and corresponding values at them such as:
indx = ['2','3']
val = ['3.10','4.21']
I want to replace index locations '2' and '3' with values '3.10' and '4.21' respectively in 'List' and keep the rest as '-999'. Any suggestions?
Solved. I used following example:
>>> s, l, m
([5, 4, 3, 2, 1, 0], [0, 1, 3, 5], [0, 0, 0, 0])
>>> d = dict(zip(l, m))
>>> d #dict is better then using two list i think
{0: 0, 1: 0, 3: 0, 5: 0}
>>> [d.get(i, j) for i, j in enumerate(s)]
[0, 0, 3, 0, 1, 0]
from similar question.