from PIL import Image
Torch Core
Important: Fastai is not a direct dependency, but we want the ability to use some of the torch utilites offered by fastai, we have this notebook, which has been copied from: fastai. At some point having fastai as a direct dep would be good, however for know we are keeping the number of deps as low as we can.
pv
pv (text, verbose)
equals
equals (a, b)
Compares a
and b
for equality; supports sublists, tensors and arrays too
one_is_instance
one_is_instance (a, b, t)
noops
noops (x=None, *args, **kwargs)
Do nothing (method)
noop
noop (x=None, *args, **kwargs)
Do nothing
all_equal
all_equal (a, b)
Compares whether a
and b
are the same length and have the same contents
is_coll
is_coll (o)
Test whether o
is a collection (i.e. has a usable len
)
is_iter
is_iter (o)
Test whether o
can be used in a for
loop
setup_cuda
setup_cuda (benchmark=True)
Sets the main cuda device and sets cudnn.benchmark
to benchmark
Arrays and show
subplots
subplots (nrows:int=1, ncols:int=1, figsize:tuple=None, imsize:int=3, suptitle:str=None, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **kwargs)
Returns a figure and set of subplots to display images of imsize
inches
Type | Default | Details | |
---|---|---|---|
nrows | int | 1 | Number of rows in returned axes grid |
ncols | int | 1 | Number of columns in returned axes grid |
figsize | tuple | None | Width, height in inches of the returned figure |
imsize | int | 3 | Size (in inches) of images that will be displayed in the returned figure |
suptitle | str | None | Title to be set to returned figure |
sharex | bool | False | |
sharey | bool | False | |
squeeze | bool | True | |
subplot_kw | NoneType | None | |
gridspec_kw | NoneType | None | |
kwargs | |||
Returns | (<class ‘matplotlib.figure.Figure’>, <class ‘matplotlib.axes._axes.Axes’>) | Returns both fig and ax as a tuple |
This is used in get_grid
. suptitle
, sharex
, sharey
, squeeze
, subplot_kw
and gridspec_kw
are all passed down to plt.subplots.
show_image
show_image (im, ax=None, figsize=None, title=None, ctx=None, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, interpolation_stage=None, filternorm=True, filterrad=4.0, resample=None, url=None, data=None, **kwargs)
Show a PIL or PyTorch image on ax
.
show_image
can show PIL images…
= Image.open(TEST_IMAGE_BW)
im = show_image(im, cmap="Greys") ax
…and color images with standard CHW
dim order…
= np.array(Image.open(TEST_IMAGE))
im2 = show_image(im2, figsize=(2,2)) ax
…and color images with HWC
dim order…
= torch.as_tensor(im2).permute(2,0,1)
im3 = show_image(im3, figsize=(2,2)) ax
show_titled_image
show_titled_image (o, ax=None, figsize=None, title=None, ctx=None, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, interpolation_stage=None, filternorm=True, filterrad=4.0, resample=None, url=None, data=None, **kwargs)
Call show_image
destructuring o
to (img,title)
'A puppy'), figsize=(2,2)) show_titled_image((im3,
Show all images ims
as subplots with rows
using titles
. suptitle
provides a way to create a figure title for all images. If you use suptitle
, constrained_layout
is used unless you set constrained_layout
to False
.
show_images
show_images (ims, nrows=1, ncols=None, titles=None, figsize:tuple=None, imsize:int=3, suptitle:str=None, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None)
Show all images ims
as subplots with rows
using titles
.
Type | Default | Details | |
---|---|---|---|
ims | |||
nrows | int | 1 | Number of rows in returned axes grid |
ncols | int | 1 | Number of columns in returned axes grid |
titles | NoneType | None | |
figsize | tuple | None | Width, height in inches of the returned figure |
imsize | int | 3 | Size (in inches) of images that will be displayed in the returned figure |
suptitle | str | None | Title to be set to returned figure |
sharex | bool | False | |
sharey | bool | False | |
squeeze | bool | True | |
subplot_kw | NoneType | None | |
gridspec_kw | NoneType | None | |
Returns | (<class ‘matplotlib.figure.Figure’>, <class ‘matplotlib.axes._axes.Axes’>) | Returns both fig and ax as a tuple |
=('number','puppy'),suptitle='Number Puppy', imsize=3) show_images((im,im3),titles
ArrayImage
, ArrayImageBW
and ArrayMask
are subclasses of ndarray
that know how to show themselves.
ArrayBase
An ndarray
that can modify casting behavior
ArrayImageBase
Base class for arrays representing images
ArrayImage
An array representing an image
ArrayImageBW
An array representing an image
ArrayMask
An array representing an image mask
= Image.open(TEST_IMAGE) im
= cast(im, ArrayImage)
im_t type(im_t), ArrayImage) test_eq(
= im_t.show(figsize=(2,2)) ax
test_fig_exists(ax)
Basics
evaluating
evaluating (model)
Temporarily switch to evaluation mode.
tensor
tensor (x, *rest, dtype=None, device=None, requires_grad=False, pin_memory=False)
Like torch.as_tensor
, but handle lists too, and can pass multiple vector elements directly.
1,2,3])), torch.tensor([1,2,3]))
test_eq(tensor(torch.tensor([1,2,3])), torch.tensor([1,2,3]))
test_eq(tensor(array([1,2,3), torch.tensor([1,2,3]))
test_eq(tensor(1.0), torch.tensor(1.0)) test_eq_type(tensor(
set_seed
is useful for reproducibility between runs. It is important to remember that certain classes such as Dataloaders
have internal random number generators that is not effected by this function, so this must be run before such objects are created in order to guarantee reproducibility.
set_seed
set_seed (s, reproducible=False)
Set random seed for random
, torch
, and numpy
(where available)
Here is an example of how set_seed
can be used to reset the state of random number generators.
2*33)
set_seed(= np.random.random()
a1 = torch.rand(())
a2 = random.random()
a3 2*33)
set_seed(= np.random.random()
b1 = torch.rand(())
b2 = random.random()
b3 print('a\'s: {0:3.3f} {1:3.3f} {2:3.3f}'.format(a1,a2,a3))
print('b\'s: {0:3.3f} {1:3.3f} {2:3.3f}'.format(b1,b2,a3))
a's: 0.154 0.498 0.071
b's: 0.154 0.498 0.071
test_eq(a1,b1)
test_eq(a2,b2) test_eq(a3,b3)
get_random_states
and set_random_states
are useful for storing a state so you can go back to it later.
get_random_states
get_random_states ()
Gets states for random
, torch
, and numpy
random number generators
set_random_states
set_random_states (random_state, numpy_state, torch_state, torch_cuda_state, torch_deterministic, torch_benchmark)
Set states for random
, torch
, and numpy
random number generators
Below notice that the old values and rewinded values are the same because we were able to return to the previous state.
= get_random_states()
old_states = (random.random(),np.random.random(),torch.rand(()))
olds = (random.random(),np.random.random(),torch.rand(()))
news **old_states)
set_random_states(= (random.random(),np.random.random(),torch.rand(()))
rewinds
print('olds: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*olds))
print('news: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*news))
print('rewinds: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*rewinds))
olds: 0.435 0.134 0.023
news: 0.246 0.363 0.227
rewinds: 0.435 0.134 0.023
test_ne(olds,news) test_eq(olds,rewinds)
In no_random
we combine the ideas of rewinding state with get_random_states
and set_random_states
with the ability to set_seed
and create a context manager that can allow us to control randomness in a portion of our code.
Note: Similar to torch.random.fork_rng
, but also with numpy
and random
no_random
no_random (seed=42, reproducible=True)
Stores and retrieves state of random number generators. Sets random seed for random
, torch
, and numpy
.
Here are some examples on how we can use no_random
to control the randomness within a block of code.
=get_random_states()
states= (random.random(),np.random.random(),torch.rand(()))
olds **states) #rewinding above random calls
set_random_states(
with no_random():
= (random.random(),np.random.random(),torch.rand(()))
new1 with no_random():
= (random.random(),np.random.random(),torch.rand(()))
new2 with no_random(seed=100):
= (random.random(),np.random.random(),torch.rand(()))
seeded1 with no_random(seed=100):
= (random.random(),np.random.random(),torch.rand(()))
seeded2
= (random.random(),np.random.random(),torch.rand(()))
rewinds
print('olds: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*olds))
print('new1: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*new1))
print('new2: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*new2))
print('seeded1: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*seeded1))
print('seeded2: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*seeded2))
print('rewinds: {0:3.3f} {1:3.3f} {2:3.3f}'.format(*rewinds))
olds: 0.246 0.363 0.227
new1: 0.639 0.375 0.882
new2: 0.639 0.375 0.882
seeded1: 0.146 0.543 0.112
seeded2: 0.146 0.543 0.112
rewinds: 0.246 0.363 0.227
Notice that olds, and rewinds are alos both equal to each other. From this we can see that everything in the with
blocks did not update the state outside of the block. Inside of the block, the state is reset for any particular seed, so for the same seed you should get the same random number generator results.
Note: It is important to remember that classes like Dataloader
have internal random number generators, and no_random
will have no effect on those random number generators.
test_ne(olds,new1)
test_eq(new1,new2)
test_ne(new1,seeded1)
test_eq(seeded1,seeded2) test_eq(olds,rewinds)
unsqueeze
unsqueeze (x, dim=-1, n=1)
Same as torch.unsqueeze
but can add n
dims
= tensor([1])
t = unsqueeze(t, n=2)
t2 None,None]) test_eq(t2,t[:,
unsqueeze_
unsqueeze_ (x, dim=-1, n=1)
Same as torch.unsqueeze_
but can add n
dims
= tensor([1])
t =2)
unsqueeze_(t, n1]).view(1,1,1)) test_eq(t, tensor([
apply
apply (func, x, *args, **kwargs)
Apply func
recursively to x
, passing on args
maybe_gather
maybe_gather (x, axis=0)
Gather copies of x
on axis
(if training is distributed)
to_detach
to_detach (b, cpu=True, gather=True)
Recursively detach lists of tensors in b
; put them on the CPU if cpu=True
.
gather
only applies during distributed training and the result tensor will be the one gathered across processes if gather=True
(as a result, the batch size will be multiplied by the number of processes).
to_half
to_half (b)
Recursively map lists of tensors in b
to FP16.
to_float
to_float (b)
Recursively map lists of int tensors in b
to float.
default_device
default_device (use_cuda=-1)
Return or set default device; use_cuda
: None - CUDA if available; True - error if not available; False - CPU
default_device
default_device (use=-1)
Return or set default device; use_cuda
: -1 - CUDA/mps if available; True - error if not available; False - CPU
if torch.cuda.is_available():
= torch.device(torch.cuda.current_device())
_td -1), _td)
test_eq(default_device(True), _td)
test_eq(default_device(else:
False), torch.device('cpu'))
test_eq(default_device(-1); default_device(
to_device
to_device (b, device=None, non_blocking=False)
Recursively put b
on device
.
= to_device((3,(tensor(3),tensor(2))))
t = t t1,(t2,t3)
if torch.cuda.is_available():
3,(tensor(3).cuda(),tensor(2).cuda())))
test_eq_type(t,(type(), "torch.cuda.LongTensor")
test_eq(t2.type(), "torch.cuda.LongTensor") test_eq(t3.
to_cpu
to_cpu (b)
Recursively map lists of tensors in b
to the cpu.
= to_cpu(t3)
t3 type(), "torch.LongTensor")
test_eq(t3.2) test_eq(t3,
to_np
to_np (x)
Convert a tensor to a numpy array.
= to_np(t3)
t3 type(t3), np.ndarray)
test_eq(2) test_eq(t3,
to_concat
to_concat (xs, dim=0)
Concat the element in xs
(recursively if they are tuples/lists of tensors)
1,2]), tensor([3,4])]), tensor([1,2,3,4]))
test_eq(to_concat([tensor([1,2]]), tensor([[3,4]])], dim=1), tensor([[1,2,3,4]]))
test_eq(to_concat([tensor([[1,2]), tensor([3,4])), (tensor([3,4]), tensor([5,6]))]), (tensor([1,2,3,4]), tensor([3,4,5,6])))
test_eq_type(to_concat([(tensor([1,2]), tensor([3,4])], [tensor([3,4]), tensor([5,6])]]), [tensor([1,2,3,4]), tensor([3,4,5,6])])
test_eq_type(to_concat([[tensor([1,2]),), (tensor([3,4]),)]), (tensor([1,2,3,4]),))
test_eq_type(to_concat([(tensor([
1,2]]), tensor([[3,4], [5,6]])], dim=1), [tensor([1]),tensor([3, 5]),tensor([4, 6])]) test_eq(to_concat([tensor([[
type(to_concat([dict(foo=tensor([1,2]), bar=tensor(3,4))])), dict) test_eq(
Tensor subtypes
Tensor.set_meta
Tensor.set_meta (x, as_copy=False)
Set all metadata in __dict__
Tensor.as_subclass
Tensor.as_subclass (typ)
Cast to typ
and include __dict__
and meta
Tensor.set_meta
and Tensor.as_subclass
work together to maintain __dict__
after casting.
class _T(Tensor): pass
= tensor(1.).requires_grad_()
t = 1
t.img_size = t.as_subclass(_T)
t2
test_eq(t.img_size, t2.img_size)1)
test_eq(t2.img_size, assert(t2.requires_grad_)
TensorBase
TensorBase (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
TensorBase
hooks into __torch_function__
to ensure metadata is not lost. To see all functions being called, set debug
.
= TensorBase(1)
a =True
a.debug1/(a+1)
TensorBase(0.5000)
TensorBase
and its subclasses also allow for passing through metadata size as img_size…
from torch.utils.data._utils.collate import default_collate
= TensorBase(1,img_size=(128,128))
a 128,128))
test_eq(a.img_size,(= cast(a,TensorBase)
b 128,128))
test_eq(b.img_size,(0).img_size,(128,128))
test_eq(torch.stack([a,b],
128,128)) test_eq(default_collate([a,b]).img_size,(
class _TImage(TensorBase): pass
class _TImage2(_TImage): pass
= _TImage([1.])
t1 = _TImage2([1.])
t2 +t1 t2
_TImage2([2.])
class _T(TensorBase): pass
= _T(range(5))
t 0], 0)
test_eq(t[+1, _T(range(1,6)))
test_eq_type(trepr(t), '_T([0, 1, 2, 3, 4])')
test_eq(False,False,True,True,True])], _T([2,3,4]))
test_eq_type(t[_T([2,3,4])], _T([2,3,4]))
test_eq_type(t[_T([type(pickle.loads(pickle.dumps(t))), _T)
test_eq(1), _T([1]))
test_eq_type(t.new_ones(1,2]), _T([1,2])) test_eq_type(t.new_tensor([
= tensor([1,2,3])
t = TensorBase([False,True,True])
m 2,3]))
test_eq(t[m], tensor([= tensor([[1,2,3],[1,2,3]])
t = cast(tensor([[False,True,True],
m False,True,True]]), TensorBase)
[2,3,2,3])) test_eq(t[m], tensor([
= tensor([[1,2,3],[1,2,3]])
t = 1
t.img_size = cast(t, TensorBase)
t2
test_eq(t2.img_size, t.img_size)= retain_type(tensor([4,5,6]), t2)
x
test_eq(x.img_size, t.img_size)= TensorBase([[1,2,3],[1,2,3]], img_size=1)
t3
test_eq(t3.img_size, t.img_size)= t2+1
t4 = 2
t4.img_size 1)
test_eq(t2.img_size, 2)
test_eq(t4.img_size, # this will fail with `Tensor` but works with `TensorBase`
test_eq(pickle.loads(pickle.dumps(t2)).img_size, t2.img_size)
TensorImageBase
TensorImageBase (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
TensorImage
TensorImage (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
TensorImageBW
TensorImageBW (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
TensorMask
TensorMask (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
= Image.open(TEST_IMAGE)
im = cast(array(im), TensorImage)
im_t type(im_t), TensorImage) test_eq(
= cast(tensor(1), TensorMask)
im_t2 type(im_t2), TensorMask)
test_eq(1))
test_eq(im_t2, tensor(= im_t.show(figsize=(2,2))
ax =(im_t == im_t2) _
test_fig_exists(ax)
Operations between TensorMask
and TensorImageBase
objects return the type of the TensorImageBase
object:
= TensorMask([1,2])
a 1)+a, TensorImage([2,3]))
test_eq_type(TensorImage(1-a, TensorMask([0,-1])) test_eq_type(
TensorFlowField
TensorFlowField (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
= TensorImage([1.]).view(1,1,1,1)
t1 = TensorFlowField([1.,1.]).view(1,1,1,2)
t2 0.25]]]])) test_eq_type(F.grid_sample(t1, t2), TensorImage([[[[
TensorCategory
TensorCategory (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
= TensorCategory([1,2,3])
tc = TensorMask([0,2,4,5])
mask_t = TensorImage([0,2,4,5])
im_t 2,4,5]))
test_eq(mask_t[tc], tensor([2,4,5])) test_eq(im_t[tc], tensor([
TensorMultiCategory
TensorMultiCategory (x, **kwargs)
A Tensor
which support subclass pickling, and maintains metadata when casting or after methods
TitledTensorScalar
TitledTensorScalar (x, **kwargs)
A tensor containing a scalar that has a show
method
L.cat
L.cat (dim=0)
Same as torch.cat
L.stack
L.stack (dim=0)
Same as torch.stack
L.tensored
L.tensored ()
mapped(tensor)
L.tensored
L.tensored ()
mapped(tensor)
There are shortcuts for torch.stack
and torch.cat
if your L
contains tensors or something convertible. You can manually convert with tensored
.
= L(([1,2],[3,4]))
t 1,2),tensor(3,4)]) test_eq(t.tensored(), [tensor(
L.stack
L.stack (dim=0)
Same as torch.stack
1,2],[3,4]])) test_eq(t.stack(), tensor([[
L.cat
L.cat (dim=0)
Same as torch.cat
1,2,3,4])) test_eq(t.cat(), tensor([
Chunks
concat
concat (*ls)
Concatenate tensors, arrays, lists, or tuples
= [1],[1,2],[1,1,2]
a,b,c
test_eq(concat(a,b), c)tuple (a),tuple (b)), tuple (c))
test_eq_type(concat(
test_eq_type(concat(array (a),array (b)), array (c))
test_eq_type(concat(tensor(a),tensor(b)), tensor(c))
test_eq_type(concat(TensorBase(a),TensorBase(b)), TensorBase(c))1,1],1), [1,1,1])
test_eq_type(concat([1,1,1), L(1,1,1))
test_eq_type(concat(1,2),1), L(1,2,1)) test_eq_type(concat(L(
Chunks
Chunks (chunks, lens=None)
Slice and int indexing into a list of lists
= L(list(string.ascii_lowercase[a:b]) for a,b in ((0,3),(3,7),(7,8),(8,16),(16,24),(24,26)))
docs
= Chunks(docs)
b for o in range(0,5)], ['a','b','c','d','e'])
test_eq([b[ o] -o] for o in range(1,6)], ['z','y','x','w','v'])
test_eq([b[6:13], 'g,h,i,j,k,l,m'.split(','))
test_eq(b[20:77], 'u,v,w,x,y,z'.split(','))
test_eq(b[5], 'a,b,c,d,e'.split(','))
test_eq(b[:2], 'a,b'.split(',')) test_eq(b[:
= torch.arange(26)
t = L(t[a:b] for a,b in ((0,3),(3,7),(7,8),(8,16),(16,24),(24,26)))
docs = Chunks(docs)
b for o in range(0,5)], range(0,5))
test_eq([b[ o] -o] for o in range(1,6)], [25,24,23,22,21])
test_eq([b[6:13], torch.arange(6,13))
test_eq(b[20:77], torch.arange(20,26))
test_eq(b[5], torch.arange(5))
test_eq(b[:2], torch.arange(2)) test_eq(b[:
= L(TensorBase(t[a:b]) for a,b in ((0,3),(3,7),(7,8),(8,16),(16,24),(24,26)))
docs = Chunks(docs)
b 2], TensorBase(range(2)))
test_eq_type(b[:5], TensorBase(range(5)))
test_eq_type(b[:9:13], TensorBase(range(9,13))) test_eq_type(b[
Simple types
show_title
show_title (o, ax=None, ctx=None, label=None, color='black', **kwargs)
Set title of ax
to o
, or print o
if ax
is None
lambda: show_title("title"), "title")
test_stdout(# ensure that col names are unique when showing to a pandas series
assert show_title("title", ctx=pd.Series(dict(a=1)), label='a').equals(pd.Series(dict(a=1,a_='title')))
ShowTitle
ShowTitle ()
Base class that adds a simple show
TitledInt
An int
with show
TitledStr
An str
with show
TitledFloat
TitledFloat (x=0)
A float
with show
lambda: TitledStr('s').show(), 's')
test_stdout(lambda: TitledInt(1).show(), '1') test_stdout(
TitledTuple
TitledTuple (x=None, *rest)
A fastuple
with show
TitledStr.truncate
TitledStr.truncate (n)
Truncate self to n
Other functions
get_empty_df
get_empty_df (n)
Return n
empty rows of a dataframe
display_df
display_df (df)
Display df
in a notebook or defaults to print
get_first
get_first (c)
Get the first element of c, even if c is a dataframe
one_param
one_param (m)
First parameter in m
item_find
item_find (x, idx=0)
Recursively takes the idx
-th element of x
find_device
find_device (b)
Recursively search the device of b
.
= to_device(tensor(0))
t2 = default_device()
dev
test_eq(find_device(t2), dev)
test_eq(find_device([t2,t2]), dev)'a':t2,'b':t2}), dev)
test_eq(find_device({'a':[[t2],[t2]],'b':t2}), dev) test_eq(find_device({
find_bs
find_bs (b)
Recursively search the batch size of b
.
= torch.randn(4,5)
x = [1,2,3]
x1 3)
test_eq(find_bs(x1), 4)
test_eq(find_bs(x), 4)
test_eq(find_bs((x,x)), 4)
test_eq(find_bs([x, x]), 'a':x,'b':x}), 4)
test_eq(find_bs({'a':[[x],[x]],'b':x}), 4) test_eq(find_bs({
np_func
np_func (f)
Convert a function taking and returning numpy arrays to one taking and returning tensors
This decorator is particularly useful for using numpy functions as fastai metrics, for instance:
from sklearn.metrics import f1_score
@np_func
def f1(inp,targ): return f1_score(targ, inp)
= array([0,1,1]),array([1,0,1])
a1,a2 = f1(tensor(a1),tensor(a2))
t
test_eq(f1_score(a1,a2), t)assert isinstance(t,Tensor)
Module
Module ()
Same as nn.Module
, but no need for subclasses to call super().__init__
class _T(Module):
def __init__(self): self.f = nn.Linear(1,1)
def forward(self,x): return self.f(x)
= _T()
t 1.])) t(tensor([
tensor([-0.0832], grad_fn=<AddBackward0>)
get_model
get_model (model)
Return the model maybe wrapped inside model
.
one_hot
one_hot (x, c)
One-hot encode x
with c
classes.
1,4], 5), tensor(0,1,0,0,1).byte())
test_eq(one_hot([5), tensor(0,0,0,0,0).byte())
test_eq(one_hot(torch.tensor([]), 2, 5), tensor(0,0,1,0,0).byte()) test_eq(one_hot(
one_hot_decode
one_hot_decode (x, vocab=None)
0,1,0,0,1)), [1,4])
test_eq(one_hot_decode(tensor(0,0,0,0,0)), [ ])
test_eq(one_hot_decode(tensor(0,0,1,0,0)), [2 ]) test_eq(one_hot_decode(tensor(
params
params (m)
Return all parameters of m
trainable_params
trainable_params (m)
Return all trainable parameters of m
= nn.Linear(4,5)
m
test_eq(trainable_params(m), [m.weight, m.bias])False)
m.weight.requires_grad_( test_eq(trainable_params(m), [m.bias])
norm_bias_params
norm_bias_params (m, with_bias=True)
Return all bias and BatchNorm parameters
for norm_func in [nn.BatchNorm1d, partial(nn.InstanceNorm1d, affine=True)]:
= nn.Sequential(nn.Linear(10,20), norm_func(20), nn.Conv1d(3,4, 3))
model 0].bias, model[1].weight, model[1].bias, model[2].bias])
test_eq(norm_bias_params(model), [model[= nn.ModuleList([nn.Linear(10,20, bias=False), nn.Sequential(norm_func(20), nn.Conv1d(3,4,3))])
model 1][0].weight, model[1][0].bias, model[1][1].bias])
test_eq(norm_bias_params(model), [model[= nn.ModuleList([nn.Linear(10,20), nn.Sequential(norm_func(20), nn.Conv1d(3,4,3))])
model =False), [model[1][0].weight, model[1][0].bias]) test_eq(norm_bias_params(model, with_bias
batch_to_samples
batch_to_samples (b, max_n=10)
‘Transposes’ a batch to (at most max_n
) samples
= tensor([1,2,3])
t +1], max_n=2), ([1,2],[2,3]))
test_eq(batch_to_samples([t,t1,2,3]), 10), [1, 2, 3])
test_eq(batch_to_samples(tensor([1,2,3]), tensor([4,5,6])], 10), [(1, 4), (2, 5), (3, 6)])
test_eq(batch_to_samples([tensor([1,2,3]), tensor([4,5,6])], 2), [(1, 4), (2, 5)])
test_eq(batch_to_samples([tensor([1,2,3]), [tensor([4,5,6]),tensor([7,8,9])]], 10),
test_eq(batch_to_samples([tensor([1, (4, 7)), (2, (5, 8)), (3, (6, 9))])
[(1,2,3]), [tensor([4,5,6]),tensor([7,8,9])]], 2), [(1, (4, 7)), (2, (5, 8))])
test_eq(batch_to_samples([tensor([
= fastuple(tensor([1,2,3]),TensorBase([2,3,4]))
t 0][1], TensorBase(2))
test_eq_type(batch_to_samples(t)[map(type), [fastuple]*3) test_eq(batch_to_samples(t).
Tensor.interp_1d
Tensor.interp_1d (x:torch.Tensor, xp, fp)
Same as np.interp
= tensor(0,1,2,4,8,64).float()
brks = tensor(range_of(brks)).float()
ys /= ys[-1].item()
ys = tensor(0.2,0.5,0.8,3,5,63)
pts
= pts.interp_1d(brks, ys)
preds
test_close(preds.numpy(), np.interp(pts.numpy(), brks.numpy(), ys.numpy()))
plt.scatter(brks,ys)
plt.scatter(pts,preds)'breaks','preds']); plt.legend([
Tensor.pca
Tensor.pca (x:torch.Tensor, k=2)
Compute PCA of x
with k
dimensions.
logit
logit (x)
Logit of x
, clamped to avoid inf.
num_distrib
num_distrib ()
Return the number of processes in distributed training (if applicable).
rank_distrib
rank_distrib ()
Return the distributed rank of this process (if applicable).
distrib_barrier
distrib_barrier ()
Place a synchronization barrier in distributed training
After calling this, ALL sub-processes in the pytorch process group must arrive here before proceeding.
Path.save_array
Path.save_array (p:pathlib.Path, o, complib='lz4', lvl=3)
Save numpy array to a compressed pytables
file, using compression level lvl
Compression lib can be any of: blosclz, lz4, lz4hc, snappy, zlib or zstd.
Path.load_array
Path.load_array (p:pathlib.Path)
Save numpy array to a pytables
file
base_doc
base_doc (elt)
Print a base documentation of elt
doc
doc (elt)
Try to use doc form nbdev and fall back to base_doc
nested_reorder
nested_reorder (t, idxs)
Reorder all tensors in t
using idxs
= tensor([0,1,2,3,4,5])
x = tensor([2,5,1,0,3,4])
idxs
test_eq_type(nested_reorder(([x], x), idxs), ([idxs], idxs))
= L(0,1,2,3,4,5)
y = L(i.item() for i in idxs)
z test_eq_type(nested_reorder((y, x), idxs), (z,idxs))
flatten_check
flatten_check (inp, targ)
Check that out
and targ
have the same number of elements and flatten them.
= torch.randn(5,4),torch.randn(20)
x1,x2 = flatten_check(x1,x2)
x1,x2 20])
test_eq(x1.shape, [20])
test_eq(x2.shape, [= torch.randn(5,4),torch.randn(21)
x1,x2 lambda: flatten_check(x1,x2)) test_fail(
Image helpers
make_cross_image
make_cross_image (bw=True)
Create a tensor containing a cross image, either bw
(True) or color
="Greys"); plt.imshow(make_cross_image(), cmap
False).permute(1,2,0)); plt.imshow(make_cross_image(
show_image_batch
show_image_batch (b, show=<function show_titled_image>, items=9, cols=3, figsize=None, **kwargs)
Display batch b
in a grid of size items
with cols
width
open(TEST_IMAGE_BW),Image.open(TEST_IMAGE)],['bw','color']), items=2) show_image_batch(([Image.
Model init
requires_grad
requires_grad (m)
Check if the first parameter of m
requires grad or not
= nn.Linear(4,5)
tst assert requires_grad(tst)
for p in tst.parameters(): p.requires_grad_(False)
assert not requires_grad(tst)
init_default
init_default (m, func=<function kaiming_normal_>)
Initialize m
weights with func
and set bias
to 0.
= nn.Linear(4,5)
tst -1,1)
tst.weight.data.uniform_(-1,1)
tst.bias.data.uniform_(= init_default(tst, func = lambda x: x.data.fill_(1.))
tst 5,4))
test_eq(tst.weight, torch.ones(5)) test_eq(tst.bias, torch.zeros(
cond_init
cond_init (m, func)
Apply init_default
to m
unless it’s a batchnorm module
= nn.Linear(4,5)
tst -1,1)
tst.weight.data.uniform_(-1,1)
tst.bias.data.uniform_(= lambda x: x.data.fill_(1.))
cond_init(tst, func 5,4))
test_eq(tst.weight, torch.ones(5))
test_eq(tst.bias, torch.zeros(
= nn.BatchNorm2d(5)
tst = [tst.weight.clone(), tst.bias.clone()]
init = lambda x: x.data.fill_(1.))
cond_init(tst, func 0])
test_eq(tst.weight, init[1]) test_eq(tst.bias, init[
apply_leaf
apply_leaf (m, f)
Apply f
to children of m
.
= nn.Sequential(nn.Linear(4,5), nn.Sequential(nn.Linear(4,5), nn.Linear(4,5)))
tst =lambda x: x.data.fill_(1.)))
apply_leaf(tst, partial(init_default, funcfor l in [tst[0], *tst[1]]: test_eq(l.weight, torch.ones(5,4))
for l in [tst[0], *tst[1]]: test_eq(l.bias, torch.zeros(5))
apply_init
apply_init (m, func=<function kaiming_normal_>)
Initialize all non-batchnorm layers of m
with func
.
= nn.Sequential(nn.Linear(4,5), nn.Sequential(nn.Linear(4,5), nn.BatchNorm1d(5)))
tst = [tst[1][1].weight.clone(), tst[1][1].bias.clone()]
init =lambda x: x.data.fill_(1.))
apply_init(tst, funcfor l in [tst[0], tst[1][0]]: test_eq(l.weight, torch.ones(5,4))
for l in [tst[0], tst[1][0]]: test_eq(l.bias, torch.zeros(5))
1][1].weight, init[0])
test_eq(tst[1][1].bias, init[1]) test_eq(tst[
autograd jit functions
script_use_ctx
script_use_ctx (f)
Decorator: create jit script and pass everything in ctx.saved_variables to
f, after
*args`
script_save_ctx
script_save_ctx (static, *argidx)
Decorator: create jit script and save args with indices argidx
using ctx.save_for_backward
script_fwd
script_fwd (*argidx)
Decorator: create static jit script and save args with indices argidx
using ctx.save_for_backward
script_bwd
script_bwd (f)
Decorator: create static jit script and pass everything in ctx.saved_variables to
f, after
*args`
grad_module
grad_module (cls)
Decorator: convert cls
into an autograd function
ismin_torch
ismin_torch (min_version)
Check if torch.__version__
>= min_version
using packaging.version
notmax_torch
notmax_torch (max_version)
Check if torch.__version__
< max_version
using packaging.version