简体   繁体   中英

How do I to average irregularly spaced x & y coordinate tensor into a grid with a specific cell size?

I have an algorithm that generates a tensor of irregularly spaced x and y coordinates (ex: torch.size([3600, 2])), and I need to average the points into grid cells of a specific size (ex: 8 by 8). The resulting grid needs to be either an array or tensor.

It's not required, but I would also like to be able to determine if any of the resulting cells have less than a specified number of points in them.

For example I can graph the tensor using matplotlib's plt.scatter , and it looks like this:

在此处输入图像描述

In the above example, 100,000 points exist but the number of points can sometimes be in the tens of millions.

I've tried using histogram approaches, and most of them use a specific number of cells vs a specific cell size. Matplotlib can seemingly do it in a graph, but that doesn't help me get an array or tensor.

Edit:

This code might work, if it can be made to work properly.

def grid_torch(x_coords, y_coords, grid_size=(8,8), x_extent=(0., 1.), y_extent=(0., 1.)):
    x_coords = ((x_coords - x_extent[0]) / (x_extent[1] - x_extent[0])) * grid_size[0]
    y_coords = ((y_coords - y_extent[0]) / (y_extent[1] - y_extent[0])) * grid_size[1]

    x_list = []
    for x in range(grid_size[0]):
        x = torch.ones_like(x_coords) * x
        y_list = []
        for y in range(grid_size[1]):
            y = torch.ones_like(y_coords) * y
            in_bounds_x = torch.logical_and(x <= x_coords, x_coords <= x + 1)
            in_bounds_y = torch.logical_and(y <= y_coords, y_coords <= y + 1)
            in_bounds = torch.logical_and(in_bounds_x, in_bounds_y)

            in_bounds_indices = torch.where(in_bounds)
            print(in_bounds_indices)
            y_list.append(in_bounds_indices)
        x_list.append(torch.stack(y_list))
    return torch.stack(x_list)



out = grid_torch(xy_tensor[:,0], xy_tensor[:,1])

print(out.shape)

def create_grid(grid_layout, activ, grid_size=(8,8), min_density=8):
    cells = []
    for x in range(grid_size[0]):
        for y in range(grid_size[1]):
            indices = grid_layout[x, y]
            if len(indices) > min_density:
                average_activation = torch.mean(activ[indices])
                cells.append((average_activation, x, y))
                print(average_activation, x, y)
    return torch.stack(cells)



grid_test = create_grid(out, xy_tensor, grid_size=(8,8))

I think this code would give you a good starting point.

def grid_torch(x_coords, y_coords, grid_size=(8,8), x_extent=(0., 1.), y_extent=(0., 1.)):
    # This part converts coordinates to bin numbers (like (2,5), (7,7) etc)
    x_bin = (((x_coords - x_extent[0]) / (x_extent[1] - x_extent[0])) * grid_size[0]).int()
    y_bin = (((y_coords - y_extent[0]) / (y_extent[1] - y_extent[0])) * grid_size[1]).int()
    
    counts = torch.zeros(grid_size)
    means = torch.zeros(list(grid_size) + [2])
    for x in range(grid_size[0]):
        for y in range(grid_size[1]):
            # these tensors are 1 where (x_bin == x and y_bin == y), 0 else where
            x_where = 1 * (x_bin == x)
            y_where = 1 * (y_bin == y)
            p_where = (x_where * y_where)
            cnt = p_where.sum()
            counts[x, y] = cnt
            
            # we'll average both x and y coords seperately.
            # you can embed min_density logic here. 
            if cnt > 0:
                means[x, y, 0] = (x_coords * p_where).sum() / p_where.sum()
                means[x, y, 1] = (y_coords * p_where).sum() / p_where.sum()
    
    return counts, means


# Generate sample points
points = torch.tensor(np.concatenate([
    np.random.normal(loc=0.2, scale=0.1, size=(1000, 2)),
    np.random.normal(loc=0.6, scale=0.1, size=(1000, 2))
]).clip(0,1)).float()
# plt.scatter(points[:,0], points[:,1])
# plt.grid()

counts, means = grid_torch(points[:,0], points[:,1])
counts

>>>
tensor([[ 47., 114.,  75.,  10.,   0.,   0.,   0.,   0.],
        [102., 204., 141.,  27.,   0.,   0.,   0.,   0.],
        [ 60., 101.,  74.,  16.,   7.,   4.,   1.,   0.],
        [  5.,  17.,   9.,  23.,  72.,  51.,  10.,   0.],
        [  1.,   1.,   4.,  54., 186., 141.,  28.,   3.],
        [  0.,   0.,   3.,  47., 154., 117.,  14.,   0.],
        [  0.,   0.,   0.,   9.,  37.,  24.,   4.,   0.],
        [  0.,   0.,   0.,   2.,   0.,   1.,   0.,   0.]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM