Package: ivy
🚀 We are granting access toIvy's Tracer and Transpilerto all of our users,sign up on our consoleif you
want to test them out!StatusUnified AIIvy is an open-source machine learning framework that
enables you to:🔥Autotune your model: Automatically find the optimal framework, compiler infrastructure and hardware for your specific use case usingivy.autotune.🔄Convert code into any framework: Use and build on top of any model, library, or device by converting any code from one framework to another usingivy.transpile.⚒️Write framework-agnostic code: Write your code once in ivy and then choose the most appropriate ML framework as the backend to leverage all the benefits and tools.Join our growing community🌍 to connect with people using Ivy.Let'sunify.aitogether 🦾Getting startedThe best way to get familiar with Ivy is to go through theDemos, a good starting point isLearn The Basics.The most important notebooks are:How to convert your code between frameworks?How to write framework-agnostic code?Accelerate your development (WIP)Autotune and optimize models (WIP)Installing ivyThere are various ways to use Ivy, depending on your preferred
environment:Installing using pipThe easiest way to set up Ivy is to install it using pip with the
following command:pipinstallivyor alternatively:python3-mpipinstallivyDockerIf you prefer to use containers, we also have pre-built Docker images
with all the supported frameworks and some relevant packages already
installed, which you can pull from:dockerpullunifyai/ivy:latestIf you are working on a GPU device, you can pull from:dockerpullunifyai/ivy:latest-gpuFrom SourceYou can also install Ivy from source if you want to take advantage of
the latest changes, but we can't ensure everything will work as
expected. :sweat_smile:gitclonehttps://github.com/unifyai/ivy.gitcdivy
pipinstall--user-e.or alternatively, for the last step:python3-mpipinstall--user-e.If you want to set up testing and various frameworks it's probably     best
to check out the [Contributing - Setting
Up](https://unify.ai/docs/ivy/overview/contributing/setting_up. html#setting-up)
page, where OS-specific and IDE-specific instructions and video
tutorials to do so are available!Using IvyAfter installing Ivy, you can start using it straight away, for example:Transpiling any code from one framework to anotherimportivyimporttorchimportjaxdefjax_fn(x):a=jax.numpy.dot(x,x)b=jax.numpy.mean(x)returnx*a+bjax_x=jax.numpy.array([1,2,3])torch_x=torch.tensor([1,2,3])torch_fn=ivy.transpile(jax_fn,source="jax",to="torch",args=(jax_x,))ret=torch_fn(torch_x)Running your code with any backendimportivyimporttorchimportjaxivy.set_backend("jax")x=jax.numpy.array([1,2,3])y=jax.numpy.array([3,2,1])z=ivy.add(x,y)ivy.set_backend('torch')x=torch.tensor([1,2,3])y=torch.tensor([3,2,1])z=ivy.add(x,y)DocumentationYou can find Ivy's documentation on theDocs page, which includes:Motivation: This contextualizes the problem Ivy is trying to solve by going overThe currentML Explosion.Explaining why it is importantto solve this problem.Explaining how we adhere to existingstandardsto make this happen.Related Work: Which paints a picture of the role Ivy plays in the ML stack, comparing it to other existing solutions in terms of functionalities and abstraction level.Design: A user-focused guide about the design decision behind the architecture and the main building blocks of Ivy.Deep Dive: Which delves deeper into the implementation details of Ivy and is oriented towards potential contributors to the code base.ExamplesTheExamples pagefeatures a wide range of
demos and tutorials showcasing the functionalities of Ivy along with
multiple use cases, but feel free to check out some shorter
framework-specific examples here ⬇️I'm using PyTorchYou can use Ivy to get PyTorch code from:Any modelFrom TensorFlowimportivyimporttorchimporttensorflowastf# Get a pretrained keras modeleff_encoder=tf.keras.applications.efficientnet_v2.EfficientNetV2B0(include_top=False,weights="imagenet",input_shape=(224,224,3))# Transpile it into a torch.nn.Module with the corresponding parametersnoise=tf.random.normal(shape=(1,224,224,3))torch_eff_encoder=ivy.transpile(eff_encoder,to="torch",args=(noise,))# Build a classifier using the transpiled encoderclassClassifier(torch.nn.Module):def__init__(self,num_classes=20):super().__init__()self.encoder=torch_eff_encoderself.fc=torch.nn.Linear(1280,num_classes)defforward(self,x):x=self.encoder(x)returnself.fc(x)# Initialize a trainable, customizable, torch.nn.Moduleclassifier=Classifier()ret=classifier(torch.rand((1,244,244,3)))From JAXimportivyimportjaximporttorch# Get a pretrained haiku model# https://unify.ai/demos/scripts/deepmind_perceiver_io.pyfromdeepmind_perceiver_ioimportkey,perceiver_backbone# Transpile it into a torch.nn.Module with the corresponding parametersdummy_input=jax.random.uniform(key,shape=(1,3,224,224))params=perceiver_backbone.init(rng=key,images=dummy_input)backbone=ivy.transpile(perceiver_backbone,to="torch",params_v=params,kwargs={"images":dummy_input})# Build a classifier using the transpiled backboneclassPerceiverIOClassifier(torch.nn.Module):def__init__(self,num_classes=20):super().__init__()self.backbone=backboneself.max_pool=torch.nn.MaxPool2d((512,1))self.flatten=torch.nn.Flatten()self.fc=torch.nn.Linear(1024,num_classes)defforward(self,x):x=self.backbone(images=x)x=self.flatten(self.max_pool(x))returnself.fc(x)# Initialize a trainable, customizable, torch.nn.Moduleclassifier=PerceiverIOClassifier()ret=classifier(torch.rand((1,3,224,224)))Any libraryFrom Tensorflowimportivyimporttorchimportosos.environ["SM_FRAMEWORK"]="tf.keras"importsegmentation_modelsassm# transpile sm from tensorflow to torchtorch_sm=ivy.transpile(sm,source="tensorflow",to="torch")# get some image-like arraysoutput=torch.rand((1,3,512,512))target=torch.rand((1,3,512,512))# and use the transpiled version of any function from the library!out=torch_sm.metrics.iou_score(output,target)From JAXimportivyimportraximporttorch# transpile rax from jax to torchtorch_rax=ivy.transpile(rax,source="jax",to="torch")# get some arraysscores=torch.tensor([2.2,1.3,5.4])labels=torch.tensor([1.0,0.0,0.0])# and use the transpiled version of any function from the library!out=torch_rax.poly1_softmax_loss(scores,labels)From NumPyimportivyimporttorchimportmadmom# transpile madmon from numpy to torchtorch_madmom=ivy.transpile(madmom,source="numpy",to="torch")# get some arraysfreqs=torch.arange(20)*10# and use the transpiled version of any function from the library!out=torch_madmom.audio.filters.hz2midi(freqs)Any functionFrom Tensorflowimportivyimporttensorflowastfimporttorchdefloss(predictions,targets):returntf.sqrt(tf.reduce_mean(tf.square(predictions-targets)))# transpile any function from tf to torchtorch_loss=ivy.transpile(loss,source="tensorflow",to="torch")# get some arraysp=torch.tensor([3.0,2.0,1.0])t=torch.tensor([0.0,0.0,0.0])# and use the transpiled version!out=torch_loss(p,t)From JAXimportivyimportjax.numpyasjnpimporttorchdefloss(predictions,targets):returnjnp.sqrt(jnp.mean((predictions-targets)**2))# transpile any function from jax to torchtorch_loss=ivy.transpile(loss,source="jax",to="torch")# get some arraysp=torch.tensor([3.0,2.0,1.0])t=torch.tensor([0.0,0.0,0.0])# and use the transpiled version!out=torch_loss(p,t)From NumPyimportivyimportnumpyasnpimporttorchdefloss(predictions,targets):returnnp.sqrt(np.mean((predictions-targets)**2))# transpile any function from numpy to torchtorch_loss=ivy.transpile(loss,source="numpy",to="torch")# get some arraysp=torch.tensor([3.0,2.0,1.0])t=torch.tensor([0.0,0.0,0.0])# and use the transpiled version!out=torch_loss(p,t)I'm using TensorFlowYou can use Ivy to get TensorFlow code from:Any modelFrom PyTorchimportivyimporttorchimporttimmimporttensorflowastf# Get a pretrained pytorch modelmlp_encoder=timm.create_model("mixer_b16_224",pretrained=True,num_classes=0)# Transpile it into a keras.Model with the corresponding parametersnoise=torch.randn(1,3,224,224)mlp_encoder=ivy.transpile(mlp_encoder,to="tensorflow",args=(noise,))# Build a classifier using the transpiled encoderclassClassifier(tf.keras.Model):def__init__(self):super().__init__()self.encoder=mlp_encoderself.output_dense=tf.keras.layers.Dense(units=1000,activation="softmax")defcall(self,x):x=self.encoder(x)returnself.output_dense(x)# Transform the classifier and use it as a standard keras.Modelx=tf.random.normal(shape=(1,3,224,224))model=Classifier()ret=model(x)From JAXimportivyimportjaximporttensorflowastf# Get a pretrained haiku model# https://unify.ai/demos/scripts/deepmind_perceiver_io.pyfromdeepmind_perceiver_ioimportkey,perceiver_backbone# Transpile it into a tf.keras.Model with the corresponding parametersdummy_input=jax.random.uniform(key,shape=(1,3,224,224))params=perceiver_backbone.init(rng=key,images=dummy_input)backbone=ivy.transpile(perceiver_backbone,to="tensorflow",params_v=params,args=(dummy_input,))# Build a classifier using the transpiled backboneclassPerceiverIOClassifier(tf.keras.Model):def__init__(self,num_classes=20):super().__init__()self.backbone=backboneself.max_pool=tf.keras.layers.MaxPooling1D(pool_size=512)self.flatten=tf.keras.layers.Flatten()self.fc=tf.keras.layers.Dense(num_classes)defcall(self,x):x=self.backbone(x)x=self.flatten(self.max_pool(x))returnself.fc(x)# Initialize a trainable, customizable, tf.keras.Modelx=tf.random.normal(shape=(1,3,224,224))classifier=PerceiverIOClassifier()ret=classifier(x)Any libraryFrom PyTorchimportivyimportkorniaimportrequestsimportnumpyasnpimporttensorflowastffromPILimportImage# transpile kornia from torch to tensorflowtf_kornia=ivy.transpile(kornia,source="torch",to="tensorflow")# get an imageurl="http://images.cocodataset.org/train2017/000000000034.jpg"raw_img=Image.open(requests.get(url,stream=True).raw)# convert it to the format expected by korniaimg=np.array(raw_img)img=tf.transpose(tf.constant(img),(2,0,1))img=tf.expand_dims(img,0)/255# and use the transpiled version of any function from the library!out=tf_kornia.enhance.sharpness(img,5)From JAXimportivyimportraximporttensorflowastf# transpile rax from jax to tensorflowtf_rax=ivy.transpile(rax,source="jax",to="tensorflow")# get some arraysscores=tf.constant([2.2,1.3,5.4])labels=tf.constant([1.0,0.0,0.0])# and use the transpiled version of any function from the library!out=tf_rax.poly1_softmax_loss(scores,labels)From NumPyimportivyimportmadmomimporttensorflowastf# transpile madmom from numpy to tensorflowtf_madmom=ivy.transpile(madmom,source="numpy",to="tensorflow")# get some arraysfreqs=tf.range(20)*10# and use the transpiled version of any function from the library!out=tf_madmom.audio.filters.hz2midi(freqs)Any functionFrom PyTorchimportivyimporttorchimporttensorflowastfdefloss(predictions,targets):returntorch.sqrt(torch.mean((predictions-targets)**2))# transpile any function from torch to tensorflowtf_loss=ivy.transpile(loss,source="torch",to="tensorflow")# get some arraysp=tf.constant([3.0,2.0,1.0])t=tf.constant([0.0,0.0,0.0])# and use the transpiled version!out=tf_loss(p,t)From JAXimportivyimportjax.numpyasjnpimporttensorflowastfdefloss(predictions,targets):returnjnp.sqrt(jnp.mean((predictions-targets)**2))# transpile any function from jax to tensorflowtf_loss=ivy.transpile(loss,source="jax",to="tensorflow")# get some arraysp=tf.constant([3.0,2.0,1.0])t=tf.constant([0.0,0.0,0.0])# and use the transpiled version!out=tf_loss(p,t)From NumPyimportivyimportnumpyasnpimporttensorflowastfdefloss(predictions,targets):returnnp.sqrt(np.mean((predictions-targets)**2))# transpile any function from numpy to tensorflowtf_loss=ivy.transpile(loss,source="numpy",to="tensorflow")# get some arraysp=tf.constant([3.0,2.0,1.0])t=tf.constant([0.0,0.0,0.0])# and use the transpiled version!out=tf_loss(p,t)I'm using JaxYou can use Ivy to get JAX code from:Any modelFrom PyTorchimportivyimporttimmimporttorchimportjaximporthaikuashk# Get a pretrained pytorch modelmlp_encoder=timm.create_model("mixer_b16_224",pretrained=True,num_classes=0)# Transpile it into a hk.Module with the corresponding parametersnoise=torch.randn(1,3,224,224)mlp_encoder=ivy.transpile(mlp_encoder,to="jax",args=(noise,))# Build a classifier using the transpiled encoderclassClassifier(hk.Module):def__init__(self,num_classes=1000):super().__init__()self.encoder=mlp_encoder()self.fc=hk.Linear(output_size=num_classes,with_bias=True)def__call__(self,x):x=self.encoder(x)x=self.fc(x)returnxdef_forward_classifier(x):module=Classifier()returnmodule(x)# Transform the classifier and use it as a standard hk.Modulerng_key=jax.random.PRNGKey(42)x=jax.random.uniform(key=rng_key,shape=(1,3,224,224),dtype=jax.numpy.float32)forward_classifier=hk.transform(_forward_classifier)params=forward_classifier.init(rng=rng_key,x=x)ret=forward_classifier.apply(params,None,x)From TensorFlowimportivyimportjaximporthaikuashkimporttensorflowastf# Get a pretrained keras modeleff_encoder=tf.keras.applications.efficientnet_v2.EfficientNetV2B0(include_top=False,weights="imagenet",input_shape=(224,224,3))# Transpile it into a hk.Module with the corresponding parametersnoise=tf.random.normal(shape=(1,224,224,3))hk_eff_encoder=ivy.transpile(eff_encoder,to="jax",args=(noise,))# Build a classifier using the transpiled encoderclassClassifier(hk.Module):def__init__(self,num_classes=1000):super().__init__()self.encoder=hk_eff_encoder()self.fc=hk.Linear(output_size=num_classes,with_bias=True)def__call__(self,x):x=self.encoder(x)x=self.fc(x)returnxdef_forward_classifier(x):module=Classifier()returnmodule(x)# Transform the classifier and use it as a standard hk.Modulerng_key=jax.random.PRNGKey(42)dummy_x=jax.random.uniform(key=rng_key,shape=(1,224,224,3))forward_classifier=hk.transform(_forward_classifier)params=forward_classifier.init(rng=rng_key,x=dummy_x)ret=forward_classifier.apply(params,None,dummy_x)Any libraryFrom PyTorchimportivyimportkorniaimportrequestsimportjax.numpyasjnpfromPILimportImage# transpile kornia from torch to jaxjax_kornia=ivy.transpile(kornia,source="torch",to="jax")# get an imageurl="http://images.cocodataset.org/train2017/000000000034.jpg"raw_img=Image.open(requests.get(url,stream=True).raw)# convert it to the format expected by korniaimg=jnp.transpose(jnp.array(raw_img),(2,0,1))img=jnp.expand_dims(img,0)/255# and use the transpiled version of any function from the library!out=jax_kornia.enhance.sharpness(img,5)From TensorFlowimportivyimportjaximportosos.environ["SM_FRAMEWORK"]="tf.keras"importsegmentation_modelsassm# transpile sm from tensorflow to jaxjax_sm=ivy.transpile(sm,source="tensorflow",to="jax")# get some image-like arrayskey=jax.random.PRNGKey(23)key1,key2=jax.random.split(key)output=jax.random.uniform(key1,(1,3,512,512))target=jax.random.uniform(key2,(1,3,512,512))# and use the transpiled version of any function from the library!out=jax_sm.metrics.iou_score(output,target)From NumPyimportivyimportmadmomimportjax.numpyasjnp# transpile madmon from numpy to jaxjax_madmom=ivy.transpile(madmom,source="numpy",to="jax")# get some arraysfreqs=jnp.arange(20)*10# and use the transpiled version of any function from the library!out=jax_madmom.audio.filters.hz2midi(freqs)Any functionFrom PyTorchimportivyimporttorchimportjax.numpyasjnpdefloss(predictions,targets):returntorch.sqrt(torch.mean((predictions-targets)**2))# transpile any function from torch to jaxjax_loss=ivy.transpile(loss,source="torch",to="jax")# get some arraysp=jnp.array([3.0,2.0,1.0])t=jnp.array([0.0,0.0,0.0])# and use the transpiled version!out=jax_loss(p,t)From TensorFlowimportivyimporttensorflowastfimportjax.numpyasjnpdefloss(predictions,targets):returntf.sqrt(tf.reduce_mean(tf.square(predictions-targets)))# transpile any function from tf to jaxjax_loss=ivy.transpile(loss,source="tensorflow",to="jax")# get some arraysp=jnp.array([3.0,2.0,1.0])t=jnp.array([0.0,0.0,0.0])# and use the transpiled version!out=jax_loss(p,t)From NumPyimportivyimportnumpyasnpimportjaximportjax.numpyasjnpjax.config.update('jax_enable_x64',True)defloss(predictions,targets):returnnp.sqrt(np.mean((predictions-targets)**2))# transpile any function from numpy to jaxjax_loss=ivy.transpile(loss,source="numpy",to="jax")# get some arraysp=jnp.array([3.0,2.0,1.0])t=jnp.array([0.0,0.0,0.0])# and use the transpiled version!out=jax_loss(p,t)I'm using NumPyYou can use Ivy to get NumPy code from:Any libraryFrom PyTorchimportivyimportkorniaimportrequestsimportnumpyasnpfromPILimportImage# transpile kornia from torch to npnp_kornia=ivy.transpile(kornia,source="torch",to="numpy")# get an imageurl="http://images.cocodataset.org/train2017/000000000034.jpg"raw_img=Image.open(requests.get(url,stream=True).raw)# convert it to the format expected by korniaimg=np.transpose(np.array(raw_img),(2,0,1))img=np.expand_dims(img,0)/255# and use the transpiled version of any function from the library!out=np_kornia.enhance.sharpness(img,5)From TensorFlowimportivyimportnumpyasnpimportosos.environ["SM_FRAMEWORK"]="tf.keras"importsegmentation_modelsassm# transpile sm from tensorflow to numpynp_sm=ivy.transpile(sm,source="tensorflow",to="numpy")# get some image-like arraysoutput=np.random.rand(1,3,512,512).astype(dtype=np.float32)target=np.random.rand(1,3,512,512).astype(dtype=np.float32)# and use the transpiled version of any function from the library!out=np_sm.metrics.iou_score(output,target)From Jaximportivyimportraximportnumpyasnp# transpile rax from jax to numpynp_rax=ivy.transpile(rax,source="jax",to="numpy")# get some arraysscores=np.array([2.2,1.3,5.4])labels=np.array([1.0,0.0,0.0])# and use the transpiled version of any function from the library!out=np_rax.poly1_softmax_loss(scores,labels)Any functionFrom PyTorchimportivyimporttorchimportnumpyasnpdefloss(predictions,targets):returntorch.sqrt(torch.mean((predictions-targets)**2))# transpile any function from torch to numpynp_loss=ivy.transpile(loss,source="torch",to="numpy")# get some arraysp=np.array([3.0,2.0,1.0])t=np.array([0.0,0.0,0.0])# and use the transpiled version!out=np_loss(p,t)From TensorFlowimportivyimporttensorflowastfimportnumpyasnpdefloss(predictions,targets):returntf.sqrt(tf.reduce_mean(tf.square(predictions-targets)))# transpile any function from tf to numpynp_loss=ivy.transpile(loss,source="tensorflow",to="numpy")# get some arraysp=np.array([3.0,2.0,1.0])t=np.array([0.0,0.0,0.0])# and use the transpiled version!out=np_loss(p,t)From JAXimportivyimportjax.numpyasjnpimportnumpyasnpdefloss(predictions,targets):returnjnp.sqrt(jnp.mean((predictions-targets)**2))# transpile any function from jax to numpynp_loss=ivy.transpile(loss,source="jax",to="numpy")# get some arraysp=np.array([3.0,2.0,1.0])t=np.array([0.0,0.0,0.0])# and use the transpiled version!out=np_loss(p,t)I'm using IvyOr you can use Ivy as a framework, breaking yourself (and your code)
free from deciding which community to support, allowing anyone to run
your code in their framework of choice!importivy# A simple image classification modelclassIvyNet(ivy.Module):def__init__(self,h_w=(32,32),input_channels=3,output_channels=512,num_classes=2,data_format="NCHW",device="cpu",):self.h_w=h_wself.input_channels=input_channelsself.output_channels=output_channelsself.num_classes=num_classesself.data_format=data_formatself.device=devicesuper().__init__()def_build(self,*args,**kwargs):self.extractor=ivy.Sequential(ivy.Conv2D(self.input_channels,6,[5,5],1,"SAME",data_format=self.data_format),ivy.GELU(),ivy.Conv2D(6,16,[5,5],1,"SAME",data_format=self.data_format),ivy.GELU(),ivy.Conv2D(16,self.output_channels,[5,5],1,"SAME",data_format=self.data_format),ivy.GELU(),)self.classifier=ivy.Sequential(# Since the padding is "SAME", this would be image_height x image_width x output_channelsivy.Linear(self.h_w[0]*self.h_w[1]*self.output_channels,512),ivy.GELU(),ivy.Linear(512,self.num_classes),)def_forward(self,x):x=self.extractor(x)# flatten all dims except batch dimx=ivy.flatten(x,start_dim=1,end_dim=-1)logits=self.classifier(x)probs=ivy.softmax(logits)returnlogits,probsAfter building your model in Ivy, you can set your favourite framework
as the backend to use its operations under the hood!ivy.set_backend("torch")model=IvyNet()x=torch.randn(1,3,32,32)logits,probs=model(x)ivy.set_backend("tensorflow")model=IvyNet()x=tf.random.uniform(shape=(1,3,32,32))logits,probs=model(x)ivy.set_backend("jax")model=IvyNet()x=jax.random.uniform(key,shape=(1,3,32,32))logits,probs=model(x)ivy.set_backend("numpy")model=IvyNet()x=np.random.uniform(size=(1,3,32,32))logits,probs=model(x)Last but not least, we can also build the training pipeline in pure ivy
⬇️Let's define some helper functions first# helper function for loading the dataset in batchesdefgenerate_batches(images,classes,dataset_size,batch_size=32):targets={k:vforv,kinenumerate(np.unique(classes))}y_train=[targets[classes[i]]foriinrange(len(classes))]ifbatch_size>dataset_size:raiseivy.utils.exceptions.IvyError("Use a smaller batch size")foridxinrange(0,dataset_size,batch_size):yieldivy.stack(images[idx:min(idx+batch_size,dataset_size)]),ivy.array(y_train[idx:min(idx+batch_size,dataset_size)])# helper function to get the number of current predictionsdefnum_correct(preds,labels):return(preds.argmax()==labels).sum().to_numpy().item()# define a loss functiondefloss_fn(params):v,model,x,y=paramsy_pred,probs=model(x)returnivy.cross_entropy(y,probs),probsAnd train this model!# train the model on gpu if it's availabledevice="cuda:0"ifivy.gpu_is_available()else"cpu"# training hyperparamsoptimizer=ivy.Adam(1e-4)batch_size=64num_epochs=20num_classes=10model=IvyNet(h_w=(28,28),input_channels=1,output_channels=120,num_classes=num_classes,device=device,)model_name=type(model).__name__.lower()# training loopdeftrain(images,classes,epochs,model,device,num_classes=10,batch_size=32):# training metricsepoch_loss=0.0running_loss=0.0fields=["epoch","epoch_loss","training_accuracy"]metrics=[]dataset_size=len(images)forepochinrange(epochs):train_loss,train_correct=0,0train_loop=tqdm(generate_batches(images,classes,len(images),batch_size=batch_size),total=dataset_size//batch_size,position=0,leave=True,)forxbatch,ybatchintrain_loop:ifdevice!="cpu":xbatch,ybatch=xbatch.to_device("gpu:0"),ybatch.to_device("gpu:0")# Since the cross entropy function expects the target classes to be in one-hot encoded formatybatch_encoded=ivy.one_hot(ybatch,num_classes)# update model paramsloss_probs,grads=ivy.execute_with_gradients(loss_fn,(model.v,model,xbatch,ybatch_encoded),)model.v=optimizer.step(model.v,grads["0"])batch_loss=ivy.to_numpy(loss_probs[0]).mean().item()# batch mean lossepoch_loss+=batch_loss*xbatch.shape[0]train_correct+=num_correct(loss_probs[1],ybatch)train_loop.set_description(f"Epoch [{epoch+1:2d}/{epochs}]")train_loop.set_postfix(running_loss=batch_loss,accuracy_percentage=(train_correct/dataset_size)*100,)epoch_loss=epoch_loss/dataset_sizetraining_accuracy=train_correct/dataset_sizemetrics.append([epoch,epoch_loss,training_accuracy])train_loop.write(f"\nAverage training loss:{epoch_loss:.6f}, Train Correct:{train_correct}",end="\n",)# write metrics for plottingwithopen(f"/{model_name}_train_summary.csv","w")asf:f=csv.writer(f)f.writerow(fields)f.writerows(metrics)# assuming the dataset(images and classes) are already prepared in a foldertrain(images,classes,num_epochs,model,device,num_classes=num_classes,batch_size=batch_size)Diving deeperAlthough theDocsare the best place to learn more, in the next section we will take a look at how Ivy works both as a transpiler and a framework in a bit more detail to get an idea of why and where to use it.Ivy as a transpilerIvy's transpiler allows you to use code from any other framework (or
from any other version of the same framework!) in your own code, by just
adding one line of code. Under the hood, Ivy traces a computational
graph and leverages the frontends and backends to link one framework to
another.This way, Ivy makes all ML-related projects available for you,
independently of the framework you want to use to research, develop, or
deploy systems. Feel free to head over to the docs for the full API
reference, but the functions you'd most likely want to use are:# Traces an efficient fully-functional graph from a function, removing all wrapping and redundant codeivy.trace_graph()# Converts framework-specific code to a different frameworkivy.transpile()# Converts framework-specific code to Ivyivy.unify()These functions can be used eagerly or lazily. If you pass the necessary
arguments for function tracing, the graph tracing/transpilation step will
happen instantly (eagerly). Otherwise, the graph tracing/transpilation
will happen only when the returned function is first invoked.importivyimportjaxivy.set_backend("jax")# Simple JAX function to transpiledeftest_fn(x):returnjax.numpy.sum(x)x1=ivy.array([1.,2.])# Arguments are available -> transpilation happens eagerlyeager_graph=ivy.transpile(test_fn,source="jax",to="torch",args=(x1,))# eager_graph is now torch code and runs efficientlyret=eager_graph(x1)# Arguments are not available -> transpilation happens lazilylazy_graph=ivy.transpile(test_fn,source="jax",to="torch")# The transpiled graph is initialized, transpilation will happen hereret=lazy_graph(x1)# lazy_graph is now torch code and runs efficientlyret=lazy_graph(x1)If you want to learn more, you can find more information in theIvy as
a transpiler section of the
docs!When should I use Ivy as a transpiler?If you want to use building blocks published in other frameworks (neural
networks, layers, array computing libraries, training pipelines...),
you want to integrate code developed in various frameworks, or maybe
straight up move code from one framework to another, the transpiler is
definitely the tool 🔧 for the job! As the output of transpilation is
native code in the target framework, you can use the converted code just
as if it was code originally developed in that framework, applying
framework-specific optimizations or tools, instantly exposing your
project to all of the unique perks of a different framework.Ivy as a frameworkThe Ivy framework is built on top of various essential components,
mainly theBackend
Handler,
which manages what framework is being used behind the scenes and theBackend Functional
APIs,
which provide framework-specific implementations of the Ivy functions.
Likewise, classes such asivy.Containerorivy.Arrayare also
available, facilitating the use of structured data and array-like
objects (learn more about themhere!).All of the functionalities in Ivy are exposed through theIvy functional APIand theIvy stateful API. All functions in theFunctional
APIareFramework Agnostic Functions, which means that we can use them
like this:importivyimportjax.numpyasjnpimporttensorflowastfimportnumpyasnpimporttorchdefmse_loss(y,target):returnivy.mean((y-target)**2)jax_mse=mse_loss(jnp.ones((5,)),jnp.ones((5,)))tf_mse=mse_loss(tf.ones((5,)),tf.ones((5,)))np_mse=mse_loss(np.ones((5,)),np.ones((5,)))torch_mse=mse_loss(torch.ones((5,)),torch.ones((5,)))In the example above we show how Ivy's functions are compatible with
tensors from different frameworks. This is the same for ALL Ivy
functions. They can accept tensors from any framework and return the
correct result.TheIvy Stateful
API,
on the other hand, allows you to define trainable modules and layers,
which you can use alone or as a part of any other framework code!importivyclassRegressor(ivy.Module):def__init__(self,input_dim,output_dim):self.input_dim=input_dimself.output_dim=output_dimsuper().__init__()def_build(self,*args,**kwargs):self.linear0=ivy.Linear(self.input_dim,128)self.linear1=ivy.Linear(128,self.output_dim)def_forward(self,x):x=self.linear0(x)x=ivy.functional.relu(x)x=self.linear1(x)returnxIf we put it all together, we'll have something like this. This example
uses PyTorch as the backend, but this can easily be changed to your
favorite frameworks, such as TensorFlow, or JAX.importivyclassRegressor(ivy.Module):def__init__(self,input_dim,output_dim):self.input_dim=input_dimself.output_dim=output_dimsuper().__init__()def_build(self,*args,**kwargs):self.linear0=ivy.Linear(self.input_dim,128)self.linear1=ivy.Linear(128,self.output_dim)def_forward(self,x):x=self.linear0(x)x=ivy.functional.relu(x)x=self.linear1(x)returnxivy.set_backend('torch')# set backend to PyTorch (or any other backend!)model=Regressor(input_dim=1,output_dim=1)optimizer=ivy.Adam(0.3)n_training_examples=2000noise=ivy.random.random_normal(shape=(n_training_examples,1),mean=0,std=0.1)x=ivy.linspace(-6,3,n_training_examples).reshape((n_training_examples,1))y=0.2*x**2+0.5*x+0.1+noisedefloss_fn(v,x,target):pred=model(x,v=v)returnivy.mean((pred-target)**2)forepochinrange(40):# forward passpred=model(x)# compute loss and gradientsloss,grads=ivy.execute_with_gradients(lambdaparams:loss_fn(*params),(model.v,x,y))# update parametersmodel.v=optimizer.step(model.v,grads)# print current lossprint(f'Epoch:{epoch+1:2d}--- Loss:{ivy.to_numpy(loss).item():.5f}')print('Finished training!')The model's output can be visualized as follows:As always, you can find more information aboutIvy as a framework in
the
docs!When should I use Ivy as a framework?As Ivy supports multiple backends, writing code in Ivy breaks you free
from framework limitations. If you want to publish highly flexible code
for everyone to use, independently of the framework they are using, or
you plan to develop ML-related tools and want them to be interoperable
with not only the already existing frameworks, but also with future
frameworks, then Ivy is for you!ContributingWe believe that everyone can contribute and make a difference. Whether
it's writing code 💻, fixing bugs 🐛, or simply sharing feedback 💬,
your contributions are definitely welcome and appreciated 🙌Check out all of our open tasks, and find out more info in ourContributing
guidein the
docs!Join our amazing community as a code contributor, and help accelerate
our journey to unify all ML frameworks!CommunityIn order to achieve the ambitious goal of unifying AI, we definitely need
as many hands as possible on it! Whether you are a seasoned developer or
just starting out, you'll find a place here! Join the Ivy community on
ourDiscord👾 server, which is the
perfect place to ask questions, share ideas, and get help from both
fellow developers and the Ivy Team directly!Also! Feel free to follow us onTwitter🐦 as well, we use it to
share updates, sneak peeks, and all sorts of relevant news, certainly a
great way to stay in the loop 😄Can't wait to see you there!CitationIf you use Ivy for your work, please don't forget to give proper credit
by including the accompanyingpaper📄 in your references. It's a small way to show appreciation and help
to continue to support this and other open source projects 🙌@article{lenton2021ivy,
  title={Ivy: Templated deep learning for inter-framework portability},
  author={Lenton, Daniel and Pardo, Fabio and Falck, Fabian and James, Stephen and Clark, Ronald},
  journal={arXiv preprint arXiv:2102.02886},
  year={2021}
}