Related
if the tensor is of shape [20, 5] then I need to take 10 at a time and sum them, so result is [2,5].
eg:
shape[20,5] -> shape[2, 5] (sum 10 at a time)
shape[100, 20] -> shape[10,20] (sum 10 at a time)
Is there any faster/optimal way to do this?
eg:
[[1, 1], [1, 2], [3, 4], [1,2]] i want [[2, 3], [4, 6]] by taking sum of 2 rows.
It is not completely clear, but I cannot use a comment for this, so.
For the first case you have:
t1 = torch.tensor([[1., 1.], [1., 2.], [3., 4.], [1.,2.]])
t1.shape #=> torch.Size([4, 2])
t1
tensor([[1., 1.],
[1., 2.],
[3., 4.],
[1., 2.]])
To get the desired output you should reshape:
tr1 = t1.reshape([2, 2, 2])
res1 = torch.sum(tr1, axis = 1)
res1.shape #=> torch.Size([2, 2])
res1
tensor([[2., 3.],
[4., 6.]])
Let's take a tensor with all one elements (torch.ones) for the second case.
t2 = torch.ones((20, 5))
t2.shape #=> torch.Size([20, 5])
t2
tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
So, reshaping to get the required (?) result:
tr2 = tensor.reshape((10, 2, 5))
res2 = torch.sum(tr2, axis = 0)
res2.shape #=> torch.Size([2, 5])
res2
tensor([[10., 10., 10., 10., 10.],
[10., 10., 10., 10., 10.]])
Is this what you are looking for?
I am not aware of any off the shelf solution for that.
If having the average is enough you can use nn.AvgPool1d https://pytorch.org/docs/stable/generated/torch.nn.AvgPool1d.html#avgpool1d:
import torch, torch.nn as nn
x = torch.rand(batch_size, channels, lenght)
pool = nn.AvgPool1D(kernel_size=10, stride=10)
avg = pool(x)
With this solution, just make sure you are averaging the correct dimension.
EDIT
I just realized you can get the sum by modifying the last line with avg = pool(x) * kernel_size!
You can also just write your own function that does the summing for you:
import torch
def SumWindow(x, window_size, dim):
input_split = torch.split(x, window_size, dim)
input_sum = [v.sum(dim=dim), for v in input_split] # may be expensive if there are too many tensors
out = torch.cat(inptu_sum, dim=dim)
return dim
Hey I have used the following code:
import matplotlib.pyplot as plt
import numpy as np
Class1=np.array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [0., 0., 1., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 0., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 0., 1., 0., 1., 0., 1.], [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 1., 1., 1., 0.]])
Unique=np.array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.,
13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25.,
26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38.])
counts=np.array([56184982, 2904400, 4950837, 114746, 4270, 182052,
844444, 106292, 47007, 68480, 23522, 13838,
23990, 301704, 50462, 21345, 12263, 7217,
64194, 251, 885, 2947045, 4895643, 102992,
4401, 180136, 844872, 281, 107200, 48703,
69791, 22651, 50295, 22772, 7020, 62543,
43, 1103, 48])
list_y2=[]
list_x=[]
list_y1=[]
for i in np.arange(len(Unique)):
list_y2.append( np.array2string(round(counts[i]/Class1.sum(axis=1)[i],2)))
if i < 9:
list_x.append(str(i+1))
else:
list_x.append( str(i+1))
list_y1.append( str(38-int(Unique[i])))
fig, ax1 = plt.subplots()
F=16
ax1.set_xlabel('Brain image',fontsize=F)
ax1.set_yticks(np.arange(len(list_y1)))
ax1.set_yticklabels(list_y1)
ax1.set_xticks(np.arange(len(list_x)))
ax1.set_xticklabels(list_x)
ax1.set_ylabel('class',fontsize=F)
ax2 = ax1.twinx()
ax2.set_yticks(np.arange(len(list_y2)))
ax2.set_yticklabels(list_y2, va='baseline')
ax2.set_ylabel('size',fontsize=F)
#Rotate the tick labels and set their alignment.
plt.setp(ax1.get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
plt.imshow(Class1, aspect='auto')
fig.tight_layout()
plt.show()
which makes the following plot:
The problem with this is that the first y-axis doesn't fit the plot properly. The length between the ticks in the first y-axis should be the same as in the second y-axis and the 0 in the top and the 38 in bottom should be moved a bit inward on the y-axis. Hope one of you can help me.
I had the same problem recently and found the following workaround: Setting the same limits for the twin axis ax2 as for the parent axis (ax1). This aligns the ticks on both y-axes and then you proceed by setting the ticks and the labels as desired as you are doing.
ax2 = ax1.twinx()
ax2.set_ylim(ax1.get_ylim()) # This was the fix for me
ax2.set_yticks(np.arange(len(list_y2)))
ax2.set_yticklabels(list_y2, va='baseline')
ax2.set_ylabel('size',fontsize=F)
Let me know if it works.
I'm observing some odd behaviour using numpy broadcasting. The problem is illustrated below, where running the first piece of code produces an error:
A = np.ones((10))
B = np.ones((10, 4))
C = np.ones((10))
np.asarray([A, B, C])
ValueError: could not broadcast input array from shape (10,4) into shape (10)
If I instead expand the dimensions of B, using B = np.expand_dims(B, axis=0), it will successfully create the array, but it now has (not surprisingly) the wrong dimensions:
array([array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]]),
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=float32)
Why does it fail to broadcast the first example, and how can I end up with an array like below (notice only double brackets around the second array)? Any feedback is much appreciated.
array([array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]),
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=object)
Including, say, None prevents the broadcasting, so this workaround is an option:
np.asarray([A, B, C, None])[:-1]
Here the outcome:
array([array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]),
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=object)
I am experimenting with clustering using the hdbscan package (0.8.3) in Python. Reading through the documentation leads me to want to test the different settings for cluster_selection_method (notably, setting it to 'leaf'). When I try to make this change I get:
__init__() got an unexpected keyword argument 'cluster_selection_method'
Here is how I call it:
clusterer = hdbscan.HDBSCAN(algorithm=algorithm,alpha=alpha,metric=metric,min_cluster_size=min_cluster_size \
,min_samples=min_samples,p=p,cluster_selection_method='leaf')
clusterer.fit(data['values'])
In this case data['values'] are all 1D arrays with each element having a value of 1.0 or 10.0 as shown below. Any advice on what might be preventing me from setting the cluster_selection_method would be appreciated.
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 10., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
10., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 10.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 10., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 10., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 10., 1., 10., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 10., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
10., 10., 10., 10., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 10., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 10., 1., 1., 10., 10., 10.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 10., 10.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 10., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 10., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.])
You may want to upgrade to a newer release of hdbscan; the cluster_selection_method was a relatively new addition.
I have a (21 x 25) 2D array which contains two discrete values, "1" & "2".
The values are shown below:
value = np.array(
[[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 2., 2.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 1., 2., 2.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 1., 2., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
If I plot this using pcolor, the resulting figure looks like this:
I want to draw the outlines of the grid squares where value == 2:
xx,yy = np.linspace(0,26,25),np.linspace(0,22,22)
xx,yy = np.meshgrid(xx,yy)
plt.pcolormesh(xx, yy, value, facecolor='none', edgecolor='b', alpha=0.8, zorder=2)
It seems like the outline isn't uniform (the lines have different shades), and I can't set the grid line colors by changing edgecolor.
You can render the squares where value == 1 as transparent by creating an np.ma.masked_array from value:
c = np.ma.masked_array(value, value == 1.) # mask squares where value == 1
plt.pcolormesh(xx, yy, c, alpha=0.8, zorder=2, facecolor='none', edgecolors='k',
cmap='gray')
Setting the colormap to 'gray' is a bit of a hack - unfortunately it seems that the default colormap overrides the edge color, even if you try to set it explicitly using edgecolor= or edgecolors=. I'm not sure whether or not this should be considered a bug in matplotlib.