Related
How to replace column in the numpy array be certain number based on probability, if it is (1,X,X) shape.
I found code to replace rows, but cannot figure out how to modify it, so it is applicable for columns replacement.
grid_example = np.random.rand(1,5,5)
probs = np.random.random((1,5))
grid_example[probs < 0.25] = 0
grid_example
Thanks!
Use:
import numpy as np
rng = np.random.default_rng(42)
grid_example = rng.random((1, 5, 5))
probs = rng.random((1, 5))
grid_example[..., (probs < 0.25).flatten()] = 0
print(grid_example)
Output
[[[0. 0.43887844 0. 0. 0.09417735]
[0. 0.7611397 0. 0. 0.45038594]
[0. 0.92676499 0. 0. 0.4434142 ]
[0. 0.55458479 0. 0. 0.6316644 ]
[0. 0.35452597 0. 0. 0.7783835 ]]]
The notation [..., (probs < 0.25).flatten()] applies the boolean indexing to the last index. More on the documentation.
I'm trying to create a random test for a "harris_corner_detector" function implementation (VERY GENERALLY AND SLIGHTLY INCORRECTLY: a function that finds corners in an image)
In the test, I want to create random simple shapes in a binary numpy matrix (it's easy to know the coordinates of their corners) (e.g rectangles, triangles, rhombus (diamond) etc...) and check if the harris implementation finds the correct corners.
I already implemented a function that randomly 'draws' an axis parallel rectangle, but i can't find an efficient way to do so when it comes to shapes that are not parallel to the axes.
To create a random rectangle, I randomly choose a starting point and an ending point on both axes and I change the value of all of the cells within those bounds like so:
getting the random coords:
def _get_random_coords(self, start, end):
x_start, y_start = np.random.randint(start, end, 2)
x_end = np.random.randint(x_start + 7, end + 20)
y_end = np.random.randint(y_start + 7, end + 20)
return (x_start, x_end, y_start, y_end)
drawing the random rectangle (values are 255 for the background and 0 for the shape):
mat = np.ones((1024, 1024)) * 255
mat[x_start: x_end, y_start: y_end] = np.zeros((x_end - x_start, y_end - y_start))
but when it comes to drawing a diamond shape efficiently I'm at a loss. All I can think about is to run a loop that creates the diamond like so:
def _get_rhombus(self, size):
rhombus = []
for i in range(size):
rhombus.append(np.zeros(i+1))
for i in range(size - 1, 0, -1):
rhombus.append(np.zeros(i))
return np.array(rhombus)
and then another loop to add it to the larger matrix.
But this method is highly inefficient when it comes to testing (as I'll draw hundreds of them, some of them might be huge).
Any better ideas out there? Alternatively - is there a better way to test this?
Thanks in advance.
There are a number of questions here, but the main one is how to create a numpy array of a filled rhombus given the corners. I'll answer that, and leave other questios, like creating random rhombuses, etc.
To fill a convex polygon, one can find the line specified by subsequent corners and fill above or below that line, and then and all the filled areas together.
import numpy as np
import matplotlib.pyplot as plt
# given two (non-vertical) points, A and B,
# fill above or below the line connecting them
def fill(A, B, fill_below=True, xs=10, ys=12):
# the equation for a line is y = m*x + b, so calculate
# m and b from the two points on the line
m = (B[1]-A[1])/(B[0]-A[0]) # m = (y2 - y1)/(x2 - x1) = slope
b = A[1] - m*A[0] # b = y1 - m*x1 = y intercept
# for each points of the grid, calculate whether it's above, below, or on
# the line. Since y = m*x + b, calculating m*x + b - y will give
# 0 when on the line, <0 when above, and >0 when below
Y, X = np.mgrid[0:ys, 0:xs]
L = m*X + b - Y
# select whether, >=0 is True, or, <=0 is True, to determine whether to
# fill above or below the line
op = np.greater_equal if fill_below else np.less_equal
return op(L, 0.0)
Here's a simple low-res rhombus
r = fill((0, 3), (3, 8), True) & \
fill((3, 8), (7, 4), True) & \
fill((7,4), (5,0), False) & \
fill((5,0), (0,3), False)
plt.imshow(r, cmap='Greys', interpolation='nearest', origin='lower')
That is, the above figure is the result of and-ing together the following fills:
fig, ax = plt.subplots(1, 4, figsize=(10, 3))
fill_params = [((0, 3), (3, 8), True), ((3, 8), (7, 4), True), ((7, 4), (5, 0), False), ((5, 0), (0, 3), False)]
for p, ax in zip(fill_params, ax):
ax.imshow(fill(*p), cmap="Greys", interpolation='nearest', origin='lower')
Or, one could do high-res, and it can have multiple sides (although I think it must be convex).
r = fill((0, 300), (300, 800), True, 1000, 1200) & \
fill((300, 800), (600,700), True, 1000, 1200) & \
fill((600, 700), (700, 400), True, 1000, 1200) & \
fill((700,400), (500,0), False, 1000, 1200) & \
fill((500,0), (100,100), False, 1000, 1200) & \
fill((100, 100), (0,300), False, 1000, 1200)
plt.imshow(r, cmap='Greys', interpolation='nearest', origin='lower')
Obviously, there are a few things to improve, like not repeating the second point of the line and the first point of the new line, but I wanted to keep this all clean and simple (and also, for fill to work the points just need to define a line and don't need to be a corner, so in some cases this more general approach might be preferable). Also, currently one needs to specify whether to fill above or below the line, and that can be calculated in various ways, but is probably easiest when generating the rhombus.
Although a little less robust than the answer already posted, here's a neat trick to form rhombus using upper and lower triangular matrices concept
import numpy as np
import matplotlib.pyplot as plt
blank = np.zeros((10, 12))
anchorx, anchory = 2, 3
# better result for odd dimensions, because mid index exists
# can handle h != w but the rhombus would still fit to a square of dimension min(h, w) x min(h, w)
h, w = 7, 7
assert anchorx+h <= blank.shape[0], "Boundaries exceed, maintain 'anchorx+h <= blank.shape[0]' "
assert anchory+w <= blank.shape[1], "Boundaries exceed, maintain 'anchory+w <= blank.shape[1]' "
tri_rtc = np.fromfunction(lambda i, j: i >= j, (h // 2 + 1, w // 2 + 1), dtype=int)
tri_ltc = np.flip(tri_rtc, axis=1)
rhombus = np.vstack((np.hstack((tri_ltc, tri_rtc[:, 1:])), np.flip(np.hstack((tri_ltc, tri_rtc[:, 1:])), axis=0)[1:, :]))
blank[anchorx:anchorx+h, anchory:anchory+w] = rhombus
print(blank)
plt.imshow(blank)
plt.show()
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
[0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 0. 0.]
[0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
I have an image and its mask picked from a competition hosted in kaggle. The shape of the image is (512,512,3) and the mask is (512,512,1). After applying a function(flipping) on an image, the shape remains the same. However, before applying the operation when I try to access the mask such as (print mask[:,:,0]), I get a matrix,
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
but after applying the operation, and try to access the mask (print mask[:,:,0]), I get the following error
Traceback (most recent call last):
File "Augmentation.py", line 94, in <module>
plot_img_and_mask_transformed(img,mask,img_flip,mask_flip)
File "Augmentation.py", line 36, in plot_img_and_mask_transformed
print(mask_tr[:,:,0])
IndexError: too many indices for array
The function I applied was
def random_flip(img,mask,u=0.5):
if np.random.random() < u :
img = cv.flip(img,0)
mask = cv.flip(mask,0)
return img, mask
img, mask = get_image_and_mask(img_id)
img_tr,mask_tr = random_flip(img,mask)
plot(img,mask,img_tr,mask_tr)
The shape of the image and the mask before flipping
((512, 512, 3), (512, 512, 1))
The shape of the image and the mask after flipping
((512, 512, 3), (512, 512))
Can someone help me out what's happening behind the scenes?
CODE
def get_image_and_mask(img_id):
img = image.load_img(join(data_dir,'train','%s.jpg' % img_id),target_size=(input_size,input_size))
img = image.img_to_array(img)
mask = image.load_img(join(data_dir,'train_masks','%s_mask.gif' % img_id), grayscale=True,target_size=(input_size,input_size))
mask = image.img_to_array(mask)
img,mask = img / 255., mask/ 255.
return img, mask
def plot_img_and_mask(img,mask):
fig, axs = plt.subplots(ncols=2, figsize=(10,5),sharex=True,sharey=True)
axs[0].imshow(img)
axs[1].imshow(mask[:,:,0])
for ax in axs:
ax.set_xlim(0,input_size)
ax.axis('off')
fig.tight_layout()
plt.show()
def plot_img_and_mask_transformed(img, mask, img_tr, mask_tr):
fig, axs=plt.subplots(ncols=4,figsize=(16,4),sharex=True,sharey=True)
axs[0].imshow(img)
axs[1].imshow(mask[:,:,0])
print(mask[:,:,0])
print(mask_tr[:,:,0])
axs[2].imshow(img_tr)
axs[3].imshow(mask_tr)
for ax in axs:
ax.set_xlim(0,input_size)
ax.axis('off')
fig.tight_layout()
plt.show()
def random_flip(img,mask,u=0.5):
# Why do we have to check less than u
if np.random.random() < u :
img = cv.flip(img,0)
mask = cv.flip(mask,0)
return img, mask
def rotate(x,theta,row_axis=0,col_axis=1,channel_axis=2,fill_mode='nearest',cval=0):
rotation_matrix = np.array([
[np.cos(theta),-np.sin(theta),0],
[np.sin(theta),np.cos(theta),0],
[0,0,1]
])
h, w = x.shape[row_axis], x.shape[col_axis]
transform_matrix = image.transform_matrix_offset_center(rotation_matrix,h,w)
x = image.apply_transform(x,transform_matrix,channel_axis,fill_mode,cval)
return x
def random_rotate(img, mask, rotate_limit=(-20,20), u=0.5):
if np.random.random() < u:
theta = np.pi/ 180 * np.random.uniform(rotate_limit[0], rotate_limit[1])
img = rotate(img,theta)
mask = rotate(mask,theta)
return img, mask
if __name__== '__main__':
input_size = 512
data_dir = '../data/carvana-image-masking-challenge'
np.random.seed(1987)
df_train = pd.read_csv(join(data_dir,'train_masks.csv'),usecols=['img'])
df_train['img_id']=df_train['img'].map(lambda s:s.split('.')[0])
df_train.head(3)
img_ids=df_train['img_id'].values
np.random.shuffle(img_ids)
img_id=img_ids[0]
img,mask=get_image_and_mask(img_id)
print((img.shape,mask.shape))
plot_img_and_mask(img,mask)
img_flip,mask_flip = random_flip(img,mask,u=1)
print((img_flip.shape,mask_flip.shape))
plot_img_and_mask_transformed(img,mask,img_flip,mask_flip)
OUTPUT
Using TensorFlow backend.
C:\Users\JamesJohnson\AppData\Local\Programs\Python\Python35\lib\site- packages\keras_preprocessing\image.py:492: UserWarning: grayscale is deprecated. Please use color_mode = "grayscale"
warnings.warn('grayscale is deprecated. Please use '
> ((512, 512, 3), (512, 512, 1))
> ((512, 512, 3), (512, 512))
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
Traceback (most recent call last):
File "Augmentation.py", line 94, in <module>
plot_img_and_mask_transformed(img,mask,img_flip,mask_flip)
File "Augmentation.py", line 36, in plot_img_and_mask_transformed
print(mask_tr[:,:,0])
IndexError: too many indices for array
It looks like OpenCV dumps the singleton dimension when you flip the mask. You'll need to reintroduce it after you flip.
mask_flip = mask_flip[..., None]
A more convenient way is to modify your method so the mask is returned with the singleton dimension after you flip in case you lose it. This way you don't have to do this every time you flip and the method takes care of that instead.
def random_flip(img,mask,u=0.5):
# Why do we have to check less than u
if np.random.random() < u:
img = cv.flip(img,0)
mask = cv.flip(mask,0)
if len(mask.shape) == 2:
mask = mask[..., None]
return img, mask
BTW as a minor note, you have a comment that asks why you have to check for less than u in the method. Remember that the np.random.random method generates a value between 0 and 1 uniformly. Suppose you chose u = 0.3. This means that there is a 30% chance that you will choose a value between between 0 and 0.3 and a 70% chance that you will choose a value between 0.3 and 1. Loosely, this means that if u = 0.3, there is a 30% chance that the if condition is run and you thus flip the image and mask. Therefore, the u controls the probability that a flip of the image and mask will happen.
Given a 3D numpy array of shape (256, 256, 256), how would I make a solid sphere shape inside? The code below generates a series of increasing and decreasing circles but is diamond shaped when viewed in the two other dimensions.
def make_sphere(arr, x_pos, y_pos, z_pos, radius=10, size=256, plot=False):
val = 255
for r in range(radius):
y, x = np.ogrid[-x_pos:n-x_pos, -y_pos:size-y_pos]
mask = x*x + y*y <= r*r
top_half = arr[z_pos+r]
top_half[mask] = val #+ np.random.randint(val)
arr[z_pos+r] = top_half
for r in range(radius, 0, -1):
y, x = np.ogrid[-x_pos:size-x_pos, -y_pos:size-y_pos]
mask = x*x + y*y <= r*r
bottom_half = arr[z_pos+r]
bottom_half[mask] = val#+ np.random.randint(val)
arr[z_pos+2*radius-r] = bottom_half
if plot:
for i in range(2*radius):
if arr[z_pos+i].max() != 0:
print(z_pos+i)
plt.imshow(arr[z_pos+i])
plt.show()
return arr
EDIT: pymrt.geometry has been removed in favor of raster_geometry.
DISCLAIMER: I am the author of both pymrt and raster_geometry.
If you just need to have the sphere, you can use the pip-installable module raster_geometry, and particularly raster_geometry.sphere(), e.g:
import raster_geometry as rg
arr = rg.sphere(3, 1)
print(arr.astype(np.int_))
# [[[0 0 0]
# [0 1 0]
# [0 0 0]]
# [[0 1 0]
# [1 1 1]
# [0 1 0]]
# [[0 0 0]
# [0 1 0]
# [0 0 0]]]
internally, this is implemented as an n-dimensional superellipsoid generator, you can check its source code for details.
Briefly, the (simplified) code would reads like this:
import numpy as np
def sphere(shape, radius, position):
"""Generate an n-dimensional spherical mask."""
# assume shape and position have the same length and contain ints
# the units are pixels / voxels (px for short)
# radius is a int or float in px
assert len(position) == len(shape)
n = len(shape)
semisizes = (radius,) * len(shape)
# genereate the grid for the support points
# centered at the position indicated by position
grid = [slice(-x0, dim - x0) for x0, dim in zip(position, shape)]
position = np.ogrid[grid]
# calculate the distance of all points from `position` center
# scaled by the radius
arr = np.zeros(shape, dtype=float)
for x_i, semisize in zip(position, semisizes):
# this can be generalized for exponent != 2
# in which case `(x_i / semisize)`
# would become `np.abs(x_i / semisize)`
arr += (x_i / semisize) ** 2
# the inner part of the sphere will have distance below or equal to 1
return arr <= 1.0
and testing it:
# this will save a sphere in a boolean array
# the shape of the containing array is: (256, 256, 256)
# the position of the center is: (127, 127, 127)
# if you want is 0 and 1 just use .astype(int)
# for plotting it is likely that you want that
arr = sphere((256, 256, 256), 10, (127, 127, 127))
# just for fun you can check that the volume is matching what expected
# (the two numbers do not match exactly because of the discretization error)
print(np.sum(arr))
# 4169
print(4 / 3 * np.pi * 10 ** 3)
# 4188.790204786391
I am failing to get how your code exactly works, but to check that this is actually producing spheres (using your numbers) you could try:
arr = sphere((256, 256, 256), 10, (127, 127, 127))
# plot in 3D
import matplotlib.pyplot as plt
from skimage import measure
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
verts, faces, normals, values = measure.marching_cubes(arr, 0.5)
ax.plot_trisurf(
verts[:, 0], verts[:, 1], faces, verts[:, 2], cmap='Spectral',
antialiased=False, linewidth=0.0)
plt.show()
Other approaches
One could implement essentially the same with a combination of np.linalg.norm() and np.indices():
import numpy as np
def sphere_idx(shape, radius, position):
"""Generate an n-dimensional spherical mask."""
assert len(position) == len(shape)
n = len(shape)
position = np.array(position).reshape((-1,) + (1,) * n)
arr = np.linalg.norm(np.indices(shape) - position, axis=0)
return arr <= radius
producing the same results (sphere_ogrid is sphere from above):
import matplotlib.pyplot as plt
funcs = sphere_ogrid, sphere_idx
fig, axs = plt.subplots(1, len(funcs), squeeze=False, figsize=(4 * len(funcs), 4))
d = 500
n = 2
shape = (d,) * n
position = (d // 2,) * n
size = (d // 8)
base = sphere_ogrid(shape, size, position)
for i, func in enumerate(funcs):
arr = func(shape, size, position)
axs[0, i].imshow(arr)
However, this is going to be substantially slower and requires much more temporary memory n_dim * shape of the output.
The benchmarks below seems to support the speed assessment:
base = sphere_ogrid(shape, size, position)
for func in funcs:
print(f"{func.__name__:20s}", np.allclose(base, arr), end=" ")
%timeit -o func(shape, size, position)
# sphere_ogrid True 1000 loops, best of 5: 866 µs per loop
# sphere_idx True 100 loops, best of 5: 4.15 ms per loop
size = 100
radius = 10
x0, y0, z0 = (50, 50, 50)
x, y, z = np.mgrid[0:size:1, 0:size:1, 0:size:1]
r = np.sqrt((x - x0)**2 + (y - y0)**2 + (z - z0)**2)
r[r > radius] = 0
Nice question. My answer to a similar question would be applicable here also.
You can try the following code. In the below mentioned code AA is the matrix that you want.
import numpy as np
from copy import deepcopy
''' size : size of original 3D numpy matrix A.
radius : radius of circle inside A which will be filled with ones.
'''
size, radius = 5, 2
''' A : numpy.ndarray of shape size*size*size. '''
A = np.zeros((size,size, size))
''' AA : copy of A (you don't want the original copy of A to be overwritten.) '''
AA = deepcopy(A)
''' (x0, y0, z0) : coordinates of center of circle inside A. '''
x0, y0, z0 = int(np.floor(A.shape[0]/2)), \
int(np.floor(A.shape[1]/2)), int(np.floor(A.shape[2]/2))
for x in range(x0-radius, x0+radius+1):
for y in range(y0-radius, y0+radius+1):
for z in range(z0-radius, z0+radius+1):
''' deb: measures how far a coordinate in A is far from the center.
deb>=0: inside the sphere.
deb<0: outside the sphere.'''
deb = radius - abs(x0-x) - abs(y0-y) - abs(z0-z)
if (deb)>=0: AA[x,y,z] = 1
Following is an example of the output for size=5 and radius=2 (a sphere of radius 2 pixels inside a numpy array of shape 5*5*5):
[[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 1. 1. 1. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 1. 0. 0.]
[0. 1. 1. 1. 0.]
[1. 1. 1. 1. 1.]
[0. 1. 1. 1. 0.]
[0. 0. 1. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 1. 1. 1. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]]
I haven't printed the output for the size and radius that you had asked for (size=32 and radius=4), as the output will be very long.
Here is how to create voxels space without numpy, the main idea that you calculate distance between center and voxel and if voxel in radius you will create.
from math import sqrt
def distance_dimension(xyz0 = [], xyz1 = []):
delta_OX = pow(xyz0[0] - xyz1[0], 2)
delta_OY = pow(xyz0[1] - xyz1[1], 2)
delta_OZ = pow(xyz0[2] - xyz1[2], 2)
return sqrt(delta_OX+delta_OY+delta_OZ)
def voxels_figure(figure = 'sphere', position = [0,0,0], size = 1):
xmin, xmax = position[0]-size, position[0]+size
ymin, ymax = position[1]-size, position[1]+size
zmin, zmax = position[2]-size, position[2]+size
voxels = []
if figure == 'cube':
for local_z, world_z in zip(range(zmax-zmin), range(zmin, zmax)):
for local_y, world_y in zip(range(ymax-ymin), range(ymin, ymax)):
for local_x, world_x in zip(range(xmax-xmin), range(xmin, xmax)):
voxels.append([world_x,world_y,world_z])
elif figure == 'sphere':
for local_z, world_z in zip(range(zmax-zmin), range(zmin, zmax)):
for local_y, world_y in zip(range(ymax-ymin), range(ymin, ymax)):
for local_x, world_x in zip(range(xmax-xmin), range(xmin, xmax)):
radius = distance_dimension(xyz0 = [world_x, world_y,world_z], xyz1 = position)
if radius < size:
voxels.append([world_x,world_y,world_z])
return voxels
voxels = voxels_figure(figure = 'sphere', position = [0,0,0], size = 3)
After you will get voxels indexes, you can apply ~ones for cube matrix.
Instead of using loops, I propose to use a meshgrid + sphere equation + np.where
import numpy as np
def generate_sphere(volumeSize):
x_ = np.linspace(0,volumeSize, volumeSize)
y_ = np.linspace(0,volumeSize, volumeSize)
z_ = np.linspace(0,volumeSize, volumeSize)
r = int(volumeSize/2) # radius can be changed by changing r value
center = int(volumeSize/2) # center can be changed here
u,v,w = np.meshgrid(x_, y_, z_, indexing='ij')
a = np.power(u-center, 2)+np.power(v-center, 2)+np.power(w-center, 2)
b = np.where(a<=r*r,1,0)
return b
What is the best (elegant and efficient) way in Theano to convert a vector of indices to a matrix of zeros and ones, in which every row is the one-of-N representation of an index?
v = t.ivector() # the vector of indices
n = t.scalar() # the width of the matrix
convert = <your code here>
f = theano.function(inputs=[v, n], outputs=convert)
Example:
n_val = 4
v_val = [1,0,3]
f(v_val, n_val) = [[0,1,0,0],[1,0,0,0],[0,0,0,1]]
I didn't compare the different option, but you can also do it like this. It don't request extra memory.
import numpy as np
import theano
n_val = 4
v_val = np.asarray([1,0,3])
idx = theano.tensor.lvector()
z = theano.tensor.zeros((idx.shape[0], n_val))
one_hot = theano.tensor.set_subtensor(z[theano.tensor.arange(idx.shape[0]), idx], 1)
f = theano.function([idx], one_hot)
print f(v_val)[[ 0. 1. 0. 0.]
[ 1. 0. 0. 0.]
[ 0. 0. 0. 1.]]
It's as simple as:
convert = t.eye(n,n)[v]
There still might be a more efficient solution that doesn't require building the whole identity matrix. This might be problematic for large n and short v's.
There's now a built in function for this theano.tensor.extra_ops.to_one_hot.
y = tensor.as_tensor([3,2,1])
fn = theano.function([], tensor.extra_ops.to_one_hot(y, 4))
print fn()
# [[ 0. 0. 0. 1.]
# [ 0. 0. 1. 0.]
# [ 0. 1. 0. 0.]]