

# Amazon Neptune ML for machine learning on graphs
<a name="machine-learning"></a>

There is often valuable information in large connected datasets that can be hard to extract using queries based on human intuition alone. Machine learning (ML) techniques can help find hidden correlations in graphs with billions of relationships. These correlations can be helpful for recommending products, predicting credit worthiness, identifying fraud, and many other things.

The Neptune ML feature makes it possible to build and train useful machine learning models on large graphs in hours instead of weeks. To accomplish this, Neptune ML uses graph neural network (GNN) technology powered by [Amazon SageMaker AI](https://aws.amazon.com/sagemaker/) and the [Deep Graph Library (DGL)](https://www.dgl.ai/) (which is [open-source](https://github.com/dmlc/dgl/)). Graph neural networks are an emerging field in artificial intelligence (see, for example, [A Comprehensive Survey on Graph Neural Networks](https://arxiv.org/abs/1901.00596)). For a hands-on tutorial about using GNNs with DGL, see [Learning graph neural networks with Deep Graph Library](https://www.amazon.science/videos-webinars/learning-graph-neural-networks-with-deep-graph-library).

**Note**  
Graph vertices are identified in Neptune ML models as "nodes". For example, vertex classification uses a node-classification machine learning model, and vertex regression uses a node-regression model.

## What Neptune ML can do
<a name="machine-learning-capabilities"></a>

Neptune supports both transductive inference, which returns predictions that were pre-computed at the time of training, based on your graph data at that time, and inductive inference, which returns applies data processing and model evaluation in real time, based on current data. See [The difference between inductive and transductive inference](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference).

Neptune ML can train machine learning models to support five different categories of inference:

**Types of inference task currently supported by Neptune ML**
+ **Node classification**   –   predicting the categorical feature of a vertex property.

  For example, given the movie *The Shawshank Redemption*, Neptune ML can predict its `genre` property as `story` from a candidate set of `[story, crime, action, fantasy, drama, family, ...]`.

  There are two types of node-classification tasks:
  + **Single-class classification**: In this kind of task, each node has only one target feature. For example, the property, `Place_of_birth` of `Alan Turing` has the value `UK`.
  + **Multi-class classification**: In this kind of task, each node can have more than one target feature. For example, the property `genre` of the film *The Godfather* has the values `crime` and `story`.
+ **Node regression**   –   predicting a numerical property of a vertex.

  For example, given the movie *Avengers: Endgame*, Neptune ML can predict that its property `popularity` has a value of `5.0`.
+ **Edge classification**   –   predicting the categorical feature of an edge property.

  There are two types of edge-classification tasks:
  + **Single-class classification**: In this kind of task, each edge has only one target feature. For example, a ratings edge between a user and a movie might have the property, `liked`, with a value of either "Yes" or "No".
  + **Multi-class classification**: In this kind of task, each edge can have more than one target feature. For example, a ratings between a user and movie might have multiple values for the property tag such as "Funny", "Heartwarming", "Chilling", and so on.
+ **Edge regression**   –   predicting a numerical property of an edge.

  For example, a rating edge between a user and a movie might have the numerical property, `score`, for which Neptune ML could predict a value given a user and a movie.
+ **Link prediction**   –   predicting the most likely destination nodes for a particular source node and outgoing edge, or the most likely source nodes for a given destination node and incoming edge.

  For example, with a drug-disease knowledge graph, given `Aspirin` as the source node, and `treats` as the outgoing edge, Neptune ML can predict the most relevant destination nodes as `heart disease`, `fever`, and so on.

  Or, with the Wikimedia knowledge graph, given `President-of` as the edge or relation and `United-States` as the destination node, Neptune ML can predict the most relevant heads as `George Washington`, `Abraham Lincoln`, `Franklin D. Roosevelt`, and so on.

**Note**  
Node classification and Edge classification only support string values. That means that numerical property values such as `0` or `1` are not supported, although the string equivalents `"0"` and `"1"` are. Similarly, the Boolean property values `true` and `false` don't work, but `"true"` and `"false"` do.

With Neptune ML, you can use machine learning models that fall in two general categories:

**Types of machine learning model currently supported by Neptune ML**
+ **Graph Neural Network (GNN) models**   –   These include [Relational Graph Convolutional Networks (R-GCNs)](https://arxiv.org/abs/1703.06103). GNN models work for all three types of task above.
+ **Knowledge-Graph Embedding (KGE) models**   –   These include `TransE`, `DistMult`, and `RotatE` models. They only work for link prediction.

**User defined models**   –   Neptune ML also lets you provide your own custom model implementation for all the types of tasks listed above. You can use the [Neptune ML toolkit](https://github.com/awslabs/neptuneml-toolkit) to develop and test your python-based custom model implementation before using the Neptune ML training API with your model. See [Custom models in Neptune ML](machine-learning-custom-models.md) for details about how to structure and organize your implementation so that it's compatible with Neptune ML's training infrastructure.

# Setting up Neptune ML
<a name="machine-learning-setup"></a>

The easiest way to get started with Neptune ML is to [use the CloudFormation quick-start template](machine-learning-quick-start.md). This template installs all necessary components, including a new Neptune DB cluster, all the necessary IAM roles, and a new Neptune graph-notebook to make working with Neptune ML easier.

You can also install Neptune ML manually, as explained in [Setting up Neptune ML without using the quick-start CloudFormation template](machine-learning-manual-setup.md).

# Using the Neptune ML AWS CloudFormation template to get started quickly in a new DB cluster
<a name="machine-learning-quick-start"></a>

The easiest way to get started with Neptune ML is to use the CloudFormation quick-start template. This template installs all necessary components, including a new Neptune DB cluster, all the necessary IAM roles, and a new Neptune graph-notebook to make working with Neptune ML easier.

**To create the Neptune ML quick-start stack**

1. To launch the CloudFormation stack on the CloudFormation console, choose one of the **Launch Stack** buttons in the following table:    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/neptune/latest/userguide/machine-learning-quick-start.html)

1.  On the **Select Template** page, choose **Next**.

1. On the **Specify Details** page, choose **Next**.

1. On the **Options** page, choose **Next**.

1. On the **Review** page, there are two check boxes that you need to check:
   + The first one acknowledges that AWS CloudFormation might create IAM resources with custom names.
   + The second acknowledges that AWS CloudFormation might require the `CAPABILITY_AUTO_EXPAND` capability for the new stack. `CAPABILITY_AUTO_EXPAND` explicitly allows CloudFormation to expand macros automatically when creating the stack, without prior review.

     Customers often create a change set from a processed template so that the changes made by macros can be reviewed before actually creating the stack. For more information, see the CloudFormation [CreateStack](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html) API.

   Then choose **Create**.

The quick-start template creates and sets up the following:
+ A Neptune DB cluster.
+ The necessary IAM roles (and attaches them).
+ The necessary Amazon EC2 security group.
+ The necessary SageMaker AI VPC endpoints.
+ A DB cluster parameter group for Neptune ML.
+ The necessary parameters in that parameter group.
+ A SageMaker AI notebook with pre-populated notebook samples for Neptune ML. Note that not all instance sizes are available in every region, so you need to be sure that the notebook instance size selected is one that your region supports.
+ The Neptune-Export service.

When the quick-start stack is ready, go to the SageMaker AI notebook that the template created and check out the pre-populated examples. They will help you download sample datasets to use for experimenting with Neptune ML capabilities.

They can also save you a lot of time when you are using Neptune ML. For example, see the [%neptune\$1ml](notebooks-magics.md#notebooks-line-magics-neptune_ml) line magic, and the [%%neptune\$1ml](notebooks-magics.md#notebooks-cell-magics-neptune_ml) cell magic that these notebooks support.

You can also use the following AWS CLI command to run the quick-start CloudFormation template:

```
aws cloudformation create-stack \
  --stack-name neptune-ml-fullstack-$(date '+%Y-%m-%d-%H-%M') \
  --template-url https://aws-neptune-customer-samples.s3.amazonaws.com/v2/cloudformation-templates/neptune-ml-nested-stack.json \
  --parameters ParameterKey=EnableIAMAuthOnExportAPI,ParameterValue=(true if you have IAM auth enabled, or false otherwise) \
               ParameterKey=Env,ParameterValue=test$(date '+%H%M')\
  --capabilities CAPABILITY_IAM \
  --region (the AWS region, like us-east-1) \
  --disable-rollback \
  --profile (optionally, a named CLI profile of yours)
```

# Setting up Neptune ML without using the quick-start CloudFormation template
<a name="machine-learning-manual-setup"></a>

 This guide provides step-by-step instructions for setting up Amazon Neptune ML without using the AWS CloudFormation quick-start template. It assumes you already have a working Neptune DB cluster and covers the necessary setup, including installing the Neptune-Export service, creating custom IAM roles, and configuring your DB cluster to enable Neptune ML. The guide also explains how to create two SageMaker AI endpoints in your Neptune VPC to give the Neptune engine access to the necessary SageMaker AI management APIs. By following these instructions, you can set up Neptune ML on your existing Neptune infrastructure without relying on the CloudFormation template. 

## Start with a working Neptune DB cluster
<a name="ml-manual-setup-prereq"></a>

If you don't use the CloudFormation quick-start template to set up Neptune ML, you will need an existing Neptune DB cluster to work with. If you want, you can use one you already have, or clone one that you are already using, or you can create a new one (see [Create Neptune cluster](get-started-create-cluster.md)).

## Install the Neptune-Export service
<a name="ml-manual-setup-export-svc"></a>

If you haven't already done so, install the Neptune-Export service, as explained in [Using the Neptune-Export service to export Neptune data](export-service.md).

Add an inbound rule to the `NeptuneExportSecurityGroup` security group that the install creates, with the following settings:
+ *Type*: `Custom TCP`
+ *Protocol*: `TCP`
+ *Port range*: `80 - 443`
+ *Source*: *(Neptune DB cluster security group ID)*

## Create a custom NeptuneLoadFromS3 IAM role
<a name="ml-manual-setup-s3-role"></a>

If you have not already done so, create a custom `NeptuneLoadFromS3` IAM role, as explained in [Creating an IAM role to access Amazon S3](bulk-load-tutorial-IAM-CreateRole.md).

## Create a custom NeptuneSageMakerIAMRole role
<a name="ml-manual-setup-sm-role"></a>

Use the [IAM console](https://console.aws.amazon.com/iam/) to create a custom `NeptuneSageMakerIAMRole`, using the following policy:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Action": [
        "ec2:CreateNetworkInterface",
        "ec2:CreateNetworkInterfacePermission",
        "ec2:CreateVpcEndpoint",
        "ec2:DeleteNetworkInterface",
        "ec2:DeleteNetworkInterfacePermission",
        "ec2:DescribeDhcpOptions",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DescribeRouteTables",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSubnets",
        "ec2:DescribeVpcEndpoints",
        "ec2:DescribeVpcs"
      ],
      "Resource": "*",
      "Effect": "Allow"
    },
    {
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability"
      ],
      "Resource": "*",
      "Effect": "Allow"
    },
    {
      "Action": [
        "iam:PassRole"
      ],
      "Resource": [
        "arn:aws:iam::*:role/*"
      ],
      "Condition": {
        "StringEquals": {
          "iam:PassedToService": [
            "sagemaker.amazonaws.com"
          ]
        }
      },
      "Effect": "Allow"
    },
    {
      "Action": [
        "kms:CreateGrant",
        "kms:Decrypt",
        "kms:GenerateDataKey*"
      ],
      "Resource": "arn:aws:kms:*:*:key/*",
      "Effect": "Allow"
    },
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents"
      ],
      "Resource": [
        "arn:aws:logs:*:*:log-group:/aws/sagemaker/*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "sagemaker:AddTags",
        "sagemaker:CreateEndpoint",
        "sagemaker:CreateEndpointConfig",
        "sagemaker:CreateHyperParameterTuningJob",
        "sagemaker:CreateModel",
        "sagemaker:CreateProcessingJob",
        "sagemaker:CreateTrainingJob",
        "sagemaker:CreateTransformJob",
        "sagemaker:DeleteEndpoint",
        "sagemaker:DeleteEndpointConfig",
        "sagemaker:DeleteModel",
        "sagemaker:DescribeEndpoint",
        "sagemaker:DescribeEndpointConfig",
        "sagemaker:DescribeHyperParameterTuningJob",
        "sagemaker:DescribeModel",
        "sagemaker:DescribeProcessingJob",
        "sagemaker:DescribeTrainingJob",
        "sagemaker:DescribeTransformJob",
        "sagemaker:InvokeEndpoint",
        "sagemaker:ListTags",
        "sagemaker:ListTrainingJobsForHyperParameterTuningJob",
        "sagemaker:StopHyperParameterTuningJob",
        "sagemaker:StopProcessingJob",
        "sagemaker:StopTrainingJob",
        "sagemaker:StopTransformJob",
        "sagemaker:UpdateEndpoint",
        "sagemaker:UpdateEndpointWeightsAndCapacities"
      ],
      "Resource": [
        "arn:aws:sagemaker:*:*:*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "sagemaker:ListEndpointConfigs",
        "sagemaker:ListEndpoints",
        "sagemaker:ListHyperParameterTuningJobs",
        "sagemaker:ListModels",
        "sagemaker:ListProcessingJobs",
        "sagemaker:ListTrainingJobs",
        "sagemaker:ListTransformJobs"
      ],
      "Resource": "*",
      "Effect": "Allow"
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:AbortMultipartUpload",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ],
      "Effect": "Allow"
    }
  ]
}
```

------

While creating this role, edit the trust relationship so that it reads as follows:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "ec2.amazonaws.com",
          "rds.amazonaws.com",
          "sagemaker.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

Finally, copy the ARN assigned to this new `NeptuneSageMakerIAMRole` role.

**Important**  
Be sure that the Amazon S3 permissions in the `NeptuneSageMakerIAMRole` match those above.
The universal ARN, `arn:aws:s3:::*` is used for the Amazon S3 resource in the policy above. If for some reason the universal ARN cannot be used, then `arn:aws:s3:::graphlytics*` and the ARN for any other customer Amazon S3 resource that NeptuneML commands will use must be added to the resource section.

## Configure your DB cluster to enable Neptune ML
<a name="ml-manual-setup-cluster-config"></a>

**To set up your DB cluster for Neptune ML**

1. In the [Neptune console](https://console.aws.amazon.com/neptune), navigate to **Parameter Groups** and then to the DB cluster parameter group associated with the DB cluster you will be using. Set the `neptune_ml_iam_role` parameter to the ARN assigned to the `NeptuneSageMakerIAMRole` role that you just created.

1. Navigate to Databases, then select the DB cluster you will be using for Neptune ML. Select **Actions** then **Manage IAM roles**.

1. On the **Manage IAM roles** page, select **Add role** and add the `NeptuneSageMakerIAMRole`. Then add the `NeptuneLoadFromS3` role. 

1. Reboot the writer instance of your DB cluster. 

## Create two SageMaker AI endpoints in your Neptune VPC
<a name="ml-manual-setup-endpoints"></a>

Finally, to give the Neptune engine access the necessary SageMaker AI management APIs, you need to create two SageMaker AI endpoints in your Neptune VPC, as explained in [Create two endpoints for SageMaker AI in your Neptune VPC](machine-learning-cluster-setup.md#machine-learning-sm-endpoints).

# Manually configuring a Neptune notebook for Neptune ML
<a name="ml-manual-setup-notebooks"></a>

Neptune SageMaker AI notebooks come pre-loaded with a variety of sample notebooks for Neptune ML. You can preview these samples in the [open source graph-notebook GitHub repository](https://github.com/aws/graph-notebook/tree/main/src/graph_notebook/notebooks/04-Machine-Learning).

You can use one of the existing Neptune notebooks, or if you want you can create one of your own, following the instructions in [Using the Neptune workbench to host Neptune notebooks](graph-notebooks.md#graph-notebooks-workbench).

You can also configure a default Neptune notebook for use with Neptune ML by following these steps:

**Modify a notebook for Neptune ML**

1. Open the Amazon SageMaker AI console at [https://console.aws.amazon.com/sagemaker/](https://console.aws.amazon.com/sagemaker/).

1. On the navigation pane on the left, choose **Notebook**, then **Notebook Instances**. Look for the name of the Neptune notebook that you would like to use for Neptune ML and select it to go to its details page.

1. If the notebook instance is running, select the **Stop** button at the top right of the notebook details page.

1. In **Notebook instance settings**, under **Lifecycle Configuration**, select the link to open the page for the notebook's lifecycle.

1. Select **Edit** at the top right, then **Continue**.

1. In the **Start notebook** tab, modify the script to include additional export commands and to fill in the fields for your Neptune ML IAM role and Export service URI, something like this depending on your shell:

   ```
   echo "export NEPTUNE_ML_ROLE_ARN=(your Neptune ML IAM role ARN)" >> ~/.bashrc
   echo "export NEPTUNE_EXPORT_API_URI=(your export service URI)" >> ~/.bashrc
   ```

1. Select **Update**.

1. Return to the notebook instance page. Under **Permissions and encryption** there is a field for **IAM role ARN**. Select the link in this field to go to the IAM role that this notebook instance runs with.

1. Create a new inline policy like this:

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Action": [
           "cloudwatch:PutMetricData"
         ],
         "Resource": "arn:aws:cloudwatch:us-east-1:111122223333:*",
         "Sid": "AllowPutMetrics",
         "Effect": "Allow"
       },
       {
         "Action": [
           "logs:CreateLogGroup",
           "logs:CreateLogStream",
           "logs:DescribeLogStreams",
           "logs:PutLogEvents",
           "logs:GetLogEvents"
         ],
         "Resource": "arn:aws:logs:us-east-1:111122223333:*",
         "Sid": "AllowCreateLogs",
         "Effect": "Allow"
       },
       {
         "Action": [
           "s3:Put*",
           "s3:Get*",
           "s3:List*"
         ],
         "Resource": "arn:aws:s3:::*",
         "Sid": "AllowS3Actions",
         "Effect": "Allow"
       },
       {
         "Action": "execute-api:Invoke",
         "Resource": "arn:aws:execute-api:us-east-1:111122223333:*/*",
         "Sid": "AllowExecute",
         "Effect": "Allow"
       },
       {
         "Action": [
           "sagemaker:CreateModel",
           "sagemaker:CreateEndpointConfig",
           "sagemaker:CreateEndpoint",
           "sagemaker:DescribeModel",
           "sagemaker:DescribeEndpointConfig",
           "sagemaker:DescribeEndpoint",
           "sagemaker:DeleteModel",
           "sagemaker:DeleteEndpointConfig",
           "sagemaker:DeleteEndpoint"
         ],
         "Resource": "arn:aws:sagemaker:us-east-1:111122223333:*/*",
         "Sid": "AllowApiActions",
         "Effect": "Allow"
       },
       {
         "Action": [
           "iam:PassRole"
         ],
         "Resource": "arn:aws:iam::111122223333:role/role-name",
         "Sid": "AllowPassRole",
         "Effect": "Allow"
       }
     ]
   }
   ```

------

1. Save this new policy and attach it to the IAM role in Step 8.

1. Select **Start** at the top right of of the SageMaker AI notebook instance details page to start the notebook instance.

# Using the AWS CLI to set up Neptune ML on a DB cluster
<a name="machine-learning-cluster-setup"></a>

In addition to the CloudFormation quick-start template and the AWS Management Console, you can also set up Neptune ML using the AWS CLI.

## Create a DB cluster parameter group for your new Neptune ML cluster
<a name="machine-learning-enabling-create-param-group"></a>

The following AWS CLI commands create a new DB cluster parameter group and set it up to work with Neptune ML:

**To create and configure a DB cluster parameter group for Neptune ML**

1. Create a new DB cluster parameter group:

   ```
   aws neptune create-db-cluster-parameter-group \
     --db-cluster-parameter-group-name (name of the new DB cluster parameter group) \
     --db-parameter-group-family neptune1
     --description "(description of your machine learning project)" \
     --region (AWS region, such as us-east-1)
   ```

1. Create a `neptune_ml_iam_role` DB cluster parameter set to the ARN of the `SageMakerExcecutionIAMRole` for your DB cluster to use while calling SageMaker AI for creating jobs and getting prediction from hosted ML models:

   ```
   aws neptune modify-db-cluster-parameter-group \
     --db-cluster-parameter-group-name (name of the new DB cluster parameter group) \
     --parameters "ParameterName=neptune_ml_iam_role, \
                   ParameterValue=ARN of the SageMakerExcecutionIAMRole, \
                   Description=NeptuneMLRole, \
                   ApplyMethod=pending-reboot" \
     --region (AWS region, such as us-east-1)
   ```

   Setting this parameter allows Neptune to access SageMaker AI without you having to pass in the role with every call.

   For information about how to create the `SageMakerExcecutionIAMRole`, see [Create a custom NeptuneSageMakerIAMRole role](machine-learning-manual-setup.md#ml-manual-setup-sm-role).

1. Finally, use `describe-db-cluster-parameters` to check that all the parameters in the new DB cluster parameter group are set as you want them to be:

   ```
   aws neptune describe-db-cluster-parameters \
     --db-cluster-parameter-group-name (name of the new DB cluster parameter group) \
     --region (AWS region, such as us-east-1)
   ```

## Attach the new DB cluster parameter group to the DB cluster you will use with Neptune ML
<a name="machine-learning-enabling-attach-param-group"></a>

Now you can attach the new DB cluster parameter group that you just created to an existing DB cluster by using the following command:

```
aws neptune modify-db-cluster \
  --db-cluster-identifier (the name of your existing DB cluster) \
  --apply-immediately
  --db-cluster-parameter-group-name (name of your new DB cluster parameter group) \
  --region (AWS region, such as us-east-1)
```

To make all the parameters effective, you can then reboot the DB cluster:

```
aws neptune reboot-db-instance
  --db-instance-identifier (name of the primary instance of your DB cluster) \
  --profile (name of your AWS profile to use) \
  --region (AWS region, such as us-east-1)
```

Or, if you're creating a new DB cluster to use with Neptune ML, you can use the following command to create the cluster with the new parameter group attached, and then create a new primary (writer) instance:

```
cluster-name=(the name of the new DB cluster)
aws neptune create-db-cluster
  --db-cluster-identifier ${cluster-name}
  --engine graphdb \
  --engine-version 1.0.4.1 \
  --db-cluster-parameter-group-name (name of your new DB cluster parameter group) \
  --db-subnet-group-name (name of the subnet to use) \
  --region (AWS region, such as us-east-1)

aws neptune create-db-instance
  --db-cluster-identifier ${cluster-name}
  --db-instance-identifier ${cluster-name}-i \
  --db-instance-class (the instance class to use, such as db.r5.xlarge)
  --engine graphdb \
  --region (AWS region, such as us-east-1)
```

## Attach the `NeptuneSageMakerIAMRole` to your DB cluster so that it can access SageMaker AI and Amazon S3 resources
<a name="machine-learning-enabling-attach-neptune-sagemaker-role"></a>

Finally, follow the instructions in [Create a custom NeptuneSageMakerIAMRole role](machine-learning-manual-setup.md#ml-manual-setup-sm-role) to create an IAM role that will allow your DB cluster to communicate with SageMaker AI and Amazon S3. Then, use the following command to attach the `NeptuneSageMakerIAMRole` role you created to your DB cluster:

```
aws neptune add-role-to-db-cluster
  --db-cluster-identifier ${cluster-name}
  --role-arn arn:aws:iam::(the ARN number of the role's ARN):role/NeptuneMLRole \
  --region (AWS region, such as us-east-1)
```

## Create two endpoints for SageMaker AI in your Neptune VPC
<a name="machine-learning-sm-endpoints"></a>

Neptune ML needs two SageMaker AI endpoints in your Neptune DB cluster's VPC:
+ `com.amazonaws.(AWS region, like us-east-1).sagemaker.runtime`
+ `com.amazonaws.(AWS region, like us-east-1).sagemaker.api`

If you haven't used the quick-start CloudFormation template, which creates these automatically for you, you can use the following AWS CLI commands to create them:

This one creates the `sagemaker.runtime` endpoint:

```
aws ec2 create-vpc-endpoint
  --vpc-id (the ID of your Neptune DB cluster's VPC)
  --vpc-endpoint-type Interface
  --service-name com.amazonaws.(AWS region, like us-east-1).sagemaker.runtime
  --subnet-ids (the subnet ID or IDs that you want to use)
  --security-group-ids (the security group for the endpoint network interface, or omit to use the default)
  --private-dns-enabled
```

And this one creates the `sagemaker.api` endpoint:

```
aws ec2 create-vpc-endpoint
  --vpc-id (the ID of your Neptune DB cluster's VPC)
  --vpc-endpoint-type Interface
  --service-name com.amazonaws.(AWS region, like us-east-1).sagemaker.api
  --subnet-ids (the subnet ID or IDs that you want to use)
  --security-group-ids (the security group for the endpoint network interface, or omit to use the default)
  --private-dns-enabled
```

You can also use the [VPC console](https://console.aws.amazon.com/vpc/) to create these endpoints. See [Secure prediction calls in Amazon SageMaker with AWS PrivateLink](https://aws.amazon.com/blogs/machine-learning/secure-prediction-calls-in-amazon-sagemaker-with-aws-privatelink/) and [Securing all Amazon SageMaker API calls with AWS PrivateLink](https://aws.amazon.com/blogs/machine-learning/securing-all-amazon-sagemaker-api-calls-with-aws-privatelink/).

## Create a SageMaker AI inference endpoint parameter in your DB cluster parameter group
<a name="machine-learning-set-inference-endpoint-cluster-parameter"></a>

To avoid having to specify the SageMaker AI inference endpoint of the model that you're using in every query you make to it, create a DB cluster parameter named `neptune_ml_endpoint` in the DB cluster parameter group for Neptune ML. Set the parameter to the `id` of the instance endpoint in question.

You can use the following AWS CLI command to do that:

```
aws neptune modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name neptune-ml-demo \
  --parameters "ParameterName=neptune_ml_endpoint, \
                ParameterValue=(the name of the SageMaker AI inference endpoint you want to query), \
                Description=NeptuneMLEndpoint, \
                ApplyMethod=pending-reboot" \
  --region (AWS region, such as us-east-1)
```

# Overview of how to use the Neptune ML feature
<a name="machine-learning-overview"></a>

 The Neptune ML feature in Amazon Neptune provides a streamlined workflow for leveraging machine learning models within a graph database. The process involves several key steps - exporting data from Neptune into CSV format, preprocessing the data to prepare it for model training, training the machine learning model using Amazon SageMaker AI, creating an inference endpoint to serve predictions, and then querying the model directly from Gremlin queries. The Neptune workbench provides convenient line and cell magic commands to help manage and automate these steps. By integrating machine learning capabilities directly into the graph database, Neptune ML enables users to derive valuable insights and make predictions using the rich relational data stored in the Neptune graph. 

## Starting workflow for using Neptune ML
<a name="machine-learning-overview-starting-workflow"></a>

Using the Neptune ML feature in Amazon Neptune generally involves the following five steps to begin with:

![\[Neptune ML workflow diagram\]](http://docs.aws.amazon.com/neptune/latest/userguide/images/neptune-ML-workflow.png)


1. **Data export and configuration**   –   The data-export step uses the Neptune-Export service or the `neptune-export` command line tool to export data from Neptune into Amazon Simple Storage Service (Amazon S3) in CSV form. A configuration file named `training-data-configuration.json` is automatically generated at the same time, which specifies how the exported data can be loaded into a trainable graph.

1. **Data preprocessing**   –   In this step, the exported dataset is preprocessed using standard techniques to prepare it for model training. Feature normalization can be performed for numeric data, and text features can be encoded using `word2vec`. At the end of this step, a DGL (Deep Graph library) graph is generated from the exported dataset for the model training step to use.

   This step is implemented using a SageMaker AI processing job in your account, and the resulting data is stored in an Amazon S3 location that you have specified.

1. **Model training**   –   The model training step trains the machine learning model that will be used for predictions.

   Model training is done in two stages:
   + The first stage uses a SageMaker AI processing job to generate a model training strategy configuration set that specifies what type of model and model hyperparameter ranges will be used for the model training.
   + The second stage then uses a SageMaker AI model tuning job to try different hyperparameter configurations and select the training job that produced the best-performing model. The tuning job runs a pre-specified number of model training job trials on the processed data. At the end of this stage, the trained model parameters of the best training job are used to generate model artifacts for inference.

1. **Create an inference endpoint in Amazon SageMaker AI**   –   The inference endpoint is a SageMaker AI endpoint instance that is launched with the model artifacts produced by the best training job. Each model is tied to a single endpoint. The endpoint is able to accept incoming requests from the graph database and return the model predictions for inputs in the requests. After you have created the endpoint, it stays active until you delete it.

1. **Query the machine learning model using Gremlin**   –   You can use extensions to the Gremlin query language to query predictions from the inference endpoint.

**Note**  
The [Neptune workbench](graph-notebooks.md#graph-notebooks-workbench) contains a line magic and a cell magic that can save you a lot of time managing these steps, namely:  
[%neptune\$1ml](notebooks-magics.md#notebooks-line-magics-neptune_ml)
[%%neptune\$1ml](notebooks-magics.md#notebooks-cell-magics-neptune_ml)

# Making predictions based on evolving graph data
<a name="machine-learning-overview-evolving-data"></a>

With a continuously changing graph, you may want to create new batch predictions periodically using fresh data. Querying pre-computed predictions (transductive inference) can be significantly faster than generating new predictions on the fly based on the very latest data (inductive inference). Both approaches have their place, depending on how rapidly your data changes and on your performance requirements.

## The difference between inductive and transductive inference
<a name="inductive-vs-transductive-inference"></a>

When performing transductive inference, Neptune looks up and returns predictions that were pre-computed at the time of training.

When performing inductive inference, Neptune constructs the relevant subgraph and fetches its properties. The DGL GNN model then applies data processing and model evaluation in real-time.

Inductive inference can therefore generate predictions involving nodes and edges that were not present at the time of training and that reflect the current state of the graph. This comes, however, at the cost of higher latency.

If your graph is dynamic, you may want to use inductive inference to be sure to take into account the latest data, but if your graph is static, transductive inference is faster and more efficient.

Inductive inference is disabled by default. You can enable it for a query by using the Gremlin [Neptune\$1ml.inductiveInference](machine-learning-gremlin-inference-query-predicates.md#machine-learning-gremlin-inference-neptune-ml-inductiveInference) predicate in the query as follows:

```
.with( "Neptune#ml.inductiveInference")
```

# Incremental transductive workflows
<a name="machine-learning-overview-evolving-data-incremental"></a>

While you update model artifacts simply by re-running the steps one through three (from **Data export and configuration** to **Model transform**), Neptune ML supports simpler ways to update your batch ML predictions using new data. One is to use an [incremental-model workflow](#machine-learning-overview-incremental), and another is to use [model retraining with a warm start](#machine-learning-overview-model-retraining).

## Incremental-model workflow
<a name="machine-learning-overview-incremental"></a>

In this workflow, you update the ML predictions without retraining the ML model.

**Note**  
You can only do this when the graph data has been updated with new nodes and/or edges. It will not currently work when nodes are removed.

1. **Data export and configuration**   –     This step is the same as in the main workflow.

1. **Incremental data preprocessing**   –     This step is similar to the data preprocessing step in the main workflow, but uses the same processing configuration used previously, that corresponds to a specific trained model.

1. **Model transform**   –     Instead of a model training step, this model-transform step takes the trained model from the main workflow and the results of the incremental data preprocessing step, and generates new model artifacts to use for inference. The model-transform step launches a SageMaker AI processing job to perform the computation that generates the updated model artifacts.

1. **Update the Amazon SageMaker AI inference endpoint**   –     Optionally, if you have an existing inference endpoint, this step updates the endpoint with the new model artifacts generated by the model-transform step. Alternatively, you can also create a new inference endpoint with the new model artifacts.

## Model re-training with a warm start
<a name="machine-learning-overview-model-retraining"></a>

Using this workflow, you can train and deploy a new ML model for making predictions using the incremental graph data, but start from an existing model generated using the main workflow:

1. **Data export and configuration**   –     This step is the same as in the main workflow.

1. **Incremental data preprocessing**   –     This step is the same as in the incremental model inference workflow. The new graph data should be processed with the same processing method that was used previously for model training.

1. **Model training with a warm start**   –     Model training is similar to what happens in the main workflow, but you can speed up model hyperparameter search by leveraging the information from the previous model training task.

1. **Update the Amazon SageMaker AI inference endpoint**   –     This step is the same as in the incremental model inference workflow.

# Workflows for custom models in Neptune ML
<a name="machine-learning-overview-custom-model-workflow"></a>

Neptune ML lets you implement, train and deploy custom models of your own for any of the tasks that Neptune ML supports. The workflow for developing and deploying a custom model is essentially the same as for the built-in models, with a few differences, as explained in [Custom model workflow](machine-learning-custom-model-overview.md#machine-learning-custom-model-workflow).

# Instance selection for the Neptune ML stages
<a name="machine-learning-on-graphs-instance-selection"></a>

The different stages of Neptune ML processing use different SageMaker AI instances. Here, we discuss how to choose the right instance type for each stage. You can find information about SageMaker AI instance types and pricing at [Amazon SageMaker Pricing](https://aws.amazon.com/sagemaker/pricing/).

## Selecting an instance for data processing
<a name="machine-learning-on-graphs-processing-instance-size"></a>

The SageMaker AI [data-processing](machine-learning-on-graphs-processing.md) step requires a [processing instance](https://docs.aws.amazon.com/sagemaker/latest/dg/processing-job.html) that has enough memory and disk storage for the input, intermediate, and output data. The specific amount of memory and disk storage needed depends on the characteristics of the Neptune ML graph and its exported features.

By default, Neptune ML chooses the smallest `ml.r5` instance whose memory is ten times larger than the size of the exported graph data on disk.

## Selecting an instance for model training and model transform
<a name="machine-learning-on-graphs-training-transform-instance-size"></a>

Selecting the right instance type for [model training](https://docs.aws.amazon.com/sagemaker/latest/dg/how-it-works-training.html) or [model transform](https://docs.aws.amazon.com/sagemaker/latest/dg/how-it-works-batch.html) depends on the task type, the graph size, and your turn-around requirements. GPU instances provide the best performance. We generally recommend `p3` and `g4dn` serial instances. You can also use `p2` or `p4d` instances.

By default, Neptune ML chooses the smallest GPU instance with more memory than model training and model transform requires. You can find what that selection is in the `train_instance_recommendation.json` file, in the Amazon S3 data processing output location. Here is an example of the contents of a `train_instance_recommendation.json` file:

```
{ 
  "instance":     "(the recommended instance type for model training and transform)",
  "cpu_instance": "(the recommended instance type for base processing instance)", 
  "disk_size":    "(the estimated disk space required)",
  "mem_size":     "(the estimated memory required)"
}
```

## Selecting an instance for an inference endpoint
<a name="machine-learning-on-graphs-inference-endpoint-instance-size"></a>

Selecting the right instance type for an [inference endpoint](machine-learning-on-graphs-inference-endpoint.md) depends on the task type, the graph size and your budget. By default, Neptune ML chooses the smallest `ml.m5d` instance with more memory the inference endpoint requires.

**Note**  
If more than 384 GB of memory is needed, Neptune ML uses an `ml.r5d.24xlarge` instance.

You can see what instance type Neptune ML recommends in the `infer_instance_recommendation.json` file located in the Amazon S3 location you are using for model training. Here is an example of that file's contents:

```
{ 
  "instance" :   "(the recommended instance type for an inference endpoint)",
  "disk_size" :  "(the estimated disk space required)",
  "mem_size" :   "(the estimated memory required)"
}
```

# Using the neptune-export tool or Neptune-Export service to export data from Neptune for Neptune ML
<a name="machine-learning-data-export"></a>

Neptune ML requires that you provide training data for the [Deep Graph Library (DGL)](https://www.dgl.ai/) to create and evaluate models.

You can export data from Neptune using either the [Neptune-Export service](export-service.md), or [`neptune-export` utility](export-utility.md). Both the service and the command line tool publish data to Amazon Simple Storage Service (Amazon S3) in a CSV format, encrypted using Amazon S3 server-side encryption (`SSE-S3`). See [Files exported by Neptune-Export and `neptune-export`](exported-files.md).

In addition, when you configure an export of training data for Neptune ML the export job creates and publishes an encrypted model-training configuration file along with the exported data. By default, this file is named `training-data-configuration.json`.

# Examples of using the Neptune-Export service to export training data for Neptune ML
<a name="machine-learning-export-examples"></a>

This request exports property-graph training data for a node classification task:

------
#### [ curl ]

```
curl \
  (your NeptuneExportApiUri) \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "command": "export-pg",
        "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
        "params": {
          "endpoint": "(your Neptune endpoint DNS name)",
          "profile": "neptune_ml"
        },
        "additionalParams": {
          "neptune_ml": {
            "version": "v2.0",
            "targets": [
              {
                "node": "Movie",
                "property": "genre",
                "type": "classification"
              }
            ]
          }
        }
      }'
```

------
#### [ awscurl ]

```
awscurl (your NeptuneExportApiUri) \
  --region us-east-1 \
  --service execute-api \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "command": "export-pg",
        "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
        "params": {
          "endpoint": "(your Neptune endpoint DNS name)",
          "profile": "neptune_ml"
        },
        "additionalParams": {
          "neptune_ml": {
            "version": "v2.0",
            "targets": [
              {
                "node": "Movie",
                "property": "genre",
                "type": "classification"
              }
            ]
          }
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------

This request exports RDF training data for a node classification task:

------
#### [ curl ]

```
curl \
  (your NeptuneExportApiUri) \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "command": "export-rdf",
        "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
        "params": {
          "endpoint": "(your Neptune endpoint DNS name)",
          "profile": "neptune_ml"
        },
        "additionalParams": {
          "neptune_ml": {
            "version": "v2.0",
            "targets": [
              {
                "node": "http://aws.amazon.com/neptune/csv2rdf/class/Movie",
                "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/genre",
                "type": "classification"
              }
            ]
          }
        }
      }'
```

------
#### [ awscurl ]

```
awscurl (your NeptuneExportApiUri) \
  --region us-east-1 \
  --service execute-api \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "command": "export-rdf",
        "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
        "params": {
          "endpoint": "(your Neptune endpoint DNS name)",
          "profile": "neptune_ml"
        },
        "additionalParams": {
          "neptune_ml": {
            "version": "v2.0",
            "targets": [
              {
                "node": "http://aws.amazon.com/neptune/csv2rdf/class/Movie",
                "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/genre",
                "type": "classification"
              }
            ]
          }
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------

# Fields to set in the params object when exporting training data
<a name="machine-learning-params"></a>

The `params` object in an export request can contain various fields, as described in the [`params` documentation](export-params-fields.md). The following ones are most relevant for exporting machine-learning training data:

****
+ **`endpoint`**   –   Use `endpoint` to specify an endpoint of a Neptune instance in your DB cluster that the export process can query to extract data.
+ **`profile`**   –   The `profile` field in the `params` object must be set to **`neptune-ml`**.

  This causes the export process to format the exported data appropriately for Neptune ML model training, in a CSV format for property-graph data or as N-Triples for RDF data. It also causes a `training-data-configuration.json` file to be created and written to the same Amazon S3 location as the exported training data.
+ **`cloneCluster`**   –   If set to `true`, the export process clones your DB cluster, exports from the clone, and then deletes the clone when it is finished.
+ **`useIamAuth`**   –   If your DB cluster has [IAM authentication](iam-auth-enable.md) enabled, you must include this field set to `true`.

The export process also provides several ways to filter the data you export (see [these examples](export-filtering-examples.md)).

# Using the additionalParams object to tune the export of model-training information
<a name="machine-learning-additionalParams"></a>

The `additionalParams` object contains fields that you can use to specify machine-learning class labels and features for training purposes and guide the creation of a training data configuration file.

The export process cannot automatically infer which node and edge properties should be the machine learning class labels to serve as examples for training purposes. It also cannot automatically infer the best feature encoding for numeric, categorical and text properties, so you need to supply hints using fields in the `additionalParams` object to specify these things, or to override the default encoding.

For property-graph data, the top-level structure of `additionalParams` in an export request might look like this:

```
{
  "command": "export-pg",
  "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
  "params": {
    "endpoint": "(your Neptune endpoint DNS name)",
    "profile": "neptune_ml"
  },
  "additionalParams": {
      "neptune_ml": {
        "version": "v2.0",
        "targets": [ (an array of node and edge class label targets) ],
        "features": [ (an array of node feature hints) ]
    }
  }
}
```

For RDF data, its top-level structure might look like this:

```
{
  "command": "export-rdf",
  "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
  "params": {
    "endpoint": "(your Neptune endpoint DNS name)",
    "profile": "neptune_ml"
  },
  "additionalParams": {
      "neptune_ml": {
        "version": "v2.0",
        "targets": [ (an array of node and edge class label targets) ]
    }
  }
}
```

You can also supply multiple export configurations, using the `jobs` field:

```
{
  "command": "export-pg",
  "outputS3Path": "s3://(your Amazon S3 bucket)/neptune-export",
  "params": {
    "endpoint": "(your Neptune endpoint DNS name)",
    "profile": "neptune_ml"
  },
  "additionalParams" : {
    "neptune_ml" : {
      "version": "v2.0",
      "jobs": [
        {
          "name" : "(training data configuration name)",
          "targets": [ (an array of node and edge class label targets) ],
          "features": [ (an array of node feature hints) ]
        },
        {
          "name" : "(another training data configuration name)",
          "targets": [ (an array of node and edge class label targets) ],
          "features": [ (an array of node feature hints) ]
        }
      ]
    }
  }
}
```

# Top-level elements in the neptune\$1ml field in additionalParams
<a name="machine-learning-neptune_ml-top-level"></a>

## The version element in neptune\$1ml
<a name="machine-learning-neptune_ml-version"></a>

Specifies the version of training data configuration to generate.

(*Optional*), *Type*: string, *Default*: "v2.0".

If you do include `version`, set it to `v2.0`.

## The jobs field in neptune\$1ml
<a name="machine-learning-neptune_ml-jobs"></a>

Contains an array of training-data configuration objects, each of which defines a data processing job, and contains:
+ **`name`**   –   The name of the training data configuration to be created.

   For example, a training data configuration with the name "job-number-1" results in a training data configuration file named `job-number-1.json`.
+ **`targets`**   –   A JSON array of node and edge class label targets that represent the machine-learning class labels for training purposes. See [The targets field in a neptune\$1ml object](machine-learning-neptune_ml-targets.md).
+ **`features`**   –   A JSON array of node property features. See [The features field in neptune\$1ml](machine-learning-neptune_ml-features.md).

# The targets field in a neptune\$1ml object
<a name="machine-learning-neptune_ml-targets"></a>

The `targets` field in a JSON training data export configuration contains an array of target objects that specify a training task and and the machine-learning class labels for training this task. The contents of the target objects varies depending on whether you are training on property-graph data or RDF data.

For property-graph node classification and regression tasks, target objects in the array can look like this:

```
{
  "node": "(node property-graph label)",
  "property": "(property name)",
  "type" : "(used to specify classification or regression)",
  "split_rate": [0.8,0.2,0.0],
  "separator": ","
}
```

For property-graph edge classification, regression or link prediction tasks, they can look like this:

```
{
  "edge": "(edge property-graph label)",
  "property": "(property name)",
  "type" : "(used to specify classification, regression or link_prediction)",
  "split_rate": [0.8,0.2,0.0],
  "separator": ","
}
```

For RDF classification and regression tasks, target objects in the array can look like this:

```
{
  "node": "(node type of an RDF node)",
  "predicate": "(predicate IRI)",
  "type" : "(used to specify classification or regression)",
  "split_rate": [0.8,0.2,0.0]
}
```

For RDF link prediction tasks, target objects in the array can look like this::

```
{
  "subject": "(source node type of an edge)",
  "predicate": "(relation type of an edge)",
  "object": "(destination node type of an edge)",
  "type" : "link_prediction",
  "split_rate": [0.8,0.2,0.0]
}
```

Target objects can contain the following fields:

**Contents**
+ [Property-graph target fields](#machine-learning-property-graph-neptune_ml-targets)
  + [node](#machine-learning-property-graph-neptune_ml-targets-node)
  + [edge](#machine-learning-property-graph-neptune_ml-targets-edge)
  + [property](#machine-learning-property-graph-neptune_ml-targets-property)
  + [type](#machine-learning-property-graph-neptune_ml-targets-type)
  + [split\$1rate](#machine-learning-property-graph-neptune_ml-targets-split_rate)
  + [separator](#machine-learning-property-graph-neptune_ml-targets-separator)
+ [RDF target fields](#machine-learning-RDF-neptune_ml-targets)
  + [node](#machine-learning-RDF-neptune_ml-targets-node)
  + [subject](#machine-learning-RDF-neptune_ml-targets-subject)
  + [predicate](#machine-learning-RDF-neptune_ml-targets-predicate)
  + [object](#machine-learning-RDF-neptune_ml-targets-object)
  + [type](#machine-learning-RDF-neptune_ml-targets-type)
  + [split\$1rate](#machine-learning-RDF-neptune_ml-targets-split_rate)

## Fields in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets"></a>

### The node (vertex) field in a target object
<a name="machine-learning-property-graph-neptune_ml-targets-node"></a>

The property-graph label of a target node (vertex). A target object must contain a `node` element or an `edge` element, but not both.

A `node` can take either a single value, like this:

```
  "node": "Movie"
```

Or, in the case of a multi-label vertex, it can take an array of values, like this:

```
  "node": ["Content", "Movie"]
```

### The edge field in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets-edge"></a>

Specifies a target edge by its start node label(s), its own label, and its end-node label(s). A target object must contain an `edge` element or a `node` element, but not both.

The value of an `edge` field is a JSON array of three strings that represent the start-node's property-graph label(s), the property-graph label of the edge itself, and the end-node's property-graph label(s), like this:

```
  "edge": ["Person_A", "knows", "Person_B"]
```

If the start node and/or end node has multiple labels, enclose them in an array, like this:

```
  "edge": [ ["Admin", Person_A"], "knows", ["Admin", "Person_B"] ]
```

### The property field in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets-property"></a>

Specifies a property of the target vertex or edge, like this:

```
  "property" : "rating"
```

This field is required, except when the target task is link prediction.

### The type field in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets-type"></a>

Indicates the type of target task to be performed on the `node` or `edge`, like this:

```
  "type" : "regression"
```

The supported task types for nodes are:
+ `classification`
+ `regression`

The supported task types for edges are:
+ `classification`
+ `regression`
+ `link_prediction`

This field is required.

### The split\$1rate field in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets-split_rate"></a>

(*Optional*) An estimate of the proportions of nodes or edges that the training, validation, and test stages will use, respectively. These proportions are represented by a JSON array of three numbers between zero and one that add up to one:

```
"split_rate": [0.7, 0.1, 0.2]
```

If you do not supply the optional `split_rate` field, the default estimated value is `[0.9, 0.1, 0.0]` for classification and regression tasks, and `[0.9,0.05, 0.05]` for link prediction tasks.

### The separator field in a property-graph target object
<a name="machine-learning-property-graph-neptune_ml-targets-separator"></a>

(*Optional*) Used with a classification task.

The `separator` field specifies a character used to split a target property value into multiple categorical values when it is used to store multiple category values in a string. For example:

```
"separator": "|"
```

The presence of a `separator` field indicates that the task is a multi-target classification task.

## Fields in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets"></a>

### The node field in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets-node"></a>

Defines the node type of target nodes. Used with node classification tasks or node regression tasks. The node type of a node in RDF is defined by:

```
  node_id, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, node_type
```

An RDF `node` can only take a single value, like this:

```
  "node": "http://aws.amazon.com/neptune/csv2rdf/class/Movie"
```

### The subject field in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets-subject"></a>

For link prediction tasks, `subject` defines the source node type of target edges.

```
  "subject": "http://aws.amazon.com/neptune/csv2rdf/class/Director"
```

**Note**  
For link prediction tasks, `subject` should be used together with `predicate` and `object`. If any of these three is not provided, all edges are treated as the training target.

### The predicate field in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets-predicate"></a>

For node classification and node regression tasks, `predicate` defines what literal data is used as the target node feature of a target node.

```
  "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/genre"
```

**Note**  
If the target nodes have only one predicate defining the target node feature, the `predicate` field can be omitted.

For link prediction tasks, `predicate` defines the relation type of target edges:

```
"predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/direct"
```

**Note**  
For link prediction tasks, `predicate` should be used together with `subject` and `object`. If any of these three is not provided, all edges are treated as the training target.

### The object field in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets-object"></a>

For link prediction tasks, `object` defines the destination node type of target edges:

```
  "object": "http://aws.amazon.com/neptune/csv2rdf/class/Movie"
```

**Note**  
For link prediction tasks, `object` should be used together with `subject` and `predicate`. If any of these three is not provided, all edges are treated as the training target.

### The type field in an RDF target object
<a name="machine-learning-RDF-neptune_ml-targets-type"></a>

Indicates the type of target task to be performed, like this:

```
  "type" : "regression"
```

The supported task types for RDF data are:
+ `link_prediction`
+ `classification`
+ `regression`

This field is required.

### The `split_rate` field in a property-graph target object
<a name="machine-learning-RDF-neptune_ml-targets-split_rate"></a>

(*Optional*) An estimate of the proportions of nodes or edges that the training, validation, and test stages will use, respectively. These proportions are represented by a JSON array of three numbers between zero and one that add up to one:

```
"split_rate": [0.7, 0.1, 0.2]
```

If you do not supply the optional `split_rate` field, the default estimated value is `[0.9, 0.1, 0.0]`.

# The features field in neptune\$1ml
<a name="machine-learning-neptune_ml-features"></a>

Property values and RDF literals come in different formats and data types. To achieve good performance in machine learning, it is essential to convert those values to numerical encodings known as *features*.

Neptune ML performs feature extraction and encoding as part of the data-export and data-processing steps, as described in [Feature encoding in Neptune ML](machine-learning-feature-encoding.md).

For property-graph datasets, the export process automatically infers `auto` features for string properties and for numeric properties that contain multiples values. For numeric properties containing single values, it infers `numerical` features. For date properties it infers `datetime` features.

If you want to override an auto-inferred feature specification, or add a bucket numerical, TF-IDF, FastText, or SBERT specification for a property, you can control the feature encoding using the features field.

**Note**  
You can only use the `features` field to control the feature specifications for property-graph data, not for RDF data.

For free-form text, Neptune ML can use several different models to convert the sequence of tokens in a string property value into a fixed-size real-value vector:
+ [`text_fasttext`](machine-learning-feature-encoding.md#machine-learning-fasttext-features)   –   Uses [fastText](https://fasttext.cc/) encoding. This is the recommended encoding for features that use one and only one of the five languages that fastText supports.
+ [`text_sbert`](machine-learning-feature-encoding.md#machine-learning-sbert-features)   –   Uses the [Sentence BERT](https://www.sbert.net/docs/pretrained_models.html#sentence-embedding-models) (SBERT) encoding models. This is the recommended encoding for text that `text_fasttext` does not support.
+ [`text_word2vec`](machine-learning-feature-encoding.md#machine-learning-word2vec-features)   –   Uses [Word2Vec](https://wikipedia.org/wiki/Word2vec) algorithms originally published by [Google](https://code.google.com/archive/p/word2vec/) to encode text. Word2Vec only supports English.
+ [`text_tfidf`](machine-learning-feature-encoding.md#machine-learning-tfidf-features)   –   Uses a [term frequency–inverse document frequency](https://wikipedia.org/wiki/Tf-idf) (TF-IDF) vectorizer for encoding text. TF-IDF encoding supports statistical features that the other encodings do not.

The `features` field contains a JSON array of node property features. Objects in the array can contain the following fields:

**Contents**
+ [node](#machine-learning-neptune_ml-features-node)
+ [edge](#machine-learning-neptune_ml-features-edge)
+ [property](#machine-learning-neptune_ml-features-property)
+ [type](#machine-learning-neptune_ml-feature-types)
+ [norm](#machine-learning-neptune_ml-features-norm)
+ [language](#machine-learning-neptune_ml-features-language)
+ [max\$1length](#machine-learning-neptune_ml-features-max_length)
+ [separator](#machine-learning-neptune_ml-features-separator)
+ [range](#machine-learning-neptune_ml-features-range)
+ [bucket\$1cnt](#machine-learning-neptune_ml-features-bucket_cnt)
+ [slide\$1window\$1size](#machine-learning-neptune_ml-features-slide_window_size)
+ [imputer](#machine-learning-neptune_ml-features-imputer)
+ [max\$1features](#machine-learning-neptune_ml-features-max_features)
+ [min\$1df](#machine-learning-neptune_ml-features-min_df)
+ [ngram\$1range](#machine-learning-neptune_ml-features-ngram_range)
+ [datetime\$1parts](#machine-learning-neptune_ml-features-datetime_parts)

## The node field in features
<a name="machine-learning-neptune_ml-features-node"></a>

The `node` field specifies a property-graph label of a feature vertex. For example:

```
  "node": "Person"
```

If a vertex has multiple labels, use an array to contain them. For example:

```
  "node": ["Admin", "Person"]
```

## The edge field in features
<a name="machine-learning-neptune_ml-features-edge"></a>

The `edge` field specifies the edge type of a feature edge. An edge type consists of an array containing the property-graph label(s) of the source vertex, the property-graph label of the edge, and the property-graph label(s) of the destination vertex. You must supply all three values when specifying an edge feature. For example:

```
  "edge": ["User", "reviewed", "Movie"]
```

If a source or destination vertex of an edge type has multiple labels, use another array to contain them. For example:

```
  "edge": [["Admin", "Person"]. "edited", "Post"]
```

## The property field in features
<a name="machine-learning-neptune_ml-features-property"></a>

Use the property parameter to specify a property of the vertex identified by the `node` parameter. For example:

```
  "property" : "age"
```

## Possible values of the type field for features
<a name="machine-learning-neptune_ml-feature-types"></a>

The `type` parameter specifies the type of feature being defined. For example:

```
  "type": "bucket_numerical"
```

**Possible values of the `type` parameter**
+ **`"auto"`**   –   Specifies that Neptune ML should automatically detect the property type and apply a proper feature encoding. An `auto` feature can also have an optional `separator` field.

  See [Auto feature encoding in Neptune ML](machine-learning-feature-encoding.md#machine-learning-auto-encoding).
+ **`"category"`**   –   This feature encoding represents a property value as one of a number of categories. In other words, the feature can take one or more discrete values. A `category` feature can also have an optional `separator` field.

  See [Categorical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-categorical-features).
+ **`"numerical"`**   –   This feature encoding represents numerical property values as numbers in a continuous interval where "greater than" and "less than" have meaning.

   A `numerical` feature can also have optional `norm`, `imputer`, and `separator` fields.

  See [Numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-numerical-features).
+ **`"bucket_numerical"`**   –   This feature encoding divides numerical property values into a set of *buckets* or categories.

  For example, you could encode people's ages in 4 buckets: kids (0-20), young-adults (20-40), middle-aged (40-60), and elders (60 and up).

  A `bucket_numerical` feature requires a `range` and a `bucket_cnt` field, and can optionally also include an `imputer` and/or `slide_window_size` field.

  See [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).
+ **`"datetime"`**   –   This feature encoding represents a datetime property value as an array of these categorical features: year, month, weekday, and hour.

  One or more of these four categories can be eliminated using the `datetime_parts` parameter.

  See [Datetime features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-datetime-features).
+ **`"text_fasttext"`**   –   This feature encoding converts property values that consist of sentences or free-form text into numeric vectors using [fastText](https://fasttext.cc/) models. It supports five languages, namely English (`en`), Chinese (`zh`), Hindi (`hi`), Spanish (`es`), and French (`fr`). For text property values in any one those five languages, `text_fasttext` is the recommended encoding. However, it cannot handle cases where the same sentence contains words in more than one language.

  For other languages than the ones that fastText supports, use `text_sbert` encoding.

  If you have many property value text strings longer than, say, 120 tokens, use the `max_length` field to limit the number of tokens in each string that `"text_fasttext"` encodes.

  See [*fastText* encoding of text property values in Neptune ML](machine-learning-feature-encoding.md#machine-learning-fasttext-features).
+ **`"text_sbert"`**   –   This encoding converts text property values into numeric vectors using [Sentence BERT](https://www.sbert.net/docs/pretrained_models.html#sentence-embedding-models) (SBERT) models. Neptune supports two SBERT methods, namely `text_sbert128`, which is the default if you just specify `text_sbert`, and `text_sbert512`. The difference between them is the maximum number of tokens in a text property that gets encoded. The `text_sbert128` encoding only encodes the first 128 tokens, while `text_sbert512` encodes up to 512 tokens. As a result, using `text_sbert512` can require more processing time than `text_sbert128`. Both methods are slower than `text_fasttext`.

  The `text_sbert*` methods support many languages, and can encode a sentence that contains more than one language.

  See [Sentence BERT (SBERT) encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-sbert-features).
+ **`"text_word2vec"`**   –   This encoding converts text property values into numeric vectors using [Word2Vec](https://wikipedia.org/wiki/Word2vec) algorithms. It only supports English.

  See [Word2Vec encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-word2vec-features).
+ **`"text_tfidf"`**   –   This encoding converts text property values into numeric vectors using a [term frequency–inverse document frequency](https://wikipedia.org/wiki/Tf-idf) (TF-IDF) vectorizer.

  You define the parameters of a `text_tfidf` feature encoding using the `ngram_range` field, the `min_df` field, and the `max_features` field.

  See [TF-IDF encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-tfidf-features).
+ **`"none"`**   –   Using the `none` type causes no feature encoding to occur. The raw property values are parsed and saved instead.

  Use `none` only if you plan to perform your own custom feature encoding as part of custom model training.

## The norm field
<a name="machine-learning-neptune_ml-features-norm"></a>

This field is required for numerical features. It specifies a normalization method to use on numeric values:

```
"norm": "min-max"
```

The following normalization methods are supported:
+ **"min-max"**   –   Normalize each value by subtracting the minimum value from it and then dividing it by the difference between the maximum value and the minimum.
+ **"standard"**   –   Normalize each value by dividing it by the sum of all the values.
+ **"none"**   –   Don't normalize the numerical values during encoding.

See [Numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-numerical-features).

## The language field
<a name="machine-learning-neptune_ml-features-language"></a>

The language field specifies the language used in text property values. Its usage depends on the text encoding method:
+ For [`text_fasttext`](machine-learning-feature-encoding.md#machine-learning-fasttext-features) encoding, this field is required, and must specify one of the following languages:
  + `en`   (English)
  + `zh`   (Chinese)
  + `hi`   (Hindi)
  + `es`   (Spanish)
  + `fr`   (French)
+ For [`text_sbert`](machine-learning-feature-encoding.md#machine-learning-fasttext-features) encoding, this field is not used, since SBERT encoding is multilingual.
+ For [`text_word2vec`](machine-learning-feature-encoding.md#machine-learning-word2vec-features) encoding, this field is optional, since `text_word2vec` only supports English. If present, it must specify the name of the English language model:

  ```
  "language" : "en_core_web_lg"
  ```
+ For [`text_tfidf`](machine-learning-feature-encoding.md#machine-learning-tfidf-features) encoding, this field is not used.

## The max\$1length field
<a name="machine-learning-neptune_ml-features-max_length"></a>

The `max_length` field is optional for `text_fasttext` features, where it specifies the maximum number of tokens in an input text feature that will be encoded. Input text that is longer than `max_length` is truncated. For example, setting max\$1length to 128 indicates that any tokens after the 128th in a text sequence will be ignored:

```
"max_length": 128
```

## The separator field
<a name="machine-learning-neptune_ml-features-separator"></a>

This field is used optionally with `category`, `numerical` and `auto` features. It specifies a character that can be used to split a property value into multiple categorical values or numerical values:

```
"separator": ";"
```

Only use the `separator` field when the property stores multiple delimited values in a single string, such as `"Actor;Director"` or `"0.1;0.2"`.

See [Categorical features](machine-learning-feature-encoding.md#machine-learning-categorical-features), [Numerical features](machine-learning-feature-encoding.md#machine-learning-numerical-features), and [Auto encoding](machine-learning-feature-encoding.md#machine-learning-auto-encoding).

## The range field
<a name="machine-learning-neptune_ml-features-range"></a>

This field is required for `bucket_numerical` features. It specifies the range of numerical values that are to be divided into buckets, in the format `[lower-bound, upper-bound]`:

```
"range" : [20, 100]
```

If a property value is smaller than the lower bound then it is assigned to the first bucket, or if it's larger than the upper bound, it's assigned to the last bucket.

See [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).

## The bucket\$1cnt field
<a name="machine-learning-neptune_ml-features-bucket_cnt"></a>

This field is required for `bucket_numerical` features. It specifies the number of buckets that the numerical range defined by the `range` parameter should be divided into:

```
"bucket_cnt": 10
```

See [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).

## The slide\$1window\$1size field
<a name="machine-learning-neptune_ml-features-slide_window_size"></a>

This field is used optionally with `bucket_numerical` features to assign values to more than one bucket:

```
"slide_window_size": 5
```

The way a slide window works is that Neptune ML takes the window size **`s`** and transforms each numeric value **`v`** of a property into a range from ` v - s/2 ` through ` v + s/2 `. The value is then assigned to every bucket that the range overlaps.

See [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).

## The imputer field
<a name="machine-learning-neptune_ml-features-imputer"></a>

This field is used optionally with `numerical` and `bucket_numerical` features to provide an imputation technique for filling in missing values:

```
"imputer": "mean"
```

The supported imputation techniques are:
+ `"mean"`
+ `"median"`
+ `"most-frequent"`

If you don't include the imputer parameter, data preprocessing halts and exits when a missing value is encountered.

See [Numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-numerical-features) and [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).

## The max\$1features field
<a name="machine-learning-neptune_ml-features-max_features"></a>

This field is used optionally by `text_tfidf` features to specify the maximum number of terms to encode:

```
"max_features": 100
```

A setting of 100 causes the TF-IDF vectorizer to encode only the 100 most common terms. The default value if you don't include `max_features` is 5,000.

See [TF-IDF encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-tfidf-features).

## The min\$1df field
<a name="machine-learning-neptune_ml-features-min_df"></a>

This field is used optionally by `text_tfidf` features to specify the minimum document frequency of terms to encode:

```
"min_df": 5
```

A setting of 5 indicates that a term must appear in at least 5 different property values in order to be encoded.

The default value if you don't include the `min_df` parameter is `2`.

See [TF-IDF encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-tfidf-features).

## The ngram\$1range field
<a name="machine-learning-neptune_ml-features-ngram_range"></a>

This field is used optionally by `text_tfidf` features to specify what size sequences of words or tokens should be considered as potential individual terms to encode:

```
"ngram_range": [2, 4]
```

The value `[2, 4]` specifies that sequences of 2, 3 and 4 words should be considered as potential individual terms.

The default if you don't explicitly set `ngram_range` is `[1, 1]`, meaning that only single words or tokens are considered as terms to encode.

See [TF-IDF encoding of text features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-tfidf-features).

## The datetime\$1parts field
<a name="machine-learning-neptune_ml-features-datetime_parts"></a>

This field is used optionally by `datetime` features to specify which parts of the datetime value to encode categorically: 

```
"datetime_parts": ["weekday", "hour"]
```

If you don't include `datetime_parts`, by default Neptune ML encodes the year, month, weekday and hour parts of the datetime value. The value `["weekday", "hour"]` indicates that only the weekday and hour of datetime values should be encoded categorically in the feature.

If one of the parts does not have more than one unique value in the training set, it is not encoded.

See [Datetime features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-datetime-features).

# Examples of using parameters within additionalParams for tuning model-training configuration
<a name="machine-learning-data-export-additionalParams-examples"></a>

 The following examples demonstrate how to utilize the "additionalParams" feature in property-graph and RDF data models to configure various aspects of the model training process for a Neptune ML application. The examples cover a wide range of functionality, including specifying default split rates for training/validation/test data, defining node classification, regression, and link prediction tasks, as well as configuring different feature types such as numerical buckets, text embeddings, datetime, and categorical data. These detailed configurations allow you to tailor the machine learning pipeline to your specific data and modeling requirements, unlocking the full potential of the Neptune ML capabilities. 

**Contents**
+ [

## Property-graph examples using additionalParams
](#machine-learning-property-graph-additionalParams-examples)
  + [

### Specifying a default split rate for model-training configuration
](#machine-learning-property-graph-additionalParams-default-split-rate-example)
  + [

### Specifying a node-classification task for model-training configuration
](#machine-learning-property-graph-additionalParams-node-classification-example)
  + [

### Specifying a multi-class node classification task for model-training configuration
](#machine-learning-property-graph-additionalParams-multi-class-example)
  + [

### Specifying a node regression task for model-training configuration
](#machine-learning-property-graph-additionalParams-node-regression-example)
  + [

### Specifying an edge-classification task for model-training configuration
](#machine-learning-property-graph-additionalParams-edge-classification-example)
  + [

### Specifying a multi-class edge classification task for model-training configuration
](#machine-learning-property-graph-additionalParams-multi-edge-classification-example)
  + [

### Specifying an edge regression for model-training configuration
](#machine-learning-property-graph-additionalParams-edge-regression-example)
  + [

### Specifying a link prediction task for model-training configuration
](#machine-learning-property-graph-additionalParams-link-prediction-example)
  + [

### Specifying a numerical bucket feature
](#machine-learning-property-graph-additionalParams-numeric-bucket-example)
  + [

### Specifying a `Word2Vec` feature
](#machine-learning-property-graph-additionalParams-word2vec-example)
  + [

### Specifying a `FastText` feature
](#machine-learning-property-graph-additionalParams-fasttext-example)
  + [

### Specifying a `Sentence BERT` feature
](#machine-learning-property-graph-additionalParams-sbert-example)
  + [

### Specifying a `TF-IDF` feature
](#machine-learning-property-graph-additionalParams-tf-idf-example)
  + [

### Specifying a `datetime` feature
](#machine-learning-property-graph-additionalParams-datetime-example)
  + [

### Specifying a `category` feature
](#machine-learning-property-graph-additionalParams-category-example)
  + [

### Specifying a `numerical` feature
](#machine-learning-property-graph-additionalParams-numerical-example)
  + [

### Specifying an `auto` feature
](#machine-learning-property-graph-additionalParams-auto-example)
+ [

## RDF examples using `additionalParams`
](#machine-learning-RDF-additionalParams-examples)
  + [

### Specifying a default split rate for model-training configuration
](#machine-learning-RDF-additionalParams-default-split-rate-example)
  + [

### Specifying a node-classification task for model-training configuration
](#machine-learning-RDF-additionalParams-node-classification-example)
  + [

### Specifying a node regression task for model-training configuration
](#machine-learning-RDF-additionalParams-node-regression-example)
  + [

### Specifying a link prediction task for particular edges
](#machine-learning-RDF-additionalParams-link-prediction-example)
  + [

### Specifying a link prediction task for all edges
](#machine-learning-RDF-additionalParams-link-prediction-example)

## Property-graph examples using additionalParams
<a name="machine-learning-property-graph-additionalParams-examples"></a>

### Specifying a default split rate for model-training configuration
<a name="machine-learning-property-graph-additionalParams-default-split-rate-example"></a>

In the following example, the `split_rate` parameter sets the default split rate for model training. If no default split rate is specified, the training uses a value of [0.9, 0.1, 0.0]. You can override the default value on a per-target basis by specifying a `split_rate` for each target.

In the following example, the `default split_rate` field indicates that a split rate of `[0.7,0.1,0.2]` should be used unless overridden on a per-target basis:"

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "split_rate": [0.7,0.1,0.2],
    "targets": [
      (...)
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a node-classification task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-node-classification-example"></a>

To indicate which node property contains labeled examples for training purposes, add a node classification element to the `targets` array, using `"type" : "classification"`. Add a `split_rate` field if you want to override the default split rate.

In the following example, the `node` target indicates that the `genre` property of each `Movie` node should be treated as a node class label. The `split_rate` value overrides the default split rate:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "node": "Movie",
        "property": "genre",
        "type": "classification",
        "split_rate": [0.7,0.1,0.2]
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a multi-class node classification task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-multi-class-example"></a>

To indicate which node property contains multiple labeled examples for training purposes, add a node classification element to the targets array, using `"type" : "classification"`, and `separator` to specify a character that can be used to split a target property value into multiple categorical values. Add a `split_rate` field if you want to override the default split rate.

In the following example, the `node` target indicates that the `genre` property of each `Movie` node should be treated as a node class label. The `separator` field indicates that each genre property contains multiple semicolon-separated values:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "node": "Movie",
        "property": "genre",
        "type": "classification",
        "separator": ";"
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a node regression task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-node-regression-example"></a>

To indicate which node property contains labeled regressions for training purposes, add a node regression element to the targets array, using `"type" : "regression"`. Add a split\$1rate field if you want to override the default split rate.

The following `node` target indicates that the `rating` property of each `Movie` node should be treated as a node regression label:

```
    "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "node": "Movie",
        "property": "rating",
        "type" : "regression",
        "split_rate": [0.7,0.1,0.2]
      }
    ],
    "features": [
      ...
    ]
  }
}
```

### Specifying an edge-classification task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-edge-classification-example"></a>

To indicate which edge property contains labeled examples for training purposes, add an edge element to the `targets` array, using `"type" : "regression"`. Add a split\$1rate field if you want to override the default split rate.

The following `edge` target indicates that the `metAtLocation` property of each `knows` edge should be treated as an edge class label:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "edge": ["Person", "knows", "Person"],
        "property": "metAtLocation",
        "type": "classification"
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a multi-class edge classification task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-multi-edge-classification-example"></a>

To indicate which edge property contains multiple labeled examples for training purposes, add an edge element to the `targets` array, using `"type" : "classification"`, and a `separator` field to specify a character used to split a target property value into multiple categorical values. Add a `split_rate` field if you want to override the default split rate.

The following `edge` target indicates that the `sentiment` property of each `repliedTo` edge should be treated as an edge class label. The separator field indicates that each sentiment property contains multile comma-separated values:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "edge": ["Person", "repliedTo", "Message"],
        "property": "sentiment",
        "type": "classification",
        "separator": ","
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying an edge regression for model-training configuration
<a name="machine-learning-property-graph-additionalParams-edge-regression-example"></a>

To indicate which edge property contains labeled regression examples for training purposes, add an `edge` element to the `targets` array, using `"type" : "regression"`. Add a `split_rate` field if you want to override the default split rate.

The following `edge` target indicates that the `rating` property of each `reviewed` edge should be treated as an edge regression:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "edge": ["Person", "reviewed", "Movie"],
        "property": "rating",
        "type" : "regression"
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a link prediction task for model-training configuration
<a name="machine-learning-property-graph-additionalParams-link-prediction-example"></a>

To indicate which edges should be used for link prediction training purposes, add an edge element to the targets array using `"type" : "link_prediction"`. Add a `split_rate` field if you want to override the default split rate.

The following `edge` target indicates that `cites` edges should be used for link prediction:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "edge": ["Article", "cites", "Article"],
        "type" : "link_prediction"
      }
    ],
    "features": [
      (...)
    ]
  }
}
```

### Specifying a numerical bucket feature
<a name="machine-learning-property-graph-additionalParams-numeric-bucket-example"></a>

You can specify a numerical data feature for a node property by adding `"type": "bucket_numerical"` to the `features` array.

The following `node` feature indicates that the `age` property of each `Person` node should be treated as a numerical bucket feature:

```
  "additionalParams": {
  "neptune_ml": {
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Person",
        "property": "age",
        "type": "bucket_numerical",
        "range": [1, 100],
        "bucket_cnt": 5,
        "slide_window_size": 3,
        "imputer": "median"
      }
    ]
  }
}
```

### Specifying a `Word2Vec` feature
<a name="machine-learning-property-graph-additionalParams-word2vec-example"></a>

You can specify a `Word2Vec` feature for a node property by adding `"type": "text_word2vec"` to the `features` array.

The following `node` feature indicates that the `description` property of each `Movie` node should be treated as a `Word2Vec` feature:

```
"additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Movie",
        "property": "description",
        "type": "text_word2vec",
        "language": "en_core_web_lg"
      }
    ]
  }
}
```

### Specifying a `FastText` feature
<a name="machine-learning-property-graph-additionalParams-fasttext-example"></a>

You can specify a `FastText` feature for a node property by adding `"type": "text_fasttext"` to the `features` array. The `language` field is required, and must specify one of the following languages codes:
+ `en`   (English)
+ `zh`   (Chinese)
+ `hi`   (Hindi)
+ `es`   (Spanish)
+ `fr`   (French)

Note that the `text_fasttext` encoding cannot handle more than one language at a time in a feature.

The following `node` feature indicates that the French `description` property of each `Movie` node should be treated as a `FastText` feature:

```
"additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Movie",
        "property": "description",
        "type": "text_fasttext",
        "language": "fr",
        "max_length": 1024
      }
    ]
  }
}
```

### Specifying a `Sentence BERT` feature
<a name="machine-learning-property-graph-additionalParams-sbert-example"></a>

You can specify a `Sentence BERT` feature for a node property by adding `"type": "text_sbert"` to the `features` array. You don't need to specify the language, since the method automatically encodes text features using a multilingual language model.

The following `node` feature indicates that the `description` property of each `Movie` node should be treated as a `Sentence BERT` feature:

```
"additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Movie",
        "property": "description",
        "type": "text_sbert128",
      }
    ]
  }
}
```

### Specifying a `TF-IDF` feature
<a name="machine-learning-property-graph-additionalParams-tf-idf-example"></a>

You can specify a `TF-IDF` feature for a node property by adding `"type": "text_tfidf"` to the `features` array.

The following `node` feature indicates that the `bio` property of each `Person` node should be treated as a `TF-IDF` feature:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Movie",
        "property": "bio",
        "type": "text_tfidf",
        "ngram_range": [1, 2],
        "min_df": 5,
        "max_features": 1000
      }
    ]
  }
}
```

### Specifying a `datetime` feature
<a name="machine-learning-property-graph-additionalParams-datetime-example"></a>

The export process automatically infers `datetime` features for date properties. However, if you want to limit the `datetime_parts` used for a `datetime` feature, or override a feature specification so that a property that would normally be treated as an `auto` feature is explicitly treated as a `datetime` feature, you can do so by adding a `"type": "datetime"` to the features array.

The following `node` feature indicates that the `createdAt` property of each `Post` node should be treated as a `datetime` feature:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Post",
        "property": "createdAt",
        "type": "datetime",
        "datetime_parts": ["month", "weekday", "hour"]
      }
    ]
  }
}
```

### Specifying a `category` feature
<a name="machine-learning-property-graph-additionalParams-category-example"></a>

The export process automatically infers `auto` features for string properties and numeric properties containing multiples values. For numeric properties containing single values, it infers `numerical` features. For date properties it infers `datetime` features.

If you want to override a feature specification so that a property is treated as a categorical feature, add a `"type": "category"` to the features array. If the property contains multiple values, include a `separator` field. For example:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Post",
        "property": "tag",
        "type": "category",
        "separator": "|"
      }
    ]
  }
}
```

### Specifying a `numerical` feature
<a name="machine-learning-property-graph-additionalParams-numerical-example"></a>

The export process automatically infers `auto` features for string properties and numeric properties containing multiples values. For numeric properties containing single values, it infers `numerical` features. For date properties it infers `datetime` features.

If you want to override a feature specification so that a property is treated as a `numerical` feature, add `"type": "numerical"` to the features array. If the property contains multiple values, include a `separator` field. For example:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "Recording",
        "property": "duration",
        "type": "numerical",
        "separator": ","
      }
    ]
  }
}
```

### Specifying an `auto` feature
<a name="machine-learning-property-graph-additionalParams-auto-example"></a>

The export process automatically infers `auto` features for string properties and numeric properties containing multiples values. For numeric properties containing single values, it infers `numerical` features. For date properties it infers `datetime` features.

If you want to override a feature specification so that a property is treated as an `auto` feature, add `"type": "auto"` to the features array. If the property contains multiple values, include a `separator` field. For example:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      ...
    ],
    "features": [
      {
        "node": "User",
        "property": "role",
        "type": "auto",
        "separator": ","
      }
    ]
  }
}
```

## RDF examples using `additionalParams`
<a name="machine-learning-RDF-additionalParams-examples"></a>

### Specifying a default split rate for model-training configuration
<a name="machine-learning-RDF-additionalParams-default-split-rate-example"></a>

In the following example, the `split_rate` parameter sets the default split rate for model training. If no default split rate is specified, the training uses a value of [0.9, 0.1, 0.0]. You can override the default value on a per-target basis by specifying a `split_rate` for each target.

In the following example, the `default split_rate` field indicates that a split rate of `[0.7,0.1,0.2]` should be used unless overridden on a per-target basis:"

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "split_rate": [0.7,0.1,0.2],
    "targets": [
      (...)
    ]
  }
}
```

### Specifying a node-classification task for model-training configuration
<a name="machine-learning-RDF-additionalParams-node-classification-example"></a>

To indicate which node property contains labeled examples for training purposes, add a node classification element to the `targets` array, using `"type" : "classification"`. Add a node field to indicate the node type of target nodes. Add a `predicate` field to define which literal data is used as the target node feature of the target node. Add a `split_rate` field if you want to override the default split rate.

In the following example, the `node` target indicates that the `genre` property of each `Movie` node should be treated as a node class label. The `split_rate` value overrides the default split rate:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "node": "http://aws.amazon.com/neptune/csv2rdf/class/Movie",
        "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/genre",
        "type": "classification",
        "split_rate": [0.7,0.1,0.2]
      }
    ]
  }
}
```

### Specifying a node regression task for model-training configuration
<a name="machine-learning-RDF-additionalParams-node-regression-example"></a>

To indicate which node property contains labeled regressions for training purposes, add a node regression element to the targets array, using `"type" : "regression"`. Add a `node` field to indicate the node type of target nodes. Add a `predicate` field to define which literal data is used as the target node feature of the target node. Add a `split_rate` field if you want to override the default split rate.

The following `node` target indicates that the `rating` property of each `Movie` node should be treated as a node regression label:

```
    "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "node": "http://aws.amazon.com/neptune/csv2rdf/class/Movie",
        "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/rating",
        "type": "regression",
        "split_rate": [0.7,0.1,0.2]
      }
    ]
  }
}
```

### Specifying a link prediction task for particular edges
<a name="machine-learning-RDF-additionalParams-link-prediction-example"></a>

To indicate which edges should be used for link prediction training purposes, add an edge element to the targets array using `"type" : "link_prediction"`. Add `subject`, `predicate` and `object` fields to specify the edge type. Add a `split_rate` field if you want to override the default split rate.

The following `edge` target indicates that `directed` edges that connect `Directors` to `Movies` should be used for link prediction:

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "subject": "http://aws.amazon.com/neptune/csv2rdf/class/Director",
        "predicate": "http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/directed",
        "object": "http://aws.amazon.com/neptune/csv2rdf/class/Movie",
        "type" : "link_prediction"
      }
    ]
  }
}
```

### Specifying a link prediction task for all edges
<a name="machine-learning-RDF-additionalParams-link-prediction-example"></a>

To indicate that all edges should be used for link prediction training purposes, add an `edge` element to the targets array using `"type" : "link_prediction"`. Do not add `subject`, `predicate`, or `object` fields. Add a `split_rate` field if you want to override the default split rate.

```
  "additionalParams": {
  "neptune_ml": {
    "version": "v2.0",
    "targets": [
      {
        "type" : "link_prediction"
      }
    ]
  }
}
```

# Processing the graph data exported from Neptune for training
<a name="machine-learning-on-graphs-processing"></a>

The data-processing step takes the Neptune graph data created by the export process and creates the information that is used by the [Deep Graph Library (DGL)](https://www.dgl.ai/) during training. This includes performing various data mappings and transformations:
+ Parsing nodes and edges to construct the graph- and ID-mapping files required by DGL.
+ Converting node and edge properties into the node and edge features required by DGL.
+ Splitting the data into training, validation, and test sets.

## Managing the data-processing step for Neptune ML
<a name="machine-learning-on-graphs-processing-managing"></a>

After you have exported the data from Neptune that you want to use for model training, you can start a data-processing job using a command like the following:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --input-data-s3-location "s3://(S3 bucket name)/(path to your input folder)" \
  --id "(a job ID for the new job)" \
  --processed-data-s3-location "s3://(S3 bucket name)/(path to your output folder)" \
  --config-file-name "training-job-configuration.json"
```

For more information, see [start-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_data_processing_job(
    inputDataS3Location='s3://(S3 bucket name)/(path to your input folder)',
    id='(a job ID for the new job)',
    processedDataS3Location='s3://(S3 bucket name)/(path to your output folder)',
    configFileName='training-job-configuration.json'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)",
        "configFileName" : "training-job-configuration.json"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/dataprocessing \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)",
        "configFileName" : "training-job-configuration.json"
      }'
```

------

The details of how to use this command are explained in [The dataprocessing command](machine-learning-api-dataprocessing.md), along with information about how to get the status of a running job, how to stop a running job, and how to list all running jobs.

## Processing updated graph data for Neptune ML
<a name="machine-learning-on-graphs-processing-updated"></a>

You can also supply a `previousDataProcessingJobId` to the API to ensure that the new data processing job uses the same processing method as a previous job. This is required when you want to get predictions for updated graph data in Neptune, either by retraining the old model on the new data, or by recomputing the model artifacts on the new data.

You do this by using a command like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --input-data-s3-location "s3://(Amazon S3 bucket name)/(path to your input folder)" \
  --id "(a job ID for the new job)" \
  --processed-data-s3-location "s3://(Amazon S3 bucket name)/(path to your output folder)" \
  --previous-data-processing-job-id "(the job ID of the previous data-processing job)"
```

For more information, see [start-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_data_processing_job(
    inputDataS3Location='s3://(Amazon S3 bucket name)/(path to your input folder)',
    id='(a job ID for the new job)',
    processedDataS3Location='s3://(Amazon S3 bucket name)/(path to your output folder)',
    previousDataProcessingJobId='(the job ID of the previous data-processing job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(Amazon S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(Amazon S3 bucket name)/(path to your output folder)",
        "previousDataProcessingJobId" : "(the job ID of the previous data-processing job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/dataprocessing \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(Amazon S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(Amazon S3 bucket name)/(path to your output folder)",
        "previousDataProcessingJobId" : "(the job ID of the previous data-processing job)"
      }'
```

------

Set the value of the `previousDataProcessingJobId` parameter to the job ID of the previous-data processing job that corresponds to the trained model.

**Note**  
Node deletions in the updated graph are currently not supported. If nodes have been removed in an updated graph, you have to start a completely new data processing job rather than use `previousDataProcessingJobId`.

# Feature encoding in Neptune ML
<a name="machine-learning-feature-encoding"></a>

Property values come in different formats and data types. To achieve good performance in machine learning, it is essential to convert those values to numerical encodings known as *features*.

Neptune ML performs feature extraction and encoding as part of the data-export and data-processing steps, using feature-encoding techniques described here.

**Note**  
If you plan to implement your own feature encoding in a custom model implementation, you can disable the automatic feature encoding in the data preprocessing stage by selecting `none` as the feature encoding type. No feature encoding then occurs on that node or edge property, and instead the raw property values are parsed and saved in a dictionary. Data preprocessing still creates the DGL graph from the exported dataset, but the constructed DGL graph doesn't have the pre-processed features for training.  
You should use this option only if you plan to perform your custom feature encoding as part of custom model training. See [Custom models in Neptune ML](machine-learning-custom-models.md) for details.

## Categorical features in Neptune ML
<a name="machine-learning-categorical-features"></a>

A property that can take one or more distinct values from a fixed list of possible values is a categorical feature. In Neptune ML, categorical features are encoded using [one-hot encoding](https://en.wikipedia.org/wiki/One-hot). The following example shows how the property name of different foods is one-hot encoded according to its category:

```
    Food        Veg.   Meat   Fruit    Encoding
   ---------    ----   ----   -----    --------
    Apple         0      0      1         001
    Chicken       0      1      0         010
    Broccoli      1      0      0         100
```

**Note**  
The maximum number of categories in any categorical feature is 100. If a property has more than 100 categories of value, only the most common 99 of them are placed in distinct categories, and the rest are placed in a special category named `OTHER`.

## Numerical features in Neptune ML
<a name="machine-learning-numerical-features"></a>

Any property whose values are real numbers can be encoded as a numerical feature in Neptune ML. Numerical features are encoded using floating-point numbers.

You can specify a data-normalization method to use when encoding numerical features, like this: `"norm": "normalization technique"`. The following normalization techniques are supported:
+ **"none"**   –   Don't normalize the numerical values during encoding.
+ **"min-max"**   –   Normalize each value by subtracting the minimum value from it and then dividing it by the difference between the maximum value and the minimum.
+ **"standard"**   –   Normalize each value by dividing it by the sum of all the values.

## Bucket-numerical features in Neptune ML
<a name="machine-learning-bucket_numerical-features"></a>

Rather than representing a numerical property using raw numbers, you can condense numerical values into categories. For example, you could divide people's ages into categories such as kids (0-20), young adults (20-40), middle-aged people (40-60) and elders (from 60 on). Using these numerical buckets, you would be transforming a numerical property into a kind of categorical feature.

In Neptune ML, you can cause a numerical property to be encoded as a bucket-numerical feature, you must provide two things:
+ A numerical range in the form, ` "range": [a, b] `, where `a` and `b` are integers.
+ A bucket count, in the form ` "bucket_cnt": c `, where `c` is the number of buckets, also an integer.

Neptune ML then calculates the size of each bucket as ` ( b - a ) / c `, and encodes each numeric value as the number of whatever bucket it falls into. Any value less than `a` is considered to belong in the first bucket, and any value greater than `b` is considered to belong in the last bucket.

You can also, optionally, make numeric values fall into more than one bucket, by specifying a slide-window size, like this: ` "slide_window_size": s `, where `s` is a number. Neptune ML then transforms each numeric value `v` of the property into a range from ` v - s/2 ` through ` v + s/2 `, and assigns the value `v` to every bucket that the range covers.

Finally, you can also optionally provide a way of filling in missing values for numerical features and bucket-numerical features. You do this using ` "imputer": "imputation technique "`, where the imputation technique is one of `"mean"`, `"median"`, or `"most-frequent"`. If you don't specify an imputer, a missing value can cause processing to halt.

## Text feature encoding in Neptune ML
<a name="machine-learning-text-features"></a>

For free-form text, Neptune ML can use several different models to convert the sequence of tokens in a property value string into a fixed-size real-value vector:
+ [`text_fasttext`](#machine-learning-fasttext-features)   –   Uses [fastText](https://fasttext.cc/) encoding. This is the recommended encoding for features that use one and only one of the five languages that fastText supports.
+ [`text_sbert`](#machine-learning-sbert-features)   –   Uses the [Sentence BERT](https://www.sbert.net/docs/pretrained_models.html#sentence-embedding-models) (SBERT) encoding models. This is the recommended encoding for text that `text_fasttext` does not support.
+ [`text_word2vec`](#machine-learning-word2vec-features)   –   Uses the [Word2Vec](https://wikipedia.org/wiki/Word2vec) algorithms originally published by [Google](https://code.google.com/archive/p/word2vec/) to encode text. Word2Vec only supports English.
+ [`text_tfidf`](#machine-learning-tfidf-features)   –   Uses a [term frequency–inverse document frequency](https://wikipedia.org/wiki/Tf-idf) (TF-IDF) vectorizer for encoding text. TF-IDF encoding supports statistical features that the other encodings do not.

### *fastText* encoding of text property values in Neptune ML
<a name="machine-learning-fasttext-features"></a>

Neptune ML can use the [fastText](https://fasttext.cc/) models to convert text property values into fixed-size real-value vectors. This is the recommended encoding method for text property values in any one of the five languages that fastText supports:
+ `en`   (English)
+ `zh`   (Chinese)
+ `hi`   (Hindi)
+ `es`   (Spanish)
+ `fr`   (French)

Note that fastText cannot handle sentences containing words in more than one language.

The `text_fasttext` method can optionally take `max_length` field that specifies the maximum number of tokens in a text property value that will be encoded, after which the string is truncated. This can improve performance when text property values contain long strings, because if `max_length` is not specified, fastText encodes all the tokens regardless of the string length.

This example specifies that French movie titles are encoded using fastText:

```
{
    "file_name" : "nodes/movie.csv",
    "separator" : ",",
    "node" : ["~id", "movie"],
    "features" : [
      {
        "feature": ["title", "title", "text_fasttext"],
        "language": "fr",
        "max_length": 1024
      }
    ]
  }
```

### Sentence BERT (SBERT) encoding of text features in Neptune ML
<a name="machine-learning-sbert-features"></a>

Neptune ML can convert the sequence of tokens in a string property value into a fixed-size real-value vector using [Sentence BERT](https://www.sbert.net/docs/pretrained_models.html#sentence-embedding-models) (SBERT) models. Neptune supports two SBERT methods: `text_sbert128`, which is the default if you just specify `text_sbert`, and `text_sbert512`. The difference between the two is the maximum length of a text property value string that is encoded. The `text_sbert128` encoding truncates text strings after encoding 128 tokens, while `text_sbert512` truncates text strings after encoding 512 tokens. As a result, `text_sbert512` requires more processing time than `text_sbert128`. Both methods are slower than `text_fasttext`.

SBERT encoding is multilingual, so there is no need to specify a language for the property value text you are encoding. SBERT supports many languages, and can encode a sentence that contains more than one language. If you are encoding property values containing text in a language or languages that fastText does not support, SBERT is the recommended encoding method.

The following example specifies that movie titles are encoded as SBERT up to a maximum of 128 tokens:

```
{
    "file_name" : "nodes/movie.csv",
    "separator" : ",",
    "node" : ["~id", "movie"],
    "features" : [
      { "feature": ["title", "title", "text_sbert128"] }
    ]
  }
```

### Word2Vec encoding of text features in Neptune ML
<a name="machine-learning-word2vec-features"></a>

Neptune ML can encode string property values as a Word2Vec feature ([Word2Vec algorithms](https://wikipedia.org/wiki/Word2vec) were originally published by [Google](https://code.google.com/archive/p/word2vec/)). The `text_word2vec` method encodes the tokens in a string as a dense vector using one of the [spaCy trained models](https://spacy.io/models). This only supports the English language using the [en\$1core\$1web\$1lg](https://spacy.io/models/en#en_core_web_lg) model).

The following example specifies that movie titles are encoded using Word2Vec:

```
{
    "file_name" : "nodes/movie.csv",
    "separator" : ",",
    "node" : ["~id", "movie"],
    "features" : [
      {
        "feature": ["title", "title", "text_word2vec"],
        "language": "en_core_web_lg"
      }
    ]
  }
```

Note that the language field is optional, since the English `en_core_web_lg` model is the only one that Neptune supports.

### TF-IDF encoding of text features in Neptune ML
<a name="machine-learning-tfidf-features"></a>

Neptune ML can encode text property values as `text_tfidf` features. This encoding converts the sequence of words in the text into a numeric vector using a [term frequency–inverse document frequency](https://wikipedia.org/wiki/Tf-idf) (TF-IDF) vectorizer, followed by a dimensionality-reduction operation.

[TF-IDF](https://en.wikipedia.org/wiki/Tf%E2%80%93idf) (term frequency – inverse document frequency) is a numerical value intended to measure how important a word is in a document set. It is calculated by dividing the number of times a word appears in a given property value by the total number of such property values that it appears in.

For example, if the word "kiss" appears twice in a given movie title (say, "kiss kiss bang bang"), and "kiss" appears in the title of 4 movies in all, then the TF-IDF value of "kiss" in the "kiss kiss bang bang" title would be ` 2 / 4 `.

The vector that is initially created has ***d*** dimensions, where ***d*** is the number of unique terms in all property values of that type. The dimensionality-reduction operation uses a random sparse projection to reduce that number to a maximum of 100. The vocabulary of a graph is then generated by merging all the `text_tfidf` features in it.

You can control the TF-IDF vectorizer in several ways:
+ **`max_features`**   –   Using the `max_features` parameter, you can limit the number of terms in `text_tfidf` features to the most common ones. For example, if you set `max_features` to 100, only the top 100 most commonly used terms are included. The default value for `max_features` if you don't explicitly set it is 5,000.
+ **`min_df`**   –   Using the `min_df` parameter, you can limit the number of terms in `text_tfidf` features to ones having at least a specified document frequency. For example, if you set `min_df` to 5, only terms that appear in at least 5 different property values are used. The default value for `min_df` if you don't explicitly set it is 2.
+ **`ngram_range`**   –   The `ngram_range` parameter determines what combinations of words are treated as terms. For example, if you set `ngram_range` to `[2, 4]`, the following 6 terms would be found in the "kiss kiss bang bang" title:
  + *2-word terms*:  "kiss kiss", "kiss bang", and "bang bang".
  + *3-word terms*:  "kiss kiss bang" and "kiss bang bang".
  + *4-word terms*:  "kiss kiss bang bang".

  The default setting for `ngram_range` is `[1, 1]`.

## Datetime features in Neptune ML
<a name="machine-learning-datetime-features"></a>

Neptune ML can convert parts of `datetime` property values into categorical features by encoding them as [one-hot arrays](https://en.wikipedia.org/wiki/One-hot). Use the `datetime_parts` parameter to specify one or more of the following parts to encode: `["year", "month", "weekday", "hour"]`. If you don't set `datetime_parts`, by default all four parts are encoded.

For example, if the range of datetime values spans the years 2010 through 2012, the four parts of the datetime entry `2011-04-22 01:16:34` are as follows:
+ **year**   –   `[0, 1, 0]`.

  Since there are only 3 years in the span (2010, 2011, and 2012), the one-hot array has three entries, one for each year.
+ **month**   –   `[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]`.

  Here, the one-hot array has an entry for each month of the year.
+ **weekday**   –   `[0, 0, 0, 0, 1, 0, 0]`.

  The ISO 8601 standard states that Monday is the first day of the week, and since April 22, 2011 was a Friday, the corresponding one-hot weekday array is hot in the fifth position. 
+ **hour**   –   `[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`.

  The hour 1 AM is set in a 24-member one-hot array.

Day of the month, minute, and second are not encoded categorically.

If the total `datetime` range in question only includes dates within a single year, no `year` array is encoded.

You can specify an imputation strategy to fill in missing `datetime` values, using the `imputer` parameter and one of the strategies available for numerical features.

## Auto feature encoding in Neptune ML
<a name="machine-learning-auto-encoding"></a>

Instead of manually specifying the feature encoding methods to use for the properties in your graph, you can set `auto` as a feature encoding method. Neptune ML then attempts to infer the best feature encoding for each property based on its underlying data type.

Here are some of the heuristics that Neptune ML uses in selecting the appropriate feature encodings:
+ If the property has only numeric values and can be cast into numeric data types, then Neptune ML generally encodes it as a numeric value. However, if the number of unique values for the property is less than 10% of the total number of values and the cardinality of those unique values is less than 100, then Neptune ML uses a categorical encoding.
+ If the property values can be cast to a `datetime` type, then Neptune ML encodes them as a `datetime` feature.
+ If the property values can be coerced to booleans (1/0 or True/False), then Neptune ML uses category encoding.
+ If the property is a string with more than 10% of its values unique, and the average number of tokens per value is greater than or equal to 3, the Neptune ML infers the property type to be text and automatically detects the language being used. If the language detected is one of the ones supported by [fastText](#machine-learning-fasttext-features), namely English, Chinese, Hindi, Spanish and French, then Neptune ML uses `text_fasttext` to encode the text. Othewise, Neptune ML uses [`text_sbert`](#machine-learning-sbert-features).
+ If the property is a string not classified as a text feature then Neptune ML presumes it to be a categorical feature and uses category encoding.
+ If each node has its own unique value for a property that is inferred to be a category feature, Neptune ML drops the property from the training graph because it is probably an ID that would not be informative for learning.
+ If the property is known to contain valid Neptune separators such as semicolons (";"), then Neptune ML can only treat the property as `MultiNumerical` or `MultiCategorical`.
  + Neptune ML first tries to encode the values as numeric features. if this succeeds, Neptune ML uses numerical encoding to create numeric vector features.
  + Otherwise, Neptune ML encodes the values as multi-categorical.
+ If Neptune ML cannot infer the data type of a property's values, Neptune MLdrops the property from the training graph.

# Editing a training data configuration file
<a name="machine-learning-processing-training-config-file"></a>

The Neptune export process exports Neptune ML data from a Neptune DB cluster into an S3 bucket. It exports nodes and edges separately into a `nodes/` and an `edges/` folder. It also creates a JSON training data configuration file, named `training-data-configuration.json` by default. This file contains information about the schema of the graph, the types of its features, feature transformation and normalization operations, and the target feature for a classification or regression task.

There might be cases when you want to modify the configuration file directly. One such case is when you want to change the way features are processed or how the graph is constructed, without needing to rerun the export every time you want to modify the specification for the machine learning task you're solving.

**To edit the training data configuration file**

1. **Download the file to your local machine.**

   Unless you specified one or more named jobs in the `additionalParams/neptune_ml` parameter passed to the export process, the file will have the default name, which is `training-data-configuration.json`. You can use an AWS CLI command like this to download the file:

   ```
   aws s3 cp \
     s3://(your Amazon S3 bucket)/(path to your export folder)/training-data-configuration.json \
     ./
   ```

1. **Edit the file using a text editor.**

1. **Upload the modified file.** Upload the modified file back to the same location in Amazon S3 from which you downloaded it, using use an AWS CLI command like this:

   ```
   aws s3 cp \
     training-data-configuration.json \
     s3://(your Amazon S3 bucket)/(path to your export folder)/training-data-configuration.json
   ```

# Example of a JSON training data configuration file
<a name="machine-learning-processing-training-config-file-example"></a>

Here is a sample training data configuration file that describes a graph for a node-classification task:

```
{
  "version" : "v2.0",
  "query_engine" : "gremlin",
  "graph" : [
    {
      "edges" : [
        {
          "file_name" : "edges/(movie)-included_in-(genre).csv",
          "separator" : ",",
          "source" : ["~from", "movie"],
          "relation" : ["", "included_in"],
          "dest" : [ "~to", "genre" ]
        },
        {
          "file_name" : "edges/(user)-rated-(movie).csv",
          "separator" : ",",
          "source" : ["~from", "movie"],
          "relation" : ["rating", "prefixname"], # [prefixname#value]
          "dest" : ["~to", "genre"],
          "features" : [
            {
              "feature" : ["rating", "rating", "numerical"],
              "norm" : "min-max"
            }
          ]
        }
      ],
      "nodes" : [
        {
          "file_name" : "nodes/genre.csv",
          "separator" : ",",
          "node" : ["~id", "genre"],
          "features" : [
            {
              "feature": ["name", "genre", "category"],
              "separator": ";"
            }
          ]
        },
        {
          "file_name" : "nodes/movie.csv",
          "separator" : ",",
          "node" : ["~id", "movie"],
          "features" : [
            {
              "feature": ["title", "title", "word2vec"],
              "language": ["en_core_web_lg"]
            }
          ]
        },
        {
          "file_name" : "nodes/user.csv",
          "separator" : ",",
          "node" : ["~id", "user"],
          "features" : [
            {
              "feature": ["age", "age", "numerical"],
              "norm" : "min-max",
              "imputation": "median",
            },
            {
              "feature": ["occupation", "occupation", "category"],
            }
          ],
          "labels" : [
            {
              "label": ["gender", "classification"],
              "split_rate" : [0.8, 0.2, 0.0]
            }
          ]
        }
      ]
    },
    "warnings" : [ ]
  ]
}
```

# The structure of JSON training data configuration files
<a name="machine-learning-processing-training-config-file-structure"></a>

The training configuration file refers to CSV files saved by the export process in the `nodes/` and `edges/` folders.

Each file under `nodes/` stores information about nodes that have the same property-graph node label. Each column in a node file stores either the node ID or the node property. The first line of the file contains a header that specifies the `~id` or property name for each column.

Each file under `edges/` stores information about nodes that have the same property-graph edge label. Each column in a node file stores either the source node ID, the destination node ID, or the edge property. The first line of the file contains a header specifying the `~from`, `~to`, or property name for each column.

The training data configuration file has three top-level elements:

```
{
  "version" : "v2.0",
  "query_engine" : "gremlin",
  "graph" : [ ... ]
}
```
+ `version`   –   (String) The version of configuration file being used.
+ `query_engine`   –   (String) The query language used for exporting the graph data. Currently, only "gremlin" is valid.
+ `graph`   –   (JSON array) lists one or more configuration objects that contain model parameters for each of the nodes and edges that will be used.

  The configuration objects in the graph array have the structure described in the next section.

## Contents of a configuration object listed in the `graph` array
<a name="machine-learning-graph-training-config-object"></a>

A configuration object in the `graph` array can contain three top-level nodes:

```
    {
      "edges"    : [ ... ],
      "nodes"    : [ ... ],
      "warnings" : [ ... ],
    }
```
+ `edges`   –   (array of JSON objects) Each JSON object specifies a set of parameters to define how an edge in the graph will be treated during the model processing and training. This is only used with the Gremlin engine.
+ `nodes`   –   (array of JSON objects) Each JSON object specifies a set of parameters to define how a node in the graph will be treated during the model processing and training. This is only used with the Gremlin engine.
+ `warnings`   –   (array of JSON objects) Each object contains a warning generated during the data export process.

## Contents of an edge configuration object listed in an `edges` array
<a name="machine-learning-graph-edges-config"></a>

An edge configuration object listed in an `edges` array can contain the following top-level fields:

```
      {
        "file_name" : "(path to a CSV file)",
        "separator" : "(separator character)",
        "source"    : ["(column label for starting node ID)", "(starting node type)"],
        "relation"  : ["(column label for the relationship name)", "(the prefix name for the relationship name)"],
        "dest"      : ["(column label for ending node ID)", "(ending node type)"],
        "features"  : [(array of feature objects)],
        "labels"    : [(array of label objects)]
      }
```
+ **`file_name`**   –   A string specifying the path to a CSV file that stores information about edges having the same property-graph label.

  The first line of that file contains a header line of column labels.

  The first two column labels are `~from` and `~to`. The first column (the `~from` column) stores the ID of the edge's starting node, and the second (the `~to` column) stores the ID of the edge's ending node.

  The remaining column labels in the header line specify, for each remaining column, the name of the edge property whose values have been exported into that column.
+ **`separator`**   –   A string containing the delimiter that separates columns in that CSV file.
+ **`source`**   –   A JSON array containing two strings that specify the starting node of the edge. The first string contains the header name of the column that the starting node ID is stored in. The second string specifies the node type.
+ **`relation`**   –   A JSON array containing two strings that specify the edge's relation type. The first string contains the header name of the column that the relation name (`relname`) is stored in. The second string contains the prefix for the relation name (`prefixname`).

  The full relation type consists of the two strings combined, with a hyphen character between them, like this: `prefixname-relname`.

  If the first string is empty, all edges have the same relation type, namely the `prefixname` string.
+ **`dest`**   –   A JSON array containing two strings that specify the ending node of the edge. The first string contains the header name of the column that the node ID is stored in. The second string specifies the node type.
+ **`features`**   –   A JSON array of property-value feature objects. Each property-value feature object contains the following fields:
  + **feature**   –   A JSON array of three strings. The first string contains the header name of the column that contains the property value. The second string contains the feature name. The third string contains the feature type.
  + **norm**   –   (*Optional*) Specifies a normalization method to apply to the property values.

    
+ **`labels`**   –   A JSON array of objects. Each of the objects defines a target feature of the edges, and specifies the proportions of the edges that the training and validation stages should take. Each object contains the following fields:
  + **label**   –   A JSON array of two strings. The first string contains the header name of the column that contains the target feature property value. The second string specifies one of the following target task types:
    + `"classification"`   –   An edge classification task. The property values provided in the column identified by the first string in the `label` array are treated as categorical values. For an edge classification task, the first string in the `label` array can't be empty.
    + `"regression"`   –   An edge regression task. The property values provided in the column identified by the first string in the `label` array are treated as numerical values. For an edge regression task, the first string in the `label` array can't be empty.
    + `"link_prediction"`   –   A link prediction task. No property values are required. For a link prediction task, the first string in the `label` array is ignored.
  + **`split_rate`**   –   A JSON array containing three numbers between zero and one that add up to one and that represent an estimate of the proportions of nodes that the training, validation, and test stages will use, respectively. Either this field or the `custom_split_filenames` can be defined, but not both. See [split\$1rate](machine-learning-neptune_ml-targets.md#machine-learning-property-graph-neptune_ml-targets-split_rate).
  + **`custom_split_filenames`**   –   A JSON object that specifies the file names for the files that define the training, validation and test populations. Either this field or `split_rate` can be defined, but not both. See [Custom train-validation-test proportions](#machine-learning-custom-stages-splits) for more information.

## Contents of a node configuration object listed in a `nodes` array
<a name="machine-learning-graph-nodes-config"></a>

A node configuration object listed in a `nodes` array can contain the following fields:

```
      {
        "file_name" : "(path to a CSV file)",
        "separator" : "(separator character)",
        "node"      : ["(column label for the node ID)", "(node type)"],
        "features"  : [(feature array)],
        "labels"    : [(label array)],
      }
```
+ **`file_name`**   –   A string specifying the path to a CSV file that stores information about nodes having the same property-graph label.

  The first line of that file contains a header line of column labels.

  The first column label is `~id`, and the first column (the `~id` column) stores the node ID.

  The remaining column labels in the header line specify, for each remaining column, the name of the node property whose values have been exported into that column.
+ **`separator`**   –   A string containing the delimiter that separates columns in that CSV file.
+ **`node`**   –   A JSON array containing two strings. The first string contains the header name of the column that stores node IDs. The second string specifies the node type in the graph, which corresponds to a property-graph label of the node.
+ **`features`**   –   A JSON array of node feature objects. See [Contents of a feature object listed in a `features` array for a node or edge](#machine-learning-graph-node-features-config).
+ **`labels`**   –   A JSON array of node label objects. See [Contents of a node label object listed in a node `labels` array](#machine-learning-graph-node-labels-config).

## Contents of a feature object listed in a `features` array for a node or edge
<a name="machine-learning-graph-node-features-config"></a>

A node feature object listed in a node `features` array can contain the following top-level fields:
+ **`feature`**   –   A JSON array of three strings. The first string contains the header name of the column that contains the property value for the feature. The second string contains the feature name.

  The third string contains the feature type. Valid feature types are listed in [Possible values of the type field for features](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-feature-types). 
+ **`norm`**   –   This field is required for numerical features. It specifies a normalization method to use on numeric values. Valid values are `"none"`, `"min-max"`, and "standard". See [The norm field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-norm) for details.
+ **`language`**   –   The language field specifies the language being used in text property values. Its usage depends on the text encoding method:
  + For [`text_fasttext`](machine-learning-feature-encoding.md#machine-learning-fasttext-features) encoding, this field is required, and must specify one of the following languages:
    + `en`   (English)
    + `zh`   (Chinese)
    + `hi`   (Hindi)
    + `es`   (Spanish)
    + `fr`   (French)

    However, `text_fasttext` cannot handle more than one language at a time.
  + For [`text_sbert`](machine-learning-feature-encoding.md#machine-learning-fasttext-features) encoding, this field is not used, since SBERT encoding is multilingual.
  + For [`text_word2vec`](machine-learning-feature-encoding.md#machine-learning-word2vec-features) encoding, this field is optional, since `text_word2vec` only supports English. If present, it must specify the name of the English language model:

    ```
    "language" : "en_core_web_lg"
    ```
  + For [`tfidf`](machine-learning-feature-encoding.md#machine-learning-tfidf-features) encoding, this field is not used.
+ **`max_length`**   –   This field is optional for [`text_fasttext`](machine-learning-feature-encoding.md#machine-learning-fasttext-features) features, where it specifies the maximum number of tokens in an input text feature that will be encoded. Input text after `max_length` is reached is ignored. For example, setting max\$1length to 128 indicates that any tokens after the 128th in a text sequence are ignored.
+ **`separator`**  –   This field is used optionally with `category`, `numerical` and `auto` features. It specifies a character that can be used to split a property value into multiple categorical values or numerical values.

  See [The separator field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-separator).
+ **`range`**  –   This field is required for `bucket_numerical` features. It specifies the range of numerical values that are to be divided into buckets.

  See [The range field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-range).
+ **`bucket_cnt`**  –   This field is required for `bucket_numerical` features. It specifies the number of buckets that the numerical range defined by the `range` parameter should be divided into.

  See [Bucket-numerical features in Neptune ML](machine-learning-feature-encoding.md#machine-learning-bucket_numerical-features).
+ **`slide_window_size`**  –   This field is used optionally with `bucket_numerical` features to assign values to more than one bucket.

  See [The slide\$1window\$1size field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-slide_window_size).
+ **`imputer`**  –   This field is used optionally with `numerical`, `bucket_numerical`, and `datetime` features to provide an imputation technique for filling in missing values. The supported imputation techniques are `"mean"`, `"median"`, and `"most_frequent"`.

  See [The imputer field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-imputer).
+ **`max_features`**  –   This field is used optionally by `text_tfidf` features to specify the maximum number of terms to encode.

  See [The max\$1features field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-max_features).
+ **`min_df`**  –   This field is used optionally by `text_tfidf` features to specify the minimum document frequency of terms to encode

  See [The min\$1df field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-min_df).
+ **`ngram_range`**  –   This field is used optionally by `text_tfidf` features to specify a range of numbers of words or tokens to considered as potential individual terms to encode

  See [The ngram\$1range field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-ngram_range).
+ **`datetime_parts`**  –   This field is used optionally by `datetime` features to specify which parts of the datetime value to encode categorically.

  See [The datetime\$1parts field](machine-learning-neptune_ml-features.md#machine-learning-neptune_ml-features-datetime_parts).

## Contents of a node label object listed in a node `labels` array
<a name="machine-learning-graph-node-labels-config"></a>

A label object listed in a node `labels` array defines a node target feature and specifies the proportions of nodes that the training, validation, and test stages will use. Each object can contain the following fields:

```
      {
        "label"      : ["(column label for the target feature property value)", "(task type)"],
        "split_rate" : [(training proportion), (validation proportion), (test proportion)],
        "custom_split_filenames" : {"train": "(training file name)", "valid": "(validation file name)", "test": "(test file name)"},
        "separator"  : "(separator character for node-classification category values)",
      }
```
+ **`label`**   –   A JSON array containing two strings. The first string contains the header name of the column that stores the property values for the feature. The second string specifies the target task type, which can be:
  + `"classification"`   –   A node classification task. The property values in the specified column are used to create a categorical feature.
  + `"regression"`   –   A node regression task. The property values in the specified column are used to create a numerical feature.
+ **`split_rate`**   –   A JSON array containing three numbers between zero and one that add up to one and represent an estimate of the proportions of nodes that the training, validation, and test stages will use, respectively. See [split\$1rate](machine-learning-neptune_ml-targets.md#machine-learning-property-graph-neptune_ml-targets-split_rate).
+ **`custom_split_filenames`**   –   A JSON object that specifies the file names for the files that define the training, validation and test populations. Either this field or `split_rate` can be defined, but not both. See [Custom train-validation-test proportions](#machine-learning-custom-stages-splits) for more information.
+ **`separator`**   –   A string containing the delimiter that separates categorical feature values for a classification task.

**Note**  
If no label object is provided for both edges and nodes, the task is automatically assumed to be link prediction, and edges are randomly split into 90% for training and 10% for validation.

## Custom train-validation-test proportions
<a name="machine-learning-custom-stages-splits"></a>

By default, the `split_rate` parameter is used by Neptune ML to split the graph randomly into training, validation and test populations using the proportions defined in this parameter. To have more precise control over which entities are used in these different populations, files can be created that explicitly define them, and then the [training data configuration file can be edited](machine-learning-processing-training-config-file.md) to map these indexing files to the populations. This mapping is specified by a JSON object for the [`custom_split_filesnames`](#custom_split_filenames) key in the training configuration file. If this option is used, filenames must be provided for the `train` and `validation` keys, and is optional for the `test` key.

The formatting of these files should match the [Gremlin data format](bulk-load-tutorial-format-gremlin.md#bulk-load-tutorial-format-gremlin-systemheaders). Specifically, for node-level tasks, each file should contain a column with the `~id` header that lists the node IDs, and for edge-level tasks, the files should specify `~from` and `~to` to indicate the source and destination nodes of the edges, respectively. These files need to be placed in the same Amazon S3 location as the exported data that is used for data processing (see: [`outputS3Path`](export-parameters.md#export-parameters-outputS3Path)).

For property classification or regression tasks, these files can optionally define the labels for the machine-learning task. In that case the files need to have a property column with the same header name as is [defined in the training data configuration file](#machine-learning-graph-node-labels-config). If property labels are defined in both the exported node and edge files and the custom-split files, priority is given to the custom-split files.

# Training a model using Neptune ML
<a name="machine-learning-on-graphs-model-training"></a>

After you have processed the data that you exported from Neptune for model training, you can start a model-training job using a command like the following:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your S3 bucket)/neptune-model-graph-autotrainer'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
      }'
```

------

The details of how to use this command are explained in [The modeltraining command](machine-learning-api-modeltraining.md), along with information about how to get the status of a running job, how to stop a running job, and how to list all running jobs.

You can also supply a `previousModelTrainingJobId` to use information from a completed Neptune ML model training job to accelerate the hyperparameter search in a new training job. This is useful during [model retraining on new graph data](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-model-retraining), as well as [incremental training on the same graph data](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-incremental). Use a command like this one:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your S3 bucket)/neptune-model-graph-autotrainer" \
  --previous-model-training-job-id "(the model-training job-id of a completed job)"
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your S3 bucket)/neptune-model-graph-autotrainer',
    previousModelTrainingJobId='(the model-training job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer",
        "previousModelTrainingJobId" : "(the model-training job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer",
        "previousModelTrainingJobId" : "(the model-training job-id of a completed job)"
      }'
```

------

You can train your own model implementation on the Neptune ML training infrastructure by supplying a `customModelTrainingParameters` object, like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer" \
  --model-name "custom" \
  --custom-model-training-parameters '{
    "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
    "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
    "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
  }'
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer',
    modelName='custom',
    customModelTrainingParameters={
        'sourceS3DirectoryPath': 's3://(your Amazon S3 bucket)/(path to your Python module)',
        'trainingEntryPointScript': '(your training script entry-point name in the Python module)',
        'transformEntryPointScript': '(your transform script entry-point name in the Python module)'
    }
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

------



See [The modeltraining command](machine-learning-api-modeltraining.md) for more information, such as about how to get the status of a running job, how to stop a running job, and how to list all running jobs. See [Custom models in Neptune ML](machine-learning-custom-models.md) for information about how to implement and use a custom model.

**Topics**
+ [

# Models and model training in Amazon Neptune ML
](machine-learning-models-and-training.md)
+ [

# Customizing model hyperparameter configurations in Neptune ML
](machine-learning-customizing-hyperparams.md)
+ [

# Model training best practices
](machine-learning-improve-model-performance.md)

# Models and model training in Amazon Neptune ML
<a name="machine-learning-models-and-training"></a>

Neptune ML uses Graph Neural Networks (GNN) to create models for the various machine-learning tasks. Graph neural networks have been shown to obtain state-of-the-art results for graph machine learning tasks and are excellent at extracting informative patterns from graph structured data.

## Graph neural networks (GNNs) in Neptune ML
<a name="machine-learning-gnns"></a>

Graph Neural Networks (GNNs) belong to a family of neural networks that compute node representations by taking into account the structure and features of nearby nodes. GNNs complement other traditional machine learning and neural network methods that are not well-suited for graph data.

GNNs are used to solve machine-learning tasks such as node classification and regression (predicting properties of nodes) and edge classification and regression (predicting properties of edges) or link prediction (predicting whether two nodes in the graph should be connected or not).

In general, using a GNN for a machine learning task involves two stages:
+ An encoding stage, where the GNN computes a d-dimensional vector for each node in the graph. These vectors are also called *representations* or *embeddings*. 
+ A decoding stage, which makes predictions based on the encoded representations.

For node classification and regression, the node representations are used directly for the classification and regression tasks. For edge classification and regression, the node representations of the incident nodes on an edge are used as input for the classification or regression. For link prediction, an edge likelihood score is computed by using a pair of node representations and an edge type representation.

The [Deep Graph Library (DGL)](https://www.dgl.ai/) facilitates the efficient definition and training of GNNs for these tasks.

Different GNN models are unified under the formulation of message passing. In this view, the representation for a node in a graph is calculated using the node's neighbors' representations (the messages), together with the node's initial representation. In NeptuneML, the initial representation of a node is derived from the features extracted from its node properties, or is learnable and depends on the identity of the node.

Neptune ML also provides the option to concatenate node features and learnable node representations to serve as the original node representation.

For the various tasks in Neptune ML involving graphs with node properties, we use the [Relational Graph Convolutional Network](https://arxiv.org/abs/1703.06103) (R-GCN)) to perform the encoding stage. R-GCN is a GNN architecture that is well-suited for graphs that have multiple node and edge types (these are known as heterogeneous graphs).

The R-GCN network consists of a fixed number of layers, stacked one after the other. Each layer of the R-GCN uses its learnable model parameters to aggregate information from the immediate, 1-hop neighborhood of a node. Since subsequent layers use the previous layer's output representations as input, the radius of the graph neighborhood that influences a node's final embedding depends on the number of layers (`num-layer`), of the R-GCN network.

For example, this means that a 2-layer network uses information from nodes that are 2 hops away.

To learn more about GNNs, see [A Comprehensive Survey on Graph Neural Networks](https://arxiv.org/abs/1901.00596). For more information about the Deep Graph Library (DGL), visit the DGL [webpage](https://www.dgl.ai/). For a hands-on tutorial about using DGL with GNNs, see [Learning graph neural networks with Deep Graph Library](https://www.amazon.science/videos-webinars/learning-graph-neural-networks-with-deep-graph-library).

## Training Graph Neural Networks
<a name="machine-learning-gnn-training"></a>

In machine learning, the process of getting a model to learn how to make good predictions for a task is called model training. This is usually performed by specifying a particular objective to optimize, as well as an algorithm to use to perform this optimization.

This process is employed in training a GNN to learn good representations for the downstream task as well. We create an objective function for that task that is minimized during model training. For example, for node classification, we use [CrossEntropyLoss](https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html) as the objective, which penalizes misclassifications, and for node regression we minimize [MeanSquareError](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html).

The objective is usually a loss function that takes the model predictions for a particular data point and compares them to the ground-truth value for that data point. It returns the loss value, which shows how far off the model's predictions are. The goal of the training process is to minimize the loss and ensure that model predictions are close to the ground-truth.

The optimization algorithm used in deep learning for the training process is usually a variant of gradient descent. In Neptune ML, we use [Adam](https://arxiv.org/pdf/1412.6980.pdf), which is an algorithm for first-order gradient-based optimization of stochastic objective functions based on adaptive estimates of lower-order moments.

While the model training process tries to ensure that the learned model parameters are close to the minima of the objective function, the overall performance of a model also depends on the model's *hyperparameters*, which are model settings that aren't learned by the training algorithm. For example, the dimensionality of the learned node representation, `num-hidden`, is a hyperparameter that affects model performance. Therefore, it is common in machine learning to perform hyperparameter optimization (HPO) to choose the suitable hyperparameters.

Neptune ML uses a SageMaker AI hyperparameter tuning job to launch multiple instances of model training with different hyperparameter configurations to try to find the best model for a range of hyperparameters settings. See [Customizing model hyperparameter configurations in Neptune ML](machine-learning-customizing-hyperparams.md).

## Knowledge graph embedding models in Neptune ML
<a name="machine-learning-kg-embedding"></a>

Knowledge graphs (KGs) are graphs that encode information about different entities (nodes) and their relations (edges). In Neptune ML, knowledge graph embedding models are applied by default for performing link prediction when the graph does not contain node properties, only relations with other nodes. Although, R-GCN models with learnable embeddings can also be used for these graphs by specifying the model type as `"rgcn"`, knowledge graph embedding models are simpler and are designed to be effective for learning representations for large scale knowledge graphs.

Knowledge graph embedding models are used in a link prediction task to predict the nodes or relations that complete a triple `(h, r, t)` where `h` is the source node, `r` is the relation type and `t` is the destination node.

The knowledge graph embedding models implemented in Neptune ML are `distmult`, `transE`, and `rotatE`. To learn more about knowledge graph embedding models, see [DGL-KE](https://github.com/awslabs/dgl-ke).

## Training custom models in Neptune ML
<a name="machine-learning-training-custom-models"></a>

Neptune ML lets you define and implement custom models of your own, for particular scenarios. See [Custom models in Neptune ML](machine-learning-custom-models.md) for information about how to implement a custom model and how to use Neptune ML infrastructure to train it.

# Customizing model hyperparameter configurations in Neptune ML
<a name="machine-learning-customizing-hyperparams"></a>

When you start a Neptune ML model-training job, Neptune ML automatically uses the information inferred from the preceding [data-processing](machine-learning-on-graphs-processing.md) job. It uses the information to generate hyperparameter configuration ranges that are used to create a [SageMaker AI hyperparameter tuning job](https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning-how-it-works.html) to train multiple models for your task. That way, you don’t have to specify a long list of hyperparameter values for the models to be trained with. Instead, the model hyperparameter ranges and defaults are selected based on the task type, graph type, and the tuning-job settings.

However, you can also override the default hyperparameter configuration and provide custom hyperparameters by modifying a JSON configuration file that the data-processing job generates.

Using the Neptune ML [modelTraining API](machine-learning-api-modeltraining.md), you can control several high level hyperparameter tuning job settings like `maxHPONumberOfTrainingJobs`, `maxHPOParallelTrainingJobs`, and `trainingInstanceType`. For more fine-grained control over the model hyperparameters, you can customize the `model-HPO-configuration.json` file that the data-processing job generates. The file is saved in the Amazon S3 location that you specified for processing-job output.

You can download the file, edit it to override the default hyperparameter configurations, and upload it back to the same Amazon S3 location. Do not change the name of the file, and be careful to follow these instructions as you edit.

To download the file from Amazon S3:

```
aws s3 cp \
  s3://(bucket name)/(path to output folder)/model-HPO-configuration.json \
  ./
```

When you have finished editing, upload the file back to where it was:

```
aws s3 cp \
  model-HPO-configuration.json \
  s3://(bucket name)/(path to output folder)/model-HPO-configuration.json
```

## Structure of the `model-HPO-configuration.json` file
<a name="machine-learning-hyperparams-file-structure"></a>

The `model-HPO-configuration.json` file specifies the model to be trained, the machine learning `task_type` and the hyperparameters that should be varied or fixed for the various runs of model training.

The hyperparameters are categorized as belonging to various tiers that signify the precedence given to the hyperparameters when the hyperparameter tuning job is invoked:
+ Tier-1 hyperparameters have the highest precedence. If you set `maxHPONumberOfTrainingJobs` to a value less than 10, only Tier-1 hyperparameters are tuned, and the rest take their default values.
+ Tier-2 hyperparameters have lower precedence, so if you have more than 10 but less than 50 total training jobs for a tuning job, then both Tier-1 and Tier-2 hyperparameters are tuned.
+ Tier 3 hyperparameters are tuned together with Tier-1 and Tier-2 only if you have more than 50 total training jobs.
+ Finally, fixed hyperparameters are not tuned at all, and always take their default values.

### Example of a `model-HPO-configuration.json` file
<a name="machine-learning-hyperparams-file-sample"></a>

The following is a sample `model-HPO-configuration.json` file:

```
{
  "models": [
    {
      "model": "rgcn",
      "task_type": "node_class",
      "eval_metric": {
        "metric": "acc"
      },
      "eval_frequency": {
          "type":  "evaluate_every_epoch",
          "value":  1
      },
      "1-tier-param": [
        {
            "param": "num-hidden",
            "range": [16, 128],
            "type": "int",
            "inc_strategy": "power2"
        },
        {
          "param": "num-epochs",
          "range": [3,30],
          "inc_strategy": "linear",
          "inc_val": 1,
          "type": "int",
          "node_strategy": "perM"
        },
        {
          "param": "lr",
          "range": [0.001,0.01],
          "type": "float",
          "inc_strategy": "log"
        }
      ],
      "2-tier-param": [
        {
          "param": "dropout",
          "range": [0.0,0.5],
          "inc_strategy": "linear",
          "type": "float",
          "default": 0.3
        },
        {
          "param": "layer-norm",
          "type": "bool",
          "default": true
        }
      ],
      "3-tier-param": [
        {
          "param": "batch-size",
          "range": [128, 4096],
          "inc_strategy": "power2",
          "type": "int",
          "default": 1024
        },
        {
          "param": "fanout",
          "type": "int",
          "options": [[10, 30],[15, 30], [15, 30]],
          "default": [10, 15, 15]
        },
        {
          "param": "num-layer",
          "range": [1, 3],
          "inc_strategy": "linear",
          "inc_val": 1,
          "type": "int",
          "default": 2
        },
        {
          "param": "num-bases",
          "range": [0, 8],
          "inc_strategy": "linear",
          "inc_val": 2,
          "type": "int",
          "default": 0
        }
      ],
      "fixed-param": [
        {
          "param": "concat-node-embed",
          "type": "bool",
          "default": true
        },
        {
          "param": "use-self-loop",
          "type": "bool",
          "default": true
        },
        {
          "param": "low-mem",
          "type": "bool",
          "default": true
        },
        {
          "param": "l2norm",
          "type": "float",
          "default": 0
        }
      ]
    }
  ]
}
```

### Elements of a `model-HPO-configuration.json` file
<a name="machine-learning-hyperparams-file-elements"></a>

The file contains a JSON object with a single top-level array named `models` that contains a single model-configuration object. When customizing the file, make sure the `models` array only has one model-configuration object in it. If your file contains more than one model-configuration object, the tuning job will fail with a warning.

The model-configuration object contains the following top-level elements:
+ **`model`**   –   (*String*) The model type to be trained (**do not modify**). Valid values are:
  + `"rgcn"`   –   This is the default for node classification and regression tasks, and for heterogeneous link prediction tasks.
  + `"transe"`   –   This is the default for KGE link prediction tasks.
  + `"distmult"`   –   This is an alternative model type for KGE link prediction tasks.
  + `"rotate"`   –   This is an alternative model type for KGE link prediction tasks.

  As a rule, don't directly modify the `model` value, because different model types often have substantially different applicable hyperparameters, which can result in a parsing error after the training job has started.

  To change the model type, use the `modelName` parameter in the [modelTraining API](machine-learning-api-modeltraining.md#machine-learning-api-modeltraining-create-job) rather than change it in the `model-HPO-configuration.json` file.

  A way to change the model type and make fine-grain hyperparameter changes is to copy the default model configuration template for the model that you want to use and paste that into the `model-HPO-configuration.json` file. There is a folder named `hpo-configuration-templates` in the same Amazon S3 location as the `model-HPO-configuration.json` file if the inferred task type supports multiple models. This folder contains all the default hyperparameter configurations for the other models that are applicable to the task.

  For example, if you want to change the model and hyperparameter configurations for a `KGE` link-prediction task from the default `transe` model to a `distmult` model, simply paste the contents of the `hpo-configuration-templates/distmult.json` file into the `model-HPO-configuration.json` file and then edit the hyperparameters as necessary.
**Note**  
If you set the `modelName` parameter in the `modelTraining` API and also change the `model` and hyperparameter specification in the `model-HPO-configuration.json` file, and these are different, the `model` value in the `model-HPO-configuration.json` file takes precedence, and the `modelName` value is ignored.
+ **`task_type`**   –   (*String*) The machine learning task type inferred by or passed directly to the data-processing job (**do not modify**). Valid values are:
  + `"node_class"`
  + `"node_regression"`
  + `"link_prediction"`

  The data-processing job infers the task type by examining the exported dataset and the generated training-job configuration file for properties of the dataset.

  This value should not be changed. If you want to train a different task, you need to [run a new data-processing job](machine-learning-on-graphs-processing.md). If the `task_type` value is not what you were expecting, you should check the inputs to your data-processing job to make sure that they are correct. This includes parameters to the `modelTraining` API, as well as in the training-job configuration file generated by the data-export process.
+ **`eval_metric`**   –   (*String*) The evaluation metric should be used for evaluating the model performance and for selecting the best-performing model across HPO runs. Valid values are:
  + `"acc"`   –   Standard classification accuracy. This is the default for single-label classification tasks, unless imbalanced labels are found during data processing, in which case the default is `"F1"`.
  + `"acc_topk"`   –   The number of times the correct label is among the top **`k`** predictions. You can also set the value **`k`** by passing in `topk` as an extra key.
  + `"F1"`   –   The [F1 score](https://en.wikipedia.org/wiki/F-score).
  + `"mse"`   –   [Mean-squared error metric](https://en.wikipedia.org/wiki/Mean_squared_error), for regression tasks.
  + `"mrr"`   –   [Mean reciprocal rank metric](https://en.wikipedia.org/wiki/Mean_reciprocal_rank).
  + `"precision"`   –   The model precision, calculated as the ratio of true positives to predicted positives: `= true-positives / (true-positives + false-positives)`.
  + `"recall"`   –   The model recall, calculated as the ratio of true positives to actual positives: `= true-positives / (true-positives + false-negatives)`.
  + `"roc_auc"`   –   The area under the [ROC curve](https://en.wikipedia.org/wiki/Receiver_operating_characteristic). This is the default for multi-label classification.

  For example, to change the metric to `F1`, change the `eval_metric` value as follows:

  ```
  "  eval_metric": {
      "metric": "F1",
    },
  ```

  Or, to change the metric to a `topk` accuracy score, you would change `eval_metric` as follows:

  ```
    "eval_metric": {
      "metric": "acc_topk",
      "topk": 2
    },
  ```
+ **`eval_frequency`**   –   (*Object*) Specifies how often during training the performance of the model on the validation set should be checked. Based on the validation performance, early stopping can then be initiated and the best model can be saved.

  The `eval_frequency` object contains two elements, namely `"type"` and `"value"`. For example:

  ```
    "eval_frequency": {
      "type":  "evaluate_every_pct",
      "value":  0.1
    },
  ```

  Valid `type` values are:
  + **`evaluate_every_pct`**   –   Specifies the percentage of training to be completed for each evaluation.

    For `evaluate_every_pct`, the `"value"` field contains a floating-point number between zero and one which expresses that percentage.

    
  + **`evaluate_every_batch`**   –   Specifies the number of training batches to be completed for each evaluation.

    For `evaluate_every_batch`, the `"value"` field contains an integer which expresses that batch count.
  + **`evaluate_every_epoch`**   –   Specifies the number of epochs per evaluation, where a new epoch starts at midnight.

    For `evaluate_every_epoch`, the `"value"` field contains an integer which expresses that epoch count.

  The default setting for `eval_frequency` is:

  ```
    "eval_frequency": {
      "type":  "evaluate_every_epoch",
      "value":  1
    },
  ```
+ **`1-tier-param`**   –   (*Required*) An array of Tier-1 hyperparameters.

  If you don't want to tune any hyperparameters, you can set this to an empty array. This does not affect the total number of training jobs launched by the SageMaker AI hyperparameter tuning job. It just means that all training jobs, if there is more than 1 but less than 10, will run with the same set of hyperparameters.

  On the other hand, if you want to treat all your tunable hyperparameters with equal significance then you can put all the hyperparameters in this array.
+ **`2-tier-param`**   –   (*Required*) An array of Tier-2 hyperparameters.

  These parameters are only tuned if `maxHPONumberOfTrainingJobs` has a value greater than 10. Otherwise, they are fixed to the default values.

  If you have a training budget of at most 10 training jobs or don't want Tier-2 hyperparameters for any other reason, but you want to tune all tunable hyperparameters, you can set this to an empty array.
+ **`3-tier-param`**   –   (*Required*) An array of Tier-3 hyperparameters.

  These parameters are only tuned if `maxHPONumberOfTrainingJobs` has a value greater than 50. Otherwise, they are fixed to the default values.

  If you don't want Tier-3 hyperparameters, you can set this to an empty array.
+ **`fixed-param`**   –   (*Required*) An array of fixed hyperparameters that take only their default values and do not vary in different training jobs.

  If you want to vary all hyperparameters, you can set this to an empty array and either set the value for `maxHPONumberOfTrainingJobs` large enough to vary all tiers or make all hyperparameters Tier-1.

The JSON object that represents each hyperparameter in `1-tier-param`, `2-tier-param`, `3-tier-param`, and `fixed-param` contains the following elements:
+ **`param`**   –   (*String*) The name of the hyperparameter (**do not change**).

  See the [list of valid hyperparameter names in Neptune ML](#machine-learning-hyperparams-list).
+ **`type`**   –   (*String*) The hyperparameter type (**do not change**).

  Valid types are: `bool`, `int`, and `float`.
+ **`default`**   –   (*String*) The default value for the hyperparameter.

  You can set a new default value.

Tunable hyperparameters can also contain the following elements:
+ **`range`**   –   (*Array*) The range for a continuous tunable hyperparameter.

  This should be an array with two values, namely the minimum and maximum of the range (`[min, max]`).
+ **`options`**   –   (*Array*) The options for a categorical tunable hyperparameter.

  This array should contain all the options to consider:

  ```
    "options" : [value1, value2, ... valuen]
  ```
+ **`inc_strategy`**   –   (*String*) The type of incremental change for continuous tunable hyperparameter ranges (**do not change**).

  Valid values are `log`, `linear`, and `power2`. This applies only when the range key is set.

  Modifying this may result in not using the full range of your hyperparameter for tuning.
+ **`inc_val`**   –   (*Float*) The amount by which successive increments differ for continuous tunablehyperparameters (**do not change**).

  This applies only when the range key is set.

  Modifying this may result in not using the full range of your hyperparameter for tuning.
+ **`node_strategy`**   –   (*String*) Indicates that the effective range for this hyperparameter should change based on the number of nodes in the graph (**do not change**).

  Valid values are `"perM"` (per million), `"per10M"` (per 10 million), and `"per100M"` (per 100 million).

  Rather than change this value, change the `range` instead.
+ **`edge_strategy`**   –   (*String*) Indicates that the effective range for this hyperparameter should change based on the number of edges in the graph (**do not change**).

  Valid values are `"perM"` (per million), `"per10M"` (per 10 million), and `"per100M"` (per 100 million).

  Rather than change this value, change the `range` instead.

### List of all the hyperparameters in Neptune ML
<a name="machine-learning-hyperparams-list"></a>

The following list contains all the hyperparameters that can be set anywhere in Neptune ML, for any model type and task. Because they are not all applicable to every model type, it is important that you only set hyperparameters in the `model-HPO-configuration.json` file that appear in the template for the model you're using.
+ **`batch-size`**   –   The size of the batch of target nodes using in one forward pass. *Type*: `int`.

  Setting this to a much larger value can cause memory issues for training on GPU instances.
+ **`concat-node-embed`**   –   Indicates whether to get the initial representation of a node by concatenating its processed features with learnable initial node embeddings in order to increase the expressivity of the model. *Type*: `bool`.
+ **`dropout`**   –   The dropout probability applied to dropout layers. *Type*: `float`.

  
+ **`edge-num-hidden`**   –   The hidden layer size or number of units for the edge feature module. Only used when `use-edge-features` is set to `True`. *Type*: float.
+ **`enable-early-stop`**   –   Toggles whether or not to use the early stopping feature. *Type*: `bool`. *Default*: `true`.

  Use this Boolean parameter to turn off the early stop feature.
+ **`fanout`**   –   The number of neighbors to sample for a target node during neighbor sampling. *Type*: `int`.

  This value is tightly coupled with `num-layers` and should always be in the same hyperparameter tier. This is because you can specify a fanout for each potential GNN layer.

  Because this hyperparameter can cause model performance to vary widely, it should be fixed or set as a Tier-2 or Tier-3 hyperparameter. Setting it to a large value can cause memory issues for training on GPU instance.
+ **`gamma`**   –   The margin value in the score function. *Type*: `float`.

  This applies to `KGE` link-prediction models only.
+ **`l2norm`**   –   The weight decay value used in the optimizer which imposes an L2 normalization penalty on the weights. *Type*: `bool`.
+ **`layer-norm`**   –   Indicates whether to use layer normalization for `rgcn` models. *Type*: `bool`.
+ **`low-mem`**   –   Indicates whether to use a low-memory implementation of the relation message passing function at the expense of speed. *Type*: `bool`.

  
+ **`lr`**   –   The learning rate. *Type*: `float`.

  This should be set as a Tier-1 hyperparameter.
+ **`neg-share`**   –   In link prediction, indicates whether positive sampled edges can share negative edge samples. *Type*: `bool`.
+ **`num-bases`**   –   The number of bases for basis decomposition in a `rgcn` model. Using a value of `num-bases` that is less than the number of edge types in the graph acts as a regularizer for the `rgcn` model. *Type*: `int`.
+ **`num-epochs`**   –   The number of epochs of training to run. *Type*: `int`.

  An epoch is a complete training pass through the graph.
+ **`num-hidden`**   –   The hidden layer size or number of units. *Type*: `int`.

  This also sets the initial embedding size for featureless nodes.

  Setting this to a much larger value without reducing `batch-size` can cause out-of-memory issues for training on GPU instance.
+ **`num-layer`**   –   The number of GNN layers in the model. *Type*: `int`.

  This value is tightly coupled with the fanout parameter and should come after fanout is set in the same hyperparameter tier.

  Because this can cause model performance to vary widely, it should be fixed or set as a Tier-2 or Tier-3 hyperparameter.
+ **`num-negs`**   –   In link prediction, the number of negative samples per positive sample. *Type*: `int`.
+ **`per-feat-name-embed`**   –   Indicates whether to embed each feature by independently transforming it before combining features. *Type*: `bool`.

  When set to `true`, each feature per node is independently transformed to a fixed dimension size before all the transformed features for the node are concatenated and further transformed to the `num_hidden` dimension.

  When set to `false`, the features are concatenated without any feature-specific transformations.
+ **`regularization-coef`**   –   In link prediction, the coefficient of regularization loss. *Type*: `float`.
+ **`rel-part`**   –   Indicates whether to use relation partition for `KGE` link prediction. *Type*: `bool`.
+ **`sparse-lr`**   –   The learning rate for learnable-node embeddings. *Type*: `float`.

  Learnable initial node embeddings are used for nodes without features or when `concat-node-embed` is set. The parameters of the sparse learnable node embedding layer are trained using a separate optimizer which can have a separate learning rate.
+ **`use-class-weight`**   –   Indicates whether to apply class weights for imbalanced classification tasks. If set to to `true`, the label counts are used to set a weight for each class label. *Type*: `bool`.
+ **`use-edge-features`**   –   Indicates whether to use edge features during message passing. If set to `true`, a custom edge feature module is added to the RGCN layer for edge types that have features. *Type*: `bool`.
+ **`use-self-loop`**   –   Indicates whether to include self loops in training a `rgcn` model. *Type*: `bool`.
+ **`window-for-early-stop`**   –   Controls the number of latest validation scores to average to decide on an early stop. The default is 3. type=int. See also [Early stopping of the model training process in Neptune ML](machine-learning-improve-model-performance.md#machine-learning-model-training-early-stop). *Type*: `int`. *Default*: `3`.

  See .

## Customizing hyperparameters in Neptune ML
<a name="machine-learning-hyperparams-editing"></a>

When you are editing the `model-HPO-configuration.json` file, the following are the most common kinds of changes to make:
+ Edit the minimum and/or maximum values of `range` hyperparameters.
+ Set a hyperparameter to a fixed value by moving it to the `fixed-param` section and setting its default value to the fixed value you want it to take.
+ Change the priority of a hyperparameter by placing it in a particular tier, editing its range, and making sure that its default value is set appropriately.

# Model training best practices
<a name="machine-learning-improve-model-performance"></a>

There are things you can do to improve the performance of Neptune ML models.

## Choose the right node property
<a name="machine-learning-before-exporting-data-choose-property"></a>

Not all the properties in your graph may be meaningful or relevant to your machine learning tasks. Any irrelevant properties should be excluded during data export.

Here are some best practices:
+ Use domain experts to help evaluate the importance of features and the feasibility of using them for predictions.
+ Remove the features that you determine are redundant or irrelevant to reduce noise in the data and unimportant correlations.
+ Iterate as you build your model. Adjust the features, feature combinations, and tuning objectives as you go along.

[Feature Processing](https://docs.aws.amazon.com/machine-learning/latest/dg/feature-processing.html) in the Amazon Machine Learning Developer Guide provides additional guidelines for feature processing that are relevant to Neptune ML.

## Handle outlier data points
<a name="machine-learning-before-exporting-data-outliers"></a>

An outlier is a data point that is significantly different from the remaining data. Data outliers can spoil or mislead the training process, resulting in longer training time or less accurate models. Unless they are truly important, you should eliminate outliers before exporting the data.

## Remove duplicate nodes and edges
<a name="machine-learning-before-exporting-data-remove-duplicates"></a>

Graphs stored in Neptune may have duplicate nodes or edges. These redundant elements will introduce noise for ML model training. Eliminate duplicate nodes or edges before exporting the data.

## Tune the graph structure
<a name="machine-learning-before-exporting-data-tune-graph"></a>

When the graph is exported, you can change the way features are processed and how the graph is constructed, to improve the model performance.

Here are some best practices:
+ When an edge property has the meaning of categories of edges, it is worth turning it into edge types in some cases.
+ The default normalization policy used for a numerical property is `min-max`, but in some cases other normalization policies work better. You can preprocess the property and change the normalization policy as explained in [Elements of a `model-HPO-configuration.json` file](machine-learning-customizing-hyperparams.md#machine-learning-hyperparams-file-elements).
+ The export process automatically generates feature types based on property types. For example, it treats `String` properties as categorical features and `Float` and `Int` properties as numerical features. If you need to, you can modify the feature type after export (see [Elements of a `model-HPO-configuration.json` file](machine-learning-customizing-hyperparams.md#machine-learning-hyperparams-file-elements)).

## Tune the hyperparameter ranges and defaults
<a name="machine-learning-before-exporting-data-change-hpo"></a>

The data-processing operation infers hyperparameter configuration ranges from the graph. If the generated model hyperparameter ranges and defaults don't work well for your graph data, you can edit the HPO configuration file to create your own hyperparameter tuning strategy.

Here are some best practices:
+ When the graph goes large, the default hidden dimension size may not be large enough to contain all the information. You can change the `num-hidden` hyperparameter to control the hidden dimension size.
+ For knowledge graph embedding (KGE) models, you may want to change the specific model being used according to your graph structure and budget.

  `TrainsE` models have difficulty in dealing with one-to-many (1-N), many-to-one (N-1), and many-to-many (N-N) relations. `DistMult` models have difficulty in dealing with symmetric relations. `RotatE` is good at modeling all kinds of relations but is more expensive than `TrainsE` and `DistMult` during training.
+ In some cases, when both node identification and node feature information are important, you should use ``concat-node-embed`` to tell the Neptune ML model to get the initial representation of a node by concatenating its features with its initial embeddings.
+ When you are getting reasonably good performance over some hyperparameters, you can adjust the hyperparameter search space according to those results.

## Early stopping of the model training process in Neptune ML
<a name="machine-learning-model-training-early-stop"></a>

Early stopping can significantly reduce the model-training run time and associated costs without degrading model performance. It also prevent the model from overfitting on the training data.

Early stopping depends on regular measurements of validation-set performance. Initially, performance improves as training proceeds, but when the model starts overfitting, it starts to decline again. The early stopping feature identifies the point at which the model starts overfitting and halts model training at that point.

Neptune ML monitors the validation metric calls and compares the most recent validation metric to the average of validation metrics over the last **`n`** evaluations, where **`n`** is a number set using the `window-for-early-stop` parameter. As soon as the validation metric is worse than that average, Neptune ML stops the model training and saves the best model so far. 

You can control early stopping using the following parameters:
+ **`window-for-early-stop`**   –   The value of this parameter is an integer that specifies the number of recent validation scores to average when deciding on an early stop. The default value is `3`.
+ **`enable-early-stop`**   –   Use this Boolean parameter to turn off the early stop feature. By default, its value is `true`.

## Early stopping of the HPO process in Neptune ML
<a name="machine-learning-HPO-early-stop"></a>

The early stop feature in Neptune ML also stops training jobs that are not performing well compared to other training jobs, using the SageMaker AI HPO warm-start feature. This too can reduce costs and improve the quality of HPO.

See [Run a warm start hyperparameter tuning job](https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning-warm-start.html) for a description of how this works.

Warm start provides the ability to pass information learned from previous training jobs to subsequent training jobs and provides two distinct benefits:
+ First, the results of previous training jobs are used to select good combinations of hyperparameters to search over in the new tuning job.
+ Second, it allows early stopping to access more model runs, which reduces tuning time.

This feature is enabled automatically in Neptune ML, and allows you strike a balance between model training time and performance. If you are satisfied with the performance of the current model, you can use that model. Otherwise, you run more HPOs that are warm-started with the results of previous runs so as to discover a better model.

## Get professional support services
<a name="machine-learning-before-exporting-data-get-support"></a>

AWS offers professional support services to help you with problems in your machine learning on Neptune projects. If you get stuck, reach out to [AWS support](https://aws.amazon.com/premiumsupport/).

# Use a trained model to generate new model artifacts
<a name="machine-learning-model-transform"></a>

Using the Neptune ML model transform command, you can compute model artifacts like node embeddings on processed graph data using pre-trained model parameters.

## Model transform for incremental inference
<a name="machine-learning-model-transform-incremental"></a>

In the [incremental model inference workflow](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-incremental), after you have processed the updated graph data that you exported from Neptune you can start a model transform job using a command like the following:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --ml-model-training-job-id "(the ML model training job-id)" \
  --model-transform-output-s3-location "s3://(your S3 bucket)/neptune-model-transform/"
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    mlModelTrainingJobId='(the ML model training job-id)',
    modelTransformOutputS3Location='s3://(your S3 bucket)/neptune-model-transform/'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "mlModelTrainingJobId": "(the ML model training job-id)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform/"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "mlModelTrainingJobId": "(the ML model training job-id)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform/"
      }'
```

------

You can then pass the ID of this job to the create-endpoints API call to create a new endpoint or update an existing one with the new model artifacts generated by this job. This allows the new or updated endpoint to provide model predictions for the updated graph data.

## Model transform for any training job
<a name="machine-learning-model-transform-any-job"></a>

You can also supply a `trainingJobName` parameter to generate model artifacts for any of the SageMaker AI training jobs launched during Neptune ML model training. Since a Neptune ML model training job can potentially launch many SageMaker AI training jobs, this gives you the flexibility to create an inference endpoint based on any of those SageMaker AI training jobs.

For example:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --training-job-name "(name of a completed SageMaker training job)" \
  --model-transform-output-s3-location "s3://(your S3 bucket)/neptune-model-transform/"
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    trainingJobName='(name of a completed SageMaker training job)',
    modelTransformOutputS3Location='s3://(your S3 bucket)/neptune-model-transform/'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform/"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform/"
      }'
```

------

If the original training job was for a user-provided custom model, you must include a `customModelTransformParameters` object when invoking a model transform. See [Custom models in Neptune ML](machine-learning-custom-models.md) for information about how to implement and use a custom model.

**Note**  
The `modeltransform` command always runs the model transform on the best SageMaker AI training job for that training.

See [The modeltransform command](machine-learning-api-modeltransform.md) for more information about model transform jobs.

# Artifacts produced by model training in Neptune ML
<a name="machine-learning-model-artifacts"></a>

After model training, Neptune ML uses the best trained model parameters to generate model artifacts that are necessary for launching the inference endpoint and providing model predictions. These artifacts are packaged by the training job and stored in the Amazon S3 output location of the best SageMaker AI training job.

The following sections describe what is included in the model artifacts for the various tasks, and how the model transform command uses a pre-existing trained model to generate artifacts even on new graph data.

## Artifacts generated for different tasks
<a name="machine-learning-task-artifacts"></a>

The content of the model artifacts generated by the training process depends on the target machine learning task:

****
+ **Node classification and regression**   –   For node property prediction, the artifacts include model parameters, node embeddings from the [GNN encoder](machine-learning-models-and-training.md#machine-learning-gnns), model predictions for nodes in the training graph, and some configuration files for the inference endpoint. In node classification and node regression tasks, model predictions are pre-computed for nodes present during training to reduce query latency.
+ **Edge classification and regression**   –   For edge property prediction, the artifacts also include model parameters and node embeddings. The parameters of the model decoder are especially important for inference because we compute the edge classification or edge regression predictions by applying the model decoder to the embeddings of the source and destination vertex of an edge.
+ **Link prediction**   –   For link prediction, in addition to the artifacts generated for edge property prediction, the DGL graph is also included as an artifact because link prediction requires the training graph to perform predictions. The objective of link prediction is to predict the destination vertices that are likely to combine with a source vertex to form an edge of a particular type in the graph. In order to do this, the node embedding of the source vertex and a learned representation for the edge type are combined with the node embeddings of all possible destination vertices to produce an edge likelihood score for each of the destination vertices. The scores are then sorted to rank the potential destination vertices and return the top candidates.

For each of the task types, the Graph Neural Network model weights from DGL are saved in the model artifact. This allows Neptune ML to compute fresh model outputs as the graph changes (*inductive* inference), in addition to using pre-computed predictions and embeddings (*transductive* inference) to reduce latency.

## Generating new model artifacts
<a name="machine-learning-task-artifacts"></a>

The model artifacts generated after model training in Neptune ML are directly tied to the training process. This means that the pre-computed embeddings and predictions only exist for entities that were in the original training graph. Although inductive inference mode for Neptune ML endpoints can compute predictions for new entities in real-time, you may want to generate batch predictions on new entities without querying an endpoint.

In order to get batch model predictions for new entities that have been added to the graph, new model artifacts need to be recomputed for the new graph data. This is accomplished using the `modeltransform` command. You use the `modeltransform` command when you only want batch predictions without setting up an endpoint, or when you want all the predictions generated so that you can write them back to the graph.

Since model training implicitly performs a model transform at the end of the training process, model artifacts are always recomputed on the training graph data by a training job. However, the `modeltransform` command can also compute model artifacts on graph data that was not used for training a model. In order to this, the new graph data must be processed using the same feature encodings as the original graph data and must adhere to the same graph schema.

You can accomplish this by first creating a new data processing job that is a clone of the data processing job run on the original training graph data, and running it on the new graph data (see [Processing updated graph data for Neptune ML](machine-learning-on-graphs-processing.md#machine-learning-on-graphs-processing-updated)). Then, call the `modeltransform` command with the new `dataProcessingJobId` and the old `modelTrainingJobId` to recompute the model artifacts on the updated graph data.

For node property prediction, the node embeddings and predictions are recomputed on the new graph data, even for nodes that were present in the original training graph.

For edge property prediction and link prediction, the node embeddings are also recomputed and similarly override any existing node embeddings. To recompute the node embeddings, Neptune ML applies the learned GNN encoder from the previous trained model to the nodes of the new graph data with their new features.

For nodes that do not have features, the learned initial representations from the original model training are re-used. For new nodes that do not have features and were not present in the original training graph, Neptune ML initializes their representation asthe average of the learned initial node representations of that node type present in the original training graph. This can cause some performance drop in model predictions if you have many new nodes that do not have features, since they will all be initialized to the average initial embedding for that node type.

If your model is trained with `concat-node-embed` set to true, then the initial node representations are created by concatenating the node features with the learnable initial representation. Thus, for the updated graph, the initial node representation of new nodes also uses the average initial node embeddings, concatenated with new node features.

Additionally, node deletions are currently not supported. If nodes have been removed in the updated graph, you have to retrain the model on the updated graph data.

Recomputing the model artifacts re-uses the learned model parameters on a new graph, and should only be done when the new graph is very similar to the old graph. If your new graph is not sufficiently similar, you need to retrain the model to obtain similar model performance on the new graph data. What constitutes sufficiently similar depends on the structure of your graph data, but as a rule of thumb you should retrain your model if your new data is more than 10-20% different from the original training graph data.

For graphs where all the nodes have features, the higher end of the threshold (20% different) applies but for graphs where many nodes do not have features and the new nodes added to the graph don’t have properties, then the lower end (10% different) may be even be too high.

See [The modeltransform command](machine-learning-api-modeltransform.md) for more information about model transform jobs.

# Custom models in Neptune ML
<a name="machine-learning-custom-models"></a>

**Note**  
Neptune ML custom model support relies on an older version of Python 3. To create and run custom GNN models with up-to-date dependencies use [GraphStorm on SageMaker](https://graphstorm.readthedocs.io/en/v0.3.1/cli/model-training-inference/distributed/sagemaker.html).  
[Real-time inductive inference](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference) is not currently supported for custom models.

Neptune ML lets you define your own custom model implementations using Python. You can train and deploy custom models using Neptune ML infrastructure very much as you do for the built-in models, and use them to obtain predictions through graph queries.

You can start implementing a custom model of your own in Python by following the [Neptune ML toolkit examples](https://github.com/awslabs/neptuneml-toolkit/tree/main/examples/custom-models/), and by using the model components provided in the Neptune ML toolkit. The following sections provide more details.

**Contents**
+ [

# Overview of custom models in Neptune ML
](machine-learning-custom-model-overview.md)
  + [

## When to use a custom model in Neptune ML
](machine-learning-custom-model-overview.md#machine-learning-custom-models-when-to-use)
  + [

## Workflow for developing and using a custom model in Neptune ML
](machine-learning-custom-model-overview.md#machine-learning-custom-model-workflow)
+ [

# Custom model development in Neptune ML
](machine-learning-custom-model-development.md)
  + [

## Custom model training script development in Neptune ML
](machine-learning-custom-model-development.md#machine-learning-custom-model-training-script)
  + [

## Custom model transform script development in Neptune ML
](machine-learning-custom-model-development.md#machine-learning-custom-model-transform-script)
  + [

## Custom `model-hpo-configuration.json` file in Neptune ML
](machine-learning-custom-model-development.md#machine-learning-custom-model-hpo-configuration-file)
  + [

## Local testing of your custom model implementation in Neptune ML
](machine-learning-custom-model-development.md#machine-learning-custom-model-testing)

# Overview of custom models in Neptune ML
<a name="machine-learning-custom-model-overview"></a>

## When to use a custom model in Neptune ML
<a name="machine-learning-custom-models-when-to-use"></a>

Neptune ML's built-in models handle all the standard tasks supported by Neptune ML, but there may be cases where you want to have more granular control over the model for a particular task, or need to customize the model training process. For example, a custom model is appropriate in the following situations:
+ Feature encoding for text features of very large text models need to be run on GPU.
+ You want to use your own custom Graph Neural Network (GNN) model developed in Deep Graph Library (DGL).
+ You want to use tabular models or ensemble models for node classification and regression.

## Workflow for developing and using a custom model in Neptune ML
<a name="machine-learning-custom-model-workflow"></a>

Custom model support in Neptune ML is designed to integrate seamlessly into existing Neptune ML workflows. It works by running custom code in your source module on Neptune ML's infrastructure to train the model. Just as is the case for a built-in mode, Neptune ML automatically launches a SageMaker AI HyperParameter tuning job and selects the best model according to the evaluation metric. It then uses the implementation provided in your source module to generate model artifacts for deployment.

Data export, training configuration, and data preprocessing is the same for a custom model as for a built-in one.

After data preprocessing is when you can iteratively and interactively develop and test your custom model implementation using Python. When your model is production-ready, you can upload the resulting Python module to Amazon S3 like this:

```
aws s3 cp --recursive (source path to module) s3://(bucket name)/(destination path for your module)
```

Then, you can use the normal [default](machine-learning-overview.md#machine-learning-overview-starting-workflow) or the [incremental](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-incremental) data workflow to deploy the model to production, with a few differences.

For model training using a custom model, you must provide a `customModelTrainingParameters` JSON object to the Neptune ML model training API to ensure that your custom code is used. The fields in the `customModelTrainingParameters` object are as follows:
+ **`sourceS3DirectoryPath`**   –   (*Required*) The path to the Amazon S3 location where the Python module implementing your model is located. This must point to a valid existing Amazon S3 location that contains, at a minimum, a training script, a transform script, and a `model-hpo-configuration.json` file.
+ **`trainingEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that performs model training and takes hyperparameters as command-line arguments, including fixed hyperparameters.

  *Default*: `training.py`.
+ **`transformEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that should be run after the best model from the hyperparameter search has been identified, to compute the model artifacts necessary for model deployment. It should be able to run with no command-line arguments.

  *Default*: `transform.py`.

For example:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer" \
  --model-name "custom" \
  --custom-model-training-parameters '{
    "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
    "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
    "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
  }'
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer',
    modelName='custom',
    customModelTrainingParameters={
        'sourceS3DirectoryPath': 's3://(your Amazon S3 bucket)/(path to your Python module)',
        'trainingEntryPointScript': '(your training script entry-point name in the Python module)',
        'transformEntryPointScript': '(your transform script entry-point name in the Python module)'
    }
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

------

Similarly, to enable a custom model transform, you must provide a `customModelTransformParameters` JSON object to the Neptune ML model transform API, with field values that are compatible with the saved model parameters from the training job. The `customModelTransformParameters` object contains these fields:
+ **`sourceS3DirectoryPath`**   –   (*Required*) The path to the Amazon S3 location where the Python module implementing your model is located. This must point to a valid existing Amazon S3 location that contains, at a minimum, a training script, a transform script, and a `model-hpo-configuration.json` file.
+ **`transformEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that should be run after the best model from the hyperparameter search has been identified, to compute the model artifacts necessary for model deployment. It should be able to run with no command-line arguments.

  *Default*: `transform.py`.

For example:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --training-job-name "(name of a completed SageMaker training job)" \
  --model-transform-output-s3-location "s3://(your Amazon S3 bucket)/neptune-model-transform/" \
  --custom-model-transform-parameters '{
    "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
    "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
  }'
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    trainingJobName='(name of a completed SageMaker training job)',
    modelTransformOutputS3Location='s3://(your Amazon S3 bucket)/neptune-model-transform/',
    customModelTransformParameters={
        'sourceS3DirectoryPath': 's3://(your Amazon S3 bucket)/(path to your Python module)',
        'transformEntryPointScript': '(your transform script entry-point name in the Python module)'
    }
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-transform/",
        "customModelTransformParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-transform/",
        "customModelTransformParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

------

# Custom model development in Neptune ML
<a name="machine-learning-custom-model-development"></a>

A good way to start custom model development is by following [Neptune ML toolkit examples](https://github.com/awslabs/neptuneml-toolkit/tree/main/examples/custom-models/introduction) to structure and write your training module. The Neptune ML toolkit also implements modularized graph ML model components in the [modelzoo](https://github.com/awslabs/neptuneml-toolkit/tree/main/src/neptuneml_toolkit/modelzoo) that you can stack and use to create your custom model.

In addition, the toolkit provides utility functions that help you generate the necessary artifacts during model training and model transform. You can import this Python package in your custom implementation. Any functions or modules provided in the toolkit are also available in the Neptune ML training environment.

If your Python module has additional external dependencies, you can include these additional dependencies by creating a `requirements.txt` file in your module's directory. The packages listed in the `requirements.txt` file will then be installed before your training script is run.

At a minimum, the Python module that implements your custom model needs to contain the following:
+ A training script entry point
+ A transform script entry point
+ A `model-hpo-configuration.json` file

## Custom model training script development in Neptune ML
<a name="machine-learning-custom-model-training-script"></a>

Your custom model training script should be an executable Python script like the Neptune ML toolkit's [https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py) example. It must accept hyperparameter names and values as command-line arguments. During model training, the hyperparameter names are obtained from the `model-hpo-configuration.json` file. The hyperparameter values either fall within the valid hyperparameter range if the hyperparameter is tunable, or take the default hyperparameter value if it is not tunable.

Your training script is run on a SageMaker AI training instance using a syntax like this:

```
python3 (script entry point) --(1st parameter) (1st value) --(2nd parameter) (2nd value) (...)
```

For all tasks, the Neptune ML AutoTrainer sends several required parameters to your training script in addition to the hyperparameters that you specify, and your script must be able to handle these additional parameters in order to work properly.

These additional required parameters vary somewhat by task:

**For node classification or node regression**
+ **`task`**   –   The task type used internally by Neptune ML. For node classification this is `node_class`, and for node regression it is `node_regression`.
+ **`model`**   –   The model name used internally by Neptune ML, which is `custom` in this case.
+ **`name`**   –   The name of the task used internally by Neptune ML, which is `node_class-custom` for node classification in this case, and `node_regression-custom` for node regression.
+ **`target_ntype`**   –   The name of the node type for classification or regression.
+ **`property`**   –   The name of the node property for classification or regression.

**For link prediction**
+ **`task`**   –   The task type used internally by Neptune ML. For link prediction, this is `link_predict`.
+ **`model`**   –   The model name used internally by Neptune ML, which is `custom` in this case.
+ **`name`**   –   The name of the task used internally by Neptune ML, which is `link_predict-custom` in this case.

**For edge classification or edge regression**
+ **`task`**   –   The task type used internally by Neptune ML. For edge classification this is `edge_class`, and for edge regression it is `edge_regression`.
+ **`model`**   –   The model name used internally by Neptune ML, which is `custom` in this case.
+ **`name`**   –   The name of the task used internally by Neptune ML, which is `edge_class-custom` for edge classification in this case, and `edge_regression-custom` for edge regression.
+ **`target_etype`**   –   The name of the edge type for classification or regression.
+ **`property`**   –   The name of the edge property for classification or regression.

Your script should save the model parameters, as well as any other artifacts that will be needed to at the end of training.

You can use Neptune ML toolkit utility functions to determine the location of the processed graph data, the location where the model parameters should be saved, and what GPU devices are available on the training instance. See the [train.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py) sample training script for examples of how to use these utility functions.

## Custom model transform script development in Neptune ML
<a name="machine-learning-custom-model-transform-script"></a>

A transform script is needed to take advantage of the Neptune ML [incremental workflow](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-incremental) for model inference on evolving graphs without retraining the model. Even if all the artifacts necessary for model deployment are generated by the training script, you still need to provide a transform script if you want to generate updated models without retraining the model.

**Note**  
[Real-time inductive inference](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference) is not currently supported for custom models.

Your custom model transform script should be an executable Python script like the Neptune ML toolkit's [transform.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/transform.py) example script. Because this script is invoked during model training with no command line arguments, any command line arguments that the script does accept must have defaults.

The script runs on a SageMaker AI training instance with a syntax like this:

```
python3 (your transform script entry point)
```

Your transform script will need various pieces of information, such as:
+ The location of the processed graph data.
+ The location where the model parameters are saved and where new model artifacts should be saved.
+ The devices available on the instance.
+ The hyperparameters that generated the best model.

These inputs are obtained using Neptune ML utility functions that your script can call. See the toolkit's sample [transform.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/transform.py) script for examples of how to do that.

The script should save the node embeddings, node ID mappings, and any other artifacts necessary for model deployment for each task. See the [model artifacts documentation](machine-learning-model-artifacts.md) for more information about the model artifacts required for different Neptune ML tasks.

## Custom `model-hpo-configuration.json` file in Neptune ML
<a name="machine-learning-custom-model-hpo-configuration-file"></a>

The `model-hpo-configuration.json` file defines hyperparameters for your custom model. It is in the same [format](machine-learning-customizing-hyperparams.md) as the `model-hpo-configuration.json` file used with the Neptune ML built-in models, and takes precedence over the version that is auto-generated by Neptune ML and uploaded to the location of your processed data.

When you add a new hyperparameter to your model, you must also add an entry for the hyperparameter in this file so that the hyperparameter is passed to your training script.

You must provide a range for a hyperparameter if you want it to be tunable, and set it as a `tier-1`, `tier-2`, or `tier-3` param. The hyperparameter will be tuned if the total number of training jobs configured allow for tuning hyperparameters in its tier. For a non-tunable parameter, you must provide a default value and add the hyperparameter to the `fixed-param` section of the file. See the toolkit's sample [sample `model-hpo-configuration.json` file](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/model-hpo-configuration.json) for an example of how to do that.

You must also provide the metric definition that the SageMaker AI HyperParameter Optimization job will use to evaluate the candidate models trained. To do this, you add an `eval_metric` JSON object to the `model-hpo-configuration.json` file like this:

```
"eval_metric": {
  "tuning_objective": {
      "MetricName": "(metric_name)",
      "Type": "Maximize"
  },
  "metric_definitions": [
    {
      "Name": "(metric_name)",
      "Regex": "(metric regular expression)"
    }
  ]
},
```

The `metric_definitions` array in the `eval_metric` object lists metric definition objects for each metric that you want SageMaker AI to extract from the training instance. Each metric definition object has a `Name` key that lets you provide a name for the metric (such as "accuracy", "f1", and so on) The `Regex` key lets you provide a regular expression string that matches how that particular metric is printed in the training logs. See the [SageMaker AI HyperParameter Tuning page](https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning-define-metrics.html) for more details on how to define metrics.

The `tuning_objective` object in `eval_metric` then allows you to specify which of the metrics in `metric_definitions` should be used as the evaluation metric that serves as the objective metric for hyperparameter optimization. The value for the `MetricName` must match the value of a `Name` in one of the definitions in `metric_definitions`. The value for `Type` should be either "Maximize" or "Minimize" depending on whether the metric should be interpreted as greater-is-better (like "accuracy") or less-is-better (like "mean-squared-error".

Errors in this section of the `model-hpo-configuration.json` file can result in failures of the Neptune ML model training API job, because the SageMaker AI HyperParameter Tuning job will not be able to select the best model.

## Local testing of your custom model implementation in Neptune ML
<a name="machine-learning-custom-model-testing"></a>

You can use the Neptune ML toolkit Conda environment to run your code locally in order to test and validate your model. If you're developing on a Neptune Notebook instance, then this Conda environment will be pre-installed on the Neptune Notebook instance. If you’re developing on a different instance, then you need to follow the [local setup instructions](https://github.com/awslabs/neptuneml-toolkit#local-installation) in the Neptune ML toolkit.

The Conda environment accurately reproduces the environment where your model will run when you call the [model training API](machine-learning-api-modeltraining.md). All of the example training scripts and transform scripts allow you to pass a command line `--local` flag to run the scripts in a local environment for easy debugging. This is a good practice while developing your own model because it allows you to interactively and iteratively test your model implementation. During model training in the Neptune ML production training environment, this parameter is omitted.

# Creating an inference endpoint to query
<a name="machine-learning-on-graphs-inference-endpoint"></a>

An inference endpoint lets you query one specific model that the model-training process constructed. The endpoint attaches to the best-performing model of a given type that the training process was able to generate. The endpoint is then able to accept Gremlin queries from Neptune and return that model's predictions for inputs in the queries. After you have created an inference endpoint, it stays active until you delete it.

## Managing inference endpoints for Neptune ML
<a name="machine-learning-on-graphs-endpoint-managing"></a>

After you have completed model training on data that you exported from Neptune, you can create an inference endpoint using a command like the following:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --ml-model-training-job-id "(the model-training job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    mlModelTrainingJobId='(the model-training job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

------

You can also create an inference endpoint from a model created by a completed model transform job, in much the same way:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --ml-model-transform-job-id "(the model-transform job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    mlModelTransformJobId='(the model-transform job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

------

The details of how to use these commands are explained in [The endpoints command](machine-learning-api-endpoints.md), along with information about how to get the status of an endpoint, how to delete an endpoint, and how to list all inference endpoints.

# Inference queries in Neptune ML
<a name="machine-learning-inference-queries"></a>

You can use either Gremlin or SPARQL to query a Neptune ML inference endpoint. [Real-time inductive inference](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference), however, is currently only supported for Gremlin queries.

# Gremlin inference queries in Neptune ML
<a name="machine-learning-gremlin-inference-queries"></a>

As described in [Neptune ML capabilities](machine-learning.md#machine-learning-capabilities), Neptune ML supports training models that can do the following kinds of inference tasks:
+ **Node classification**   –   Predicts the categorical feature of a vertex property.
+ **Node regression**   –   Predicts a numerical property of a vertex.
+ **Edge classification**   –   Predicts the categorical feature of an edge property.
+ **Edge regression**   –   Predicts a numerical property of an edge.
+ **Link prediction**   –   Predicts destination nodes given a source node and outgoing edge, or source nodes given a destination node and incoming edge.

We can illustrate these different tasks with examples that use the [MovieLens 100k dataset](https://grouplens.org/datasets/movielens/100k/) provided by [GroupLens Research](https://grouplens.org/datasets/movielens/). This dataset consists of movies, users, and ratings of the movies by the users, from which we've created a property graph like this: 

![\[Sample movie property graph using the MovieLens 100k dataset\]](http://docs.aws.amazon.com/neptune/latest/userguide/images/movie_property_graph_example.png)


**Node classification**: In the dataset above, `Genre` is a vertex type which is connected to vertex type `Movie` by edge `included_in`. However, if we tweak the dataset to make `Genre` a [categorical](https://en.wikipedia.org/wiki/Categorical_variable) feature for vertex type `Movie`, then the problem of inferring `Genre` for new movies added to our knowledge graph can be solved using node classification models.

**Node regression**: If we consider the vertex type `Rating`, which has properties like `timestamp` and `score`, then the problem of inferring the numerical value `Score` for a `Rating` can be solved using node regression models.

**Edge classification**: Similarly, for a `Rated` edge, if we have a property `Scale` that can have one of the values, `Love`, `Like`, `Dislike`, `Neutral`, `Hate`, then the problem of inferring `Scale` for the `Rated` edge for new movies/ratings can be solved using edge classification models.

**Edge regression**: Similarly, for the same `Rated` edge, if we have a property `Score` that holds a numerical value for the rating, then this can be inferred from edge regression models.

**Link prediction**: Problems like, find the top ten users who are most likely to rate a given movie, or find the top ten Movies that a given user is most likely to rate, falls under link prediction.

**Note**  
For Neptune ML use-cases, we have a very rich set of notebooks designed to give you a hands-on understanding of each use-case. You can create these notebooks along with your Neptune cluster when you use the [Neptune ML CloudFormation template](machine-learning-quick-start.md) to create a Neptune ML cluster. These notebooks are also available on [github](https://github.com/aws/graph-notebook/tree/main/src/graph_notebook/notebooks/04-Machine-Learning) as well.

**Topics**
+ [

# Neptune ML predicates used in Gremlin inference queries
](machine-learning-gremlin-inference-query-predicates.md)
+ [

# Gremlin node classification queries in Neptune ML
](machine-learning-gremlin-vertex-classification-queries.md)
+ [

# Gremlin node regression queries in Neptune ML
](machine-learning-gremlin-vertex-regression-queries.md)
+ [

# Gremlin edge classification queries in Neptune ML
](machine-learning-gremlin-edge-classification-queries.md)
+ [

# Gremlin edge regression queries in Neptune ML
](machine-learning-gremlin-edge-regression.md)
+ [

# Gremlin link prediction queries using link-prediction models in Neptune ML
](machine-learning-gremlin-link-prediction-queries.md)
+ [

# List of exceptions for Neptune ML Gremlin inference queries
](machine-learning-gremlin-exceptions.md)

# Neptune ML predicates used in Gremlin inference queries
<a name="machine-learning-gremlin-inference-query-predicates"></a>

## `Neptune#ml.deterministic`
<a name="machine-learning-gremlin-inference-neptune-ml-deterministic-predicate"></a>

This predicate is an option for inductive inference queries — that is, for queries that include the [`Neptune#ml.inductiveInference`](#machine-learning-gremlin-inference-neptune-ml-inductiveInference) predicate.

When using inductive inference, the Neptune engine creates the appropriate subgraph to evaluate the trained GNN model, and the requirements of this subgraph depend on parameters of the final model. Specifically, the `num-layer` parameter determines the number of traversal hops from the target nodes or edges, and the `fanouts` parameter specifies how many neighbors to sample at each hop (see [HPO parameters](machine-learning-customizing-hyperparams.md)).

By default, inductive inference queries run in non-deterministic mode, in which Neptune builds the neighborhood randomly. When making predictions, this normal random-neighbor sampling sometimes result in different predictions.

When you include `Neptune#ml.deterministic` in an inductive inference query, the Neptune engine attempts to sample neighbors in a deterministic way so that multiple invocations of the same query return the same results every time. The results can't be guaranteed to be completely deterministic, however, because changes to the underlying graph and artifacts of distributed systems can still introduce fluctuations.

You include the `Neptune#ml.deterministic` predicate in a query like this:

```
.with("Neptune#ml.deterministic")
```

If the `Neptune#ml.deterministic` predicate is included in a query that doesn't also include `Neptune#ml.inductiveInference`, it is simply ignored.

## `Neptune#ml.disableInductiveInferenceMetadataCache`
<a name="machine-learning-gremlin-disableInductiveInferenceMetadataCache-predicate"></a>

This predicate is an option for inductive inference queries — that is, for queries that include the [`Neptune#ml.inductiveInference`](#machine-learning-gremlin-inference-neptune-ml-inductiveInference) predicate.

For inductive inference queries, Neptune uses a metadata file stored in Amazon S3 to decide the number of hops and the fanout while building the neighborhood. Neptune normally caches this model metadata to avoid fetching the file from Amazon S3 repeatedly. Caching can be disabled by including the `Neptune#ml.disableInductiveInferenceMetadataCache` predicate in the query. Although it may be slower for Neptune to fetch the metadata directly from Amazon S3, it is useful when the SageMaker AI endpoint has been updated after retraining or transformation and the cache is stale.

You include the `Neptune#ml.disableInductiveInferenceMetadataCache` predicate in a query like this:

```
.with("Neptune#ml.disableInductiveInferenceMetadataCache")
```

Here is how a sample query might look in a Jupyter notebook:

```
%%gremlin
g.with("Neptune#ml.endpoint", "ep1")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .with("Neptune#ml.disableInductiveInferenceMetadataCache")
 .V('101').properties("rating")
 .with("Neptune#ml.regression")
 .with("Neptune#ml.inductiveInference")
```

## `Neptune#ml.endpoint`
<a name="machine-learning-gremlin-inference-neptune-ml-endpoint-predicate"></a>

The `Neptune#ml.endpoint` predicate is used in a `with()` step to specify the inference endpoint, if necessary:

```
 .with("Neptune#ml.endpoint", "the model's SageMaker AI inference endpoint")
```

You can identify the endpoint either by its `id` or its URL. For example:

```
 .with( "Neptune#ml.endpoint", "node-classification-movie-lens-endpoint" )
```

Or:

```
 .with( "Neptune#ml.endpoint", "https://runtime.sagemaker.us-east-1.amazonaws.com/endpoints/node-classification-movie-lens-endpoint/invocations" )
```

**Note**  
If you [set the `neptune_ml_endpoint` parameter](machine-learning-cluster-setup.md#machine-learning-set-inference-endpoint-cluster-parameter) in your Neptune DB cluster parameter group to the endpoint `id` or URL, you don't need to include the `Neptune#ml.endpoint` predicate in each query.

## `Neptune#ml.iamRoleArn`
<a name="machine-learning-gremlin-inference-neptune-ml-iamRoleArn-predicate"></a>

`Neptune#ml.iamRoleArn` is used in a `with()` step to specify the ARN of the SageMaker AI execution IAM role, if necessary:

```
 .with("Neptune#ml.iamRoleArn", "the ARN for the SageMaker AI execution IAM role")
```

For information about how to create the SageMaker AI execution IAM role, see [Create a custom NeptuneSageMakerIAMRole role](machine-learning-manual-setup.md#ml-manual-setup-sm-role).

**Note**  
If you [set the `neptune_ml_iam_role` parameter](machine-learning-cluster-setup.md#machine-learning-enabling-create-param-group) in your Neptune DB cluster parameter group to the ARN of your SageMaker AI execution IAM role, you don't need to include the `Neptune#ml.iamRoleArn` predicate in each query.

## Neptune\$1ml.inductiveInference
<a name="machine-learning-gremlin-inference-neptune-ml-inductiveInference"></a>

Transductive inference is enabled by default in Gremlin. To make a [real-time inductive inference](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference) query, include the `Neptune#ml.inductiveInference` predicate like this:

```
.with("Neptune#ml.inductiveInference")
```

If your graph is dynamic, inductive inference is often the best choice, but if your graph is static, transductive inference is faster and more efficient.

## `Neptune#ml.limit`
<a name="machine-learning-gremlin-inference-neptune-ml-limit-predicate"></a>

The `Neptune#ml.limit` predicate optionally limits the number of results returned per entity:

```
 .with( "Neptune#ml.limit", 2 )
```

By default, the limit is 1, and the maximum number that can be set is 100.

## `Neptune#ml.threshold`
<a name="machine-learning-gremlin-inference-neptune-ml-threshold-predicate"></a>

The `Neptune#ml.threshold` predicate optionally establishes a cutoff threshold for result scores:

```
 .with( "Neptune#ml.threshold", 0.5D )
```

This lets you discard all results with scores below the specified threshold.

## `Neptune#ml.classification`
<a name="machine-learning-gremlin-inference-neptune-ml-classification-predicate"></a>

The `Neptune#ml.classification` predicate is attached to the `properties()` step to establish that the properties need to be fetched from the SageMaker AI endpoint of the node classification model:

```
 .properties( "property key of the node classification model" ).with( "Neptune#ml.classification" )
```

## `Neptune#ml.regression`
<a name="machine-learning-gremlin-inference-neptune-ml-regression-predicate"></a>

The `Neptune#ml.regression` predicate is attached to the `properties()` step to establish that the properties need to be fetched from the SageMaker AI endpoint of the node regression model:

```
 .properties( "property key of the node regression model" ).with( "Neptune#ml.regression" )
```

## `Neptune#ml.prediction`
<a name="machine-learning-gremlin-inference-neptune-ml-prediction-predicate"></a>

The `Neptune#ml.prediction` predicate is attached to `in()` and `out()` steps to establish that this a link-prediction query:

```
 .in("edge label of the link prediction model").with("Neptune#ml.prediction").hasLabel("target node label")
```

## `Neptune#ml.score`
<a name="machine-learning-gremlin-inference-neptune-ml-score-predicate"></a>

The `Neptune#ml.score` predicate is used in Gremlin node or edge classification queries to fetch a machine-learning confidence Score. The `Neptune#ml.score` predicate should be passed together with the query predicate in the `properties()` step to obtain an ML confidence score for node or edge classification queries.

You can find a node classification example with [other node classification examples](machine-learning-gremlin-vertex-classification-queries.md#machine-learning-gremlin-node-class-other-queries), and an edge classification example in the [edge classification section](machine-learning-gremlin-edge-classification-queries.md).

# Gremlin node classification queries in Neptune ML
<a name="machine-learning-gremlin-vertex-classification-queries"></a>

For Gremlin node classification in Neptune ML:
+ The model is trained on one property of the vertices. The set of unique values of this property are referred to as a set of node classes, or simply, classes.
+ The node class or categorical property value of a vertex's property can be inferred from the node classification model. This is useful where this property is not already attached to the vertex.
+ In order to fetch one or more classes from a node classification model, you need to use the `with()` step with the predicate `Neptune#ml.classification` to configure the `properties()` step. The output format is similar to what you would expect if those were vertex properties.

**Note**  
Node classification only works with string property values. That means that numerical property values such as `0` or `1` are not supported, although the string equivalents `"0"` and `"1"` are. Similarly, the Boolean property values `true` and `false` don't work, but `"true"` and `"false"` do.

Here is a sample node classification query:

```
g.with( "Neptune#ml.endpoint","node-classification-movie-lens-endpoint" )
 .with( "Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role" )
 .with( "Neptune#ml.limit", 2 )
 .with( "Neptune#ml.threshold", 0.5D )
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre").with("Neptune#ml.classification")
```

The output of this query would look something like the following:

```
==>vp[genre->Action]
==>vp[genre->Crime]
==>vp[genre->Comedy]
```

In the query above, the `V()` and `properties()` steps are used as follows:

The `V()` step contains the set of vertices for which you want to fetch the classes from the node-classification model:

```
 .V( "movie_1", "movie_2", "movie_3" )
```

The `properties()` step contains the key on which the model was trained, and has `.with("Neptune#ml.classification")` to indicate that this is a node classification ML inference query.

Multiple property keys are not currently supported in a `properties().with("Neptune#ml.classification")` step. For example, the following query results in an exception:

```
g.with("Neptune#ml.endpoint", "node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre", "other_label").with("Neptune#ml.classification")
```

For the specific error message, see the [list of Neptune ML exceptions](machine-learning-gremlin-exceptions.md).

A `properties().with("Neptune#ml.classification")` step can be used in combination with any of the following steps:
+ `value()`
+ `value().is()`
+ `hasValue()`
+ `has(value,"")`
+ `key()`
+ `key().is()`
+ `hasKey()`
+ `has(key,"")`
+ `path()`

## Other node-classification queries
<a name="machine-learning-gremlin-node-class-other-queries"></a>

If both the inference endpoint and the corresponding IAM role have been saved in your DB cluster parameter group, a node-classification query can be as simple as this:

```
g.V("movie_1", "movie_2", "movie_3").properties("genre").with("Neptune#ml.classification")
```

You can mix vertex properties and classes in a query using the `union()` step:

```
g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .union(
   properties("genre").with("Neptune#ml.classification"),
   properties("genre")
 )
```

You can also make an unbounded query such as this:

```
g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V()
 .properties("genre").with("Neptune#ml.classification")
```

You can retrieve the node classes together with vertices using the `select()` step together with the `as()` step:

```
g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" ).as("vertex")
 .properties("genre").with("Neptune#ml.classification").as("properties")
 .select("vertex","properties")
```

You can also filter on node classes, as illustrated in these examples:

```
g.with("Neptune#ml.endpoint", "node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre").with("Neptune#ml.classification")
 .has(value, "Horror")

g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre").with("Neptune#ml.classification")
 .has(value, P.eq("Action"))

g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre").with("Neptune#ml.classification")
 .has(value, P.within("Action", "Horror"))
```

You can get a node classification confidence score using the `Neptune#ml.score` predicate:

```
 g.with("Neptune#ml.endpoint","node-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V( "movie_1", "movie_2", "movie_3" )
 .properties("genre", "Neptune#ml.score").with("Neptune#ml.classification")
```

The response would look like this:

```
==>vp[genre->Action]
==>vp[Neptune#ml.score->0.01234567]
==>vp[genre->Crime]
==>vp[Neptune#ml.score->0.543210]
==>vp[genre->Comedy]
==>vp[Neptune#ml.score->0.10101]
```

## Using inductive inference in a node classification query
<a name="machine-learning-gremlin-node-class-inductive"></a>

Supposing you were to add a new node to an existing graph, in a Jupyter notebook, like this:

```
%%gremlin
g.addV('label1').property(id,'101').as('newV')
 .V('1').as('oldV1')
 .V('2').as('oldV2')
 .addE('eLabel1').from('newV').to('oldV1')
 .addE('eLabel2').from('oldV2').to('newV')
```

You could then use an inductive inference query to get a genre and confidence score that reflected the new node:

```
%%gremlin
g.with("Neptune#ml.endpoint", "nc-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('101').properties("genre", "Neptune#ml.score")
 .with("Neptune#ml.classification")
 .with("Neptune#ml.inductiveInference")
```

If you ran the query several times, however, you might get somewhat different results:

```
# First time
==>vp[genre->Action]
==>vp[Neptune#ml.score->0.12345678]

# Second time
==>vp[genre->Action]
==>vp[Neptune#ml.score->0.21365921]
```

You could make the same query deterministic:

```
%%gremlin
g.with("Neptune#ml.endpoint", "nc-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('101').properties("genre", "Neptune#ml.score")
 .with("Neptune#ml.classification")
 .with("Neptune#ml.inductiveInference")
 .with("Neptune#ml.deterministic")
```

In that case, the results would be roughly the same every time:

```
# First time
==>vp[genre->Action]
==>vp[Neptune#ml.score->0.12345678]
# Second time
==>vp[genre->Action]
==>vp[Neptune#ml.score->0.12345678]
```

# Gremlin node regression queries in Neptune ML
<a name="machine-learning-gremlin-vertex-regression-queries"></a>

Node regression is similar to node classification, except that the value inferred from the regression model for each node is numeric. You can use the same Gremlin queries for node regression as for node classification except for the following differences:
+ Again, in Neptune ML, nodes refer to vertices.
+ The `properties()` step takes the form, `properties().with("Neptune#ml.regression")`instead of `properties().with("Neptune#ml.classification")`.
+ The `"Neptune#ml.limit`" and `"Neptune#ml.threshold"` predicates are not applicable.
+ When you filter on the value, you have to specify a numeric value.

Here is a sample vertex classification query:

```
g.with("Neptune#ml.endpoint","node-regression-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::0123456789:role/sagemaker-role")
 .V("movie_1","movie_2","movie_3")
 .properties("revenue").with("Neptune#ml.regression")
```

You can filter on the value inferred using a regression model, as illustrated in the following examples:

```
g.with("Neptune#ml.endpoint","node-regression-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("movie_1","movie_2","movie_3")
 .properties("revenue").with("Neptune#ml.regression")
 .value().is(P.gte(1600000))

g.with("Neptune#ml.endpoint","node-regression-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("movie_1","movie_2","movie_3")
 .properties("revenue").with("Neptune#ml.regression")
 .hasValue(P.lte(1600000D))
```

## Using inductive inference in a node regression query
<a name="machine-learning-gremlin-node-regress-inductive"></a>

Supposing you were to add a new node to an existing graph, in a Jupyter notebook, like this:

```
%%gremlin
g.addV('label1').property(id,'101').as('newV')
 .V('1').as('oldV1')
 .V('2').as('oldV2')
 .addE('eLabel1').from('newV').to('oldV1')
 .addE('eLabel2').from('oldV2').to('newV')
```

You could then use an inductive inference query to get a rating that took into account the new node:

```
%%gremlin
g.with("Neptune#ml.endpoint", "nr-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('101').properties("rating")
 .with("Neptune#ml.regression")
 .with("Neptune#ml.inductiveInference")
```

Because the query is not deterministic, it might return somewhat different results if you run it several times, based on the neighborhood:

```
# First time
==>vp[rating->9.1]

# Second time
==>vp[rating->8.9]
```

If you need more consistent results, you could make the query deterministic:

```
%%gremlin
g.with("Neptune#ml.endpoint", "nc-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('101').properties("rating")
 .with("Neptune#ml.regression")
 .with("Neptune#ml.inductiveInference")
 .with("Neptune#ml.deterministic")
```

Now the results will be roughly the same every time:

```
# First time
==>vp[rating->9.1]

# Second time
==>vp[rating->9.1]
```

# Gremlin edge classification queries in Neptune ML
<a name="machine-learning-gremlin-edge-classification-queries"></a>

For Gremlin edge classification in Neptune ML:
+ The model is trained on one property of the edges. The set of unique values of this property is referred to as a set of classes.
+ The class or categorical property value of an edge can be inferred from the edge classification model, which is useful when this property is not already attached to the edge.
+ In order to fetch one or more classes from an edge classification model, you need to use the `with()` step with the predicate, `"Neptune#ml.classification"` to configure the `properties()` step. The output format is similar to what you would expect if those were edge properties.

**Note**  
Edge classification only works with string property values. That means that numerical property values such as `0` or `1` are not supported, although the string equivalents `"0"` and `"1"` are. Similarly, the Boolean property values `true` and `false` don't work, but `"true"` and `"false"` do.

Here is an example of an edge classification query that requests a confidence score using the `Neptune#ml.score` predicate:

```
g.with("Neptune#ml.endpoint","edge-classification-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .E("relationship_1","relationship_2","relationship_3")
 .properties("knows_by", "Neptune#ml.score").with("Neptune#ml.classification")
```

The response would look like this:

```
==>p[knows_by->"Family"]
==>p[Neptune#ml.score->0.01234567]
==>p[knows_by->"Friends"]
==>p[Neptune#ml.score->0.543210]
==>p[knows_by->"Colleagues"]
==>p[Neptune#ml.score->0.10101]
```

## Syntax of a Gremlin edge classification query
<a name="machine-learning-gremlin-edge-classification-syntax"></a>

For a simple graph where `User` is the head and tail node, and `Relationship` is the edge that connects them, an example edge classification query is:

```
g.with("Neptune#ml.endpoint","edge-classification-social-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .E("relationship_1","relationship_2","relationship_3")
 .properties("knows_by").with("Neptune#ml.classification")
```

The output of this query would look something like the following:

```
==>p[knows_by->"Family"]
==>p[knows_by->"Friends"]
==>p[knows_by->"Colleagues"]
```

In the query above, the `E()` and `properties()` steps are used as follows:
+ The `E()` step contains the set of edges for which you want to fetch the classes from the edge-classification model:

  ```
  .E("relationship_1","relationship_2","relationship_3")
  ```
+ The `properties()` step contains the key on which the model was trained, and has `.with("Neptune#ml.classification")` to indicate that this is an edge classification ML inference query.

Multiple property keys are not currently supported in a `properties().with("Neptune#ml.classification")` step. For example, the following query results in an exception being thrown:

```
g.with("Neptune#ml.endpoint","edge-classification-social-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .E("relationship_1","relationship_2","relationship_3")
 .properties("knows_by", "other_label").with("Neptune#ml.classification")
```

For specific error messages, see [List of exceptions for Neptune ML Gremlin inference queries](machine-learning-gremlin-exceptions.md).

A `properties().with("Neptune#ml.classification")` step can be used in combination with any of the following steps:
+ `value()`
+ `value().is()`
+ `hasValue()`
+ `has(value,"")`
+ `key()`
+ `key().is()`
+ `hasKey()`
+ `has(key,"")`
+ `path()`

## Using inductive inference in an edge classification query
<a name="machine-learning-gremlin-edge-class-inductive"></a>

Supposing you were to add a new edge to an existing graph, in a Jupyter notebook, like this:

```
%%gremlin
g.V('1').as('fromV')
.V('2').as('toV')
.addE('eLabel1').from('fromV').to('toV').property(id, 'e101')
```

You could then use an inductive inference query to get a scale that took into account the new edge:

```
%%gremlin
g.with("Neptune#ml.endpoint", "ec-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .E('e101').properties("scale", "Neptune#ml.score")
 .with("Neptune#ml.classification")
 .with("Neptune#ml.inductiveInference")
```

Because the query is not deterministic, the results would vary somewhat if you run it multiple times, based on the random neighborhood:

```
# First time
==>vp[scale->Like]
==>vp[Neptune#ml.score->0.12345678]

# Second time
==>vp[scale->Like]
==>vp[Neptune#ml.score->0.21365921]
```

If you need more consistent results, you could make the query deterministic:

```
%%gremlin
g.with("Neptune#ml.endpoint", "ec-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .E('e101').properties("scale", "Neptune#ml.score")
 .with("Neptune#ml.classification")
 .with("Neptune#ml.inductiveInference")
 .with("Neptune#ml.deterministic")
```

Now the results will be more or less the same every time you run the query:

```
# First time
==>vp[scale->Like]
==>vp[Neptune#ml.score->0.12345678]

# Second time
==>vp[scale->Like]
==>vp[Neptune#ml.score->0.12345678]
```

# Gremlin edge regression queries in Neptune ML
<a name="machine-learning-gremlin-edge-regression"></a>

Edge regression is similar to edge classification, except that the value inferred from the ML model is numeric. For edge regression, Neptune ML supports the same queries as for classification.

Key points to note are:
+ You need to use the ML predicate `"Neptune#ml.regression"` to configure the `properties()` step for this use-case.
+ The `"Neptune#ml.limit"` and `"Neptune#ml.threshold"` predicates are not applicable in this use-case.
+ For filtering on the value, you need to specify the value as numerical.

## Syntax of a Gremlin edge regression query
<a name="machine-learning-gremlin-edge-regression-syntax"></a>

For a simple graph where `User` is the head node, `Movie` is the tail node, and `Rated` is the edge that connects them, here is an example edge regression query that finds the numeric rating value, referred to as score here, for the edge `Rated`:

```
g.with("Neptune#ml.endpoint","edge-regression-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .E("rating_1","rating_2","rating_3")
 .properties("score").with("Neptune#ml.regression")
```

You can also filter on a value inferred from the ML regression model. For the existing `Rated` edges (from `User` to `Movie`) identified by `"rating_1"`, `"rating_2"`, and `"rating_3"`, where the edge property `Score` is not present for these ratings, you can use a query like following to infer `Score` for the edges where it is greater than or equal to 9:

```
g.with("Neptune#ml.endpoint","edge-regression-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .E("rating_1","rating_2","rating_3")
 .properties("score").with("Neptune#ml.regression")
 .value().is(P.gte(9))
```

## Using inductive inference in an edge regression query
<a name="machine-learning-gremlin-edge-regression-inductive"></a>

Supposing you were to add a new edge to an existing graph, in a Jupyter notebook, like this:

```
%%gremlin
g.V('1').as('fromV')
.V('2').as('toV')
.addE('eLabel1').from('fromV').to('toV').property(id, 'e101')
```

You could then use an inductive inference query to get a score that took into account the new edge:

```
%%gremlin
g.with("Neptune#ml.endpoint", "er-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .E('e101').properties("score")
 .with("Neptune#ml.regression")
 .with("Neptune#ml.inductiveInference")
```

Because the query is not deterministic, the results would vary somewhat if you run it multiple times, based on the random neighborhood:

```
# First time
==>ep[score->96]

# Second time
==>ep[score->91]
```

If you need more consistent results, you could make the query deterministic:

```
%%gremlin
g.with("Neptune#ml.endpoint", "er-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .E('e101').properties("score")
 .with("Neptune#ml.regression")
 .with("Neptune#ml.inductiveInference")
 .with("Neptune#ml.deterministic")
```

Now the results will be more or less the same every time you run the query:

```
# First time
==>ep[score->96]

# Second time
==>ep[score->96]
```

# Gremlin link prediction queries using link-prediction models in Neptune ML
<a name="machine-learning-gremlin-link-prediction-queries"></a>

Link-prediction models can solve problems such as the following:
+ **Head-node prediction**: Given a vertex and an edge type, what vertices is that vertex likely to link from?
+ **Tail-node prediction**: Given a vertex and an edge label, what vertices is that vertex likely to link to?

**Note**  
Edge prediction is not yet supported in Neptune ML.

For the examples below, consider a simple graph with the vertices `User` and `Movie` that are linked by the edge `Rated`.

Here is a sample head-node prediction query, used to predict the top five users most likely to rate the movies, `"movie_1"`, `"movie_2"`, and `"movie_3"`:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .with("Neptune#ml.limit", 5)
 .V("movie_1", "movie_2", "movie_3")
 .in("rated").with("Neptune#ml.prediction").hasLabel("user")
```

Here is a similar one for tail-node prediction, used to predict the top five movies that user `"user_1"` is likely to rate:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("user_1")
 .out("rated").with("Neptune#ml.prediction").hasLabel("movie")
```

Both the edge label and the predicted vertex label are required. If either is omitted, an exception is thrown. For example, the following query without a predicted vertex label throws an exception:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("user_1")
 .out("rated").with("Neptune#ml.prediction")
```

Similarly, the following query without an edge label throws an exception:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("user_1")
 .out().with("Neptune#ml.prediction").hasLabel("movie")
```

For the specific error messages that these exceptions return, see the [list of Neptune ML exceptions](machine-learning-gremlin-exceptions.md).

## Other link-prediction queries
<a name="machine-learning-gremlin-other-link-prediction-queries"></a>

You can use the `select()` step with the `as(`) step to output the predicted vertices together with the input vertices:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("movie_1").as("source")
 .in("rated").with("Neptune#ml.prediction").hasLabel("user").as("target")
 .select("source","target")

g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("user_1").as("source")
 .out("rated").with("Neptune#ml.prediction").hasLabel("movie").as("target")
 .select("source","target")
```

You can make unbounded queries, like these:

```
g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("user_1")
 .out("rated").with("Neptune#ml.prediction").hasLabel("movie")

g.with("Neptune#ml.endpoint","node-prediction-movie-lens-endpoint")
 .with("Neptune#ml.iamRoleArn","arn:aws:iam::0123456789:role/sagemaker-role")
 .V("movie_1")
 .in("rated").with("Neptune#ml.prediction").hasLabel("user")
```

## Using inductive inference in a link prediction query
<a name="machine-learning-gremlin-link-predict-inductive"></a>

Supposing you were to add a new node to an existing graph, in a Jupyter notebook, like this:

```
%%gremlin
g.addV('label1').property(id,'101').as('newV1')
 .addV('label2').property(id,'102').as('newV2')
 .V('1').as('oldV1')
 .V('2').as('oldV2')
 .addE('eLabel1').from('newV1').to('oldV1')
 .addE('eLabel2').from('oldV2').to('newV2')
```

You could then use an inductive inference query to predict the head node, taking into account the new node:

```
%%gremlin
g.with("Neptune#ml.endpoint", "lp-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('101').out("eLabel1")
 .with("Neptune#ml.prediction")
 .with("Neptune#ml.inductiveInference")
 .hasLabel("label2")
```

Result:

```
==>V[2]
```

Similarly, you could use an inductive inference query to predict the tail node, taking into account the new node:

```
%%gremlin
g.with("Neptune#ml.endpoint", "lp-ep")
 .with("Neptune#ml.iamRoleArn", "arn:aws:iam::123456789012:role/NeptuneMLRole")
 .V('102').in("eLabel2")
 .with("Neptune#ml.prediction")
 .with("Neptune#ml.inductiveInference")
 .hasLabel("label1")
```

Result:

```
==>V[1]
```

# List of exceptions for Neptune ML Gremlin inference queries
<a name="machine-learning-gremlin-exceptions"></a>

 This is a comprehensive list of exceptions that can occur when executing Neptune ML Gremlin inference queries. These exceptions cover a range of issues, from problems with the specified IAM role or endpoint, to unsupported Gremlin steps and limitations on the number of ML inference queries per query. Each entry includes a detailed message describing the issue. 
+ **`BadRequestException`**   –   The credentials for the supplied role cannot be loaded.

  *Message*: `Unable to load credentials for role: the specified IAM Role ARN.`
+ **`BadRequestException`**   –   The specified IAM role is not authorized to invoke the SageMaker AI endpoint.

  *Message*: `User: the specified IAM Role ARN is not authorized to perform: sagemaker:InvokeEndpoint on resource: the specified endpoint.`
+ **`BadRequestException`**   –   The specified endpoint does not exist.

  *Message*: `Endpoint the specified endpoint not found.`
+ **`InternalFailureException`**   –   Unable to fetch Neptune ML real-time inductive inference metadata from Amazon S3.

  *Message*: `Unable to fetch Neptune ML - Real-Time Inductive Inference metadata from S3. Check the permissions of the S3 bucket or if the Neptune instance can connect to S3.`
+ **`InternalFailureException`**   –   Neptune ML cannot find the metadata file for real-time inductive inference in Amazon S3.

  *Message*: `Neptune ML cannot find the metadata file for Real-Time Inductive Inference in S3.`
+ **`InvalidParameterException`**   –   The specified endpoint is not syntactically valid.

  *Message*: `Invalid endpoint provided for external service query.`
+ **`InvalidParameterException`**   –   The specified SageMaker execution IAM Role ARN is not syntactically valid.

  *Message*: `Invalid IAM role ARN provided for external service query.`
+ **`InvalidParameterException`**   –   Multiple property keys are specified in the `properties()` step in a query.

  *Message*: `ML inference queries are currently supported for one property key.`
+ **`InvalidParameterException`**   –   Multiple edge labels are specified in a query.

  *Message*: `ML inference are currently supported only with one edge label.`
+ **`InvalidParameterException`**   –   Multiple vertex label constraints are specified in a query.

  *Message*: `ML inference are currently supported only with one vertex label constraint.`
+ **`InvalidParameterException`**   –   Both `Neptune#ml.classification` and `Neptune#ml.regression` predicates are present in the same query.

  *Message*: `Both regression and classification ML predicates cannot be specified in the query.`
+ **`InvalidParameterException`**   –   More than one edge label was specified in the `in()` or `out()` step in a link-prediction query.

  *Message*: `ML inference are currently supported only with one edge label.`
+ **`InvalidParameterException`**   –   More than one property key was specified with Neptune\$1ml.score.

  *Message*: `Neptune ML inference queries are currently supported for one property key and one Neptune#ml.score property key.`
+ **`MissingParameterException`**   –   The endpoint was not specified in the query or as a DB cluster parameter.

  *Message*: `No endpoint provided for external service query.`
+ **``MissingParameterException**   –   The SageMaker AI execution IAM role was not specified in the query or as a DB cluster parameter.

  *Message*: `No IAM role ARN provided for external service query.`
+ **`MissingParameterException`**   –   The property key is missing from the `properties()` step in a query.

  *Message*: `Property key needs to be specified using properties() step for ML inference queries.`
+ **`MissingParameterException`**   –   No edge label was specified in the `in()` or `out()` step of a link-prediction query.

  *Message*: `Edge label needs to be specified while using in() or out() step for ML inference queries.`
+ **`MissingParameterException`**   –   No property key was specified with Neptune\$1ml.score.

  *Message*: `Property key needs to be specified along with Neptune#ml.score property key while using the properties() step for Neptune ML inference queries.`
+ **`UnsupportedOperationException`**   –   The `both()` step is used in a link-prediction query.

  *Message*: `ML inference queries are currently not supported with both() step.`
+ **`UnsupportedOperationException`**   –   No predicted vertex label was specified in the `has()` step with the `in()` or `out()` step in a link-prediction query.

  *Message*: `Predicted vertex label needs to be specified using has() step for ML inference queries.`
+ **`UnsupportedOperationException`**   –   Gremlin ML inductive inference queries are not currently supported with unoptimized steps.

  *Message*: `Neptune ML - Real-Time Inductive Inference queries are currently not supported with Gremlin steps which are not optimized for Neptune. Check the Neptune User Guide for a list of Neptune-optimized steps.`
+ **`UnsupportedOperationException`**   –   Neptune ML inference queries are not currently supported inside a `repeat` step.

  *Message*: `Neptune ML inference queries are currently not supported inside a repeat step.`
+ **`UnsupportedOperationException`**   –   No more than one Neptune ML inference query is currently supported per Gremlin query.

  *Message*: `Neptune ML inference queries are currently supported only with one ML inference query per gremlin query.`

# SPARQL inference queries in Neptune ML
<a name="machine-learning-sparql-inference-queries"></a>

Neptune ML maps the RDF graph into a property graph to model the ML Task. Currently, it supports the following use-cases:
+ **Object classification**   –   Predicts the categorical feature of an object.
+ **Object regression**   –   Predicts a numerical property of an object.
+ **Object prediction**   –   Predicts an object given a subject and a relationship.
+ **Subject prediction**   –   Predicts a subject given an object and a relationship.

**Note**  
Neptune ML does not support subject classification and regression use cases with SPARQL.

# Neptune ML predicates used in SPARQL inference queries
<a name="machine-learning-sparql-inference-query-predicates"></a>

The following predicates are used with SPARQL inference:

## `neptune-ml:timeout` predicate
<a name="machine-learning-sparql-inference-predicates-timeout"></a>

Specifies the timeout for connection with the remote server. Should not be confused with the query request timeout, which is the maximum amount of time the server can take to satisfy a request.

Note that if the query timeout occurs before the service timeout specified by the `neptune-ml:timeout` predicate occurs, the service connection is canceled too.

## `neptune-ml:outputClass` predicate
<a name="machine-learning-sparql-inference-predicates-outputClass"></a>

The `neptune-ml:outputClass` predicate is only used to define the class of the predicted object for object prediction or predicted subject for subect prediction.

## `neptune-ml:outputScore` predicate
<a name="machine-learning-sparql-inference-predicates-outputScore"></a>

The `neptune-ml:outputScore` predicate is a positive number that represents the likelihood that the output of a machine learning model is correct.

## `neptune-ml:modelType` predicate
<a name="machine-learning-sparql-inference-predicates-modelType"></a>

The `neptune-ml:modelType` predicate specifies the type of machine learning model being trained:
+ `OBJECT_CLASSIFICATION`
+ `OBJECT_REGRESSION`
+ `OBJECT_PREDICTION`
+ `SUBJECT_PREDICTION`

## `neptune-ml:input` predicate
<a name="machine-learning-sparql-inference-predicates-input"></a>

The `neptune-ml:input` predicate refers to the list of URIs used as inputs for Neptune ML.

## `neptune-ml:output` predicate
<a name="machine-learning-sparql-inference-predicates-output"></a>

The `neptune-ml:output` predicate refers to the list of binding sets where Neptune ML returns results.

## `neptune-ml:predicate` predicate
<a name="machine-learning-sparql-inference-predicates-predicate"></a>

The `neptune-ml:predicate` predicate is used differently depending on the task being performed:
+ For **object or subject prediction**: defines the type of predicate (the edge or relationship type).
+ For **object classification and regression**: defines the literal (property) we want to predict.

## `neptune-ml:batchSize` predicate
<a name="machine-learning-sparql-inference-predicates-batchSize"></a>

The `neptune-ml:batchSize` specifies the input size for the remote service call.

# SPARQL object classification examples
<a name="machine-learning-sparql-inference-object-classification"></a>

For SPARQL object classification in Neptune ML, the model is trained on one of the predicate values. This is useful where that predicate is not already present with a given subject.

Only categorical predicate values can be inferred using the object classification model.

The following query seeks to predict the <http://www.example.org/team> predicate value for all the inputs of type `foaf:Person`:

```
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:modelType 'OBJECT_CLASSIFICATION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/team> ;
                      neptune-ml:output ?output .
  }
}
```

This query can be customized as follows:

```
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:endpoint 'node-prediction-account-balance-endpoint' ;
                      neptune-ml:iamRoleArn 'arn:aws:iam::0123456789:role/sagemaker-role' ;

                      neptune-ml:batchSize "40"^^xsd:integer ;
                      neptune-ml:timeout "1000"^^xsd:integer ;

                      neptune-ml:modelType 'OBJECT_CLASSIFICATION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/team> ;
                      neptune-ml:output ?output .
  }
}
```

# SPARQL object regression examples
<a name="machine-learning-sparql-inference-object-regression"></a>

Object regression is similar to object classification, except that a numerical predicate value inferred from the regression model for each node. You can use the same SPARQL queries for object regression as for object classification with the exception that `the Neptune#ml.limit` and `Neptune#ml.threshold` predicates are not applicable.

The following query seeks to predict the <http://www.example.org/accountbalance> predicate value for all the inputs of type `foaf:Person`:

```
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:modelType 'OBJECT_REGRESSION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/accountbalance> ;
                      neptune-ml:output ?output .
  }
}
```

This query can be customized as follows:

```
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:endpoint 'node-prediction-account-balance-endpoint' ;
                      neptune-ml:iamRoleArn 'arn:aws:iam::0123456789:role/sagemaker-role' ;

                      neptune-ml:batchSize "40"^^xsd:integer ;
                      neptune-ml:timeout "1000"^^xsd:integer ;

                      neptune-ml:modelType 'OBJECT_REGRESSION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/accountbalance> ;
                      neptune-ml:output ?output .
  }
}
```

# SPARQL object prediction example
<a name="machine-learning-sparql-inference-object-prediction"></a>

*Object prediction* predicts the object value for a given subject and predicate.

The following object-prediction query seeks to predict what movie the input of type `foaf:Person` would like:

```
?x a foaf:Person .
?x   <http://www.example.org/likes> ?m .
?m a <http://www.example.org/movie> .

## Query
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:modelType 'OBJECT_PREDICTION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/likes> ;
                      neptune-ml:output ?output ;
                      neptune-ml:outputClass <http://www.example.org/movie> .
  }
}
```

The query itself could be customized as follows:

```
SELECT * WHERE { ?input a foaf:Person .
  SERVICE neptune-ml:inference {
    neptune-ml:config neptune-ml:endpoint 'node-prediction-user-movie-prediction-endpoint' ;
                      neptune-ml:iamRoleArn 'arn:aws:iam::0123456789:role/sagemaker-role' ;

                      neptune-ml:limit "5"^^xsd:integer ;
                      neptune-ml:batchSize "40"^^xsd:integer ;
                      neptune-ml:threshold "0.1"^^xsd:double ;
                      neptune-ml:timeout "1000"^^xsd:integer ;
                      neptune-ml:outputScore ?score ;

                      neptune-ml:modelType 'OBJECT_PREDICTION' ;
                      neptune-ml:input ?input ;
                      neptune-ml:predicate <http://www.example.org/likes> ;
                      neptune-ml:output ?output ;
                      neptune-ml:outputClass <http://www.example.org/movie> .
  }
}
```

# SPARQL subject prediction example
<a name="machine-learning-sparql-inference-subject-prediction"></a>

*Subject prediction* predicts the subject given a predicate and an object.

For example, the following query predicts who (of type `foaf:User`) will watch a given movie:

```
SELECT * WHERE { ?input (a foaf:Movie) .
    SERVICE neptune-ml:inference {
        neptune-ml:config neptune-ml:modelType 'SUBJECT_PREDICTION' ;
                          neptune-ml:input ?input ;
                          neptune-ml:predicate <http://aws.amazon.com/neptune/csv2rdf/object_Property/rated> ;
                          neptune-ml:output ?output ;
                          neptune-ml:outputClass <http://aws.amazon.com/neptune/csv2rdf/class/User> ;        }
}
```

# List of exceptions for Neptune ML SPARQL inference queries
<a name="machine-learning-sparql-exceptions"></a>

****
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference expects at least 1 value for the parameter (parameter name), found zero.`
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference expects at most 1 value for the parameter (parameter name), found (a number) values.`
+ **`BadRequestException`**   –   *Message*: `Invalid predicate (predicate name) provided for external service http://aws.amazon.com/neptune/vocab/v01/services/ml#inference query.`
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference expects the predicate (predicate name) to be defined`.
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference expects the value of (parameter) (parameter name) to be a variable, found: (type)"`
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference expects the input (parameter name) to be a constant, found: (type)`.
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference is expected to return only 1 value`.
+ **`BadRequestException`**   –   *Message*: `"The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference only allows StatementPatternNodes`.
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference does not allow the predicate (predicate name)`.
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference predicates cannot be variables, found: (type)`.
+ **`BadRequestException`**   –   *Message*: `The SERVICE http://aws.amazon.com/neptune/vocab/v01/services/ml#inference predicates are expected to be part of the namespace (namespace name), found: (namespace name)`.

# Neptune ML management API reference
<a name="machine-learning-api-reference"></a>

**Contents**
+ [The dataprocessing command](machine-learning-api-dataprocessing.md)
  + [Create a data-processing job](machine-learning-api-dataprocessing.md#machine-learning-api-dataprocessing-create-job)
  + [Get job status](machine-learning-api-dataprocessing.md#machine-learning-api-dataprocessing-get-job-status)
  + [Stop a job](machine-learning-api-dataprocessing.md#machine-learning-api-dataprocessing-stop-job)
  + [Listing jobs](machine-learning-api-dataprocessing.md#machine-learning-api-dataprocessing-list-jobs)
+ [The modeltraining command](machine-learning-api-modeltraining.md)
  + [Create a model-training job](machine-learning-api-modeltraining.md#machine-learning-api-modeltraining-create-job)
  + [Get job status](machine-learning-api-modeltraining.md#machine-learning-api-modeltraining-get-job-status)
  + [Stop a job](machine-learning-api-modeltraining.md#machine-learning-api-modeltraining-stop-job)
  + [Listing jobs](machine-learning-api-modeltraining.md#machine-learning-api-modeltraining-list-jobs)
+ [The modeltransform command](machine-learning-api-modeltransform.md)
  + [Create a model-transform job](machine-learning-api-modeltransform.md#machine-learning-api-modeltransform-create-job)
  + [Get job status](machine-learning-api-modeltransform.md#machine-learning-api-modeltransform-get-job-status)
  + [Stop a job](machine-learning-api-modeltransform.md#machine-learning-api-modeltransform-stop-job)
  + [Listing jobs](machine-learning-api-modeltransform.md#machine-learning-api-modeltransform-list-jobs)
+ [The endpoints command](machine-learning-api-endpoints.md)
  + [Create an inference endpoint](machine-learning-api-endpoints.md#machine-learning-api-endpoints-create-job)
  + [Get endpoint status](machine-learning-api-endpoints.md#machine-learning-api-endpoints-get-endpoint-status)
  + [Delete an endpoint](machine-learning-api-endpoints.md#machine-learning-api-endpoints-delete-endpoint)
  + [Listing inference endpoints](machine-learning-api-endpoints.md#machine-learning-api-endpoints-list-endpoints)
+ [Exceptions](machine-learning-api-exceptions.md)

# Data processing using the `dataprocessing` command
<a name="machine-learning-api-dataprocessing"></a>

You use the Neptune ML `dataprocessing` command to create a data processing job, check its status, stop it, or list all active data-processing jobs.

## Creating a data-processing job using the Neptune ML `dataprocessing` command
<a name="machine-learning-api-dataprocessing-create-job"></a>

A typical Neptune ML `dataprocessing` command for creating a new job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --input-data-s3-location "s3://(S3 bucket name)/(path to your input folder)" \
  --id "(a job ID for the new job)" \
  --processed-data-s3-location "s3://(S3 bucket name)/(path to your output folder)"
```

For more information, see [start-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_data_processing_job(
    inputDataS3Location='s3://(S3 bucket name)/(path to your input folder)',
    id='(a job ID for the new job)',
    processedDataS3Location='s3://(S3 bucket name)/(path to your output folder)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/dataprocessing \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for the new job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)"
      }'
```

------

A command to initiate incremental re-processing looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --input-data-s3-location "s3://(S3 bucket name)/(path to your input folder)" \
  --id "(a job ID for this job)" \
  --processed-data-s3-location "s3://(S3 bucket name)/(path to your output folder)" \
  --previous-data-processing-job-id "(the job ID of a previously completed job to update)"
```

For more information, see [start-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_data_processing_job(
    inputDataS3Location='s3://(S3 bucket name)/(path to your input folder)',
    id='(a job ID for this job)',
    processedDataS3Location='s3://(S3 bucket name)/(path to your output folder)',
    previousDataProcessingJobId='(the job ID of a previously completed job to update)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for this job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)",
        "previousDataProcessingJobId" : "(the job ID of a previously completed job to update)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/dataprocessing \
  -H 'Content-Type: application/json' \
  -d '{
        "inputDataS3Location" : "s3://(S3 bucket name)/(path to your input folder)",
        "id" : "(a job ID for this job)",
        "processedDataS3Location" : "s3://(S3 bucket name)/(path to your output folder)",
        "previousDataProcessingJobId" : "(the job ID of a previously completed job to update)"
      }'
```

------

**Parameters for `dataprocessing` job creation**
+ **`id`**   –   (*Optional*) A unique identifier for the new job.

  *Type*: string. *Default*: An autogenerated UUID.
+ **`previousDataProcessingJobId`**   –   (*Optional*) The job ID of a completed data processing job run on an earlier version of the data.

  *Type*: string. *Default*: *none*.

  *Note*: Use this for incremental data processing, to update the model when graph data has changed (but not when data has been deleted).
+ **`inputDataS3Location`**   –   (*Required*) The URI of the Amazon S3 location where you want SageMaker AI to download the data needed to run the data processing job.

  *Type*: string.
+ **`processedDataS3Location`**   –   (*Required*) The URI of the Amazon S3 location where you want SageMaker AI to save the results of a data processing job.

  *Type*: string.
+ **`sagemakerIamRoleArn`**   –   (*Optional*) The ARN of an IAM role for SageMaker AI execution.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The Amazon Resource Name (ARN) of an IAM role that SageMaker AI can assume to perform tasks on your behalf.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`processingInstanceType`**   –   (*Optional*) The type of ML instance used during data processing. Its memory should be large enough to hold the processed dataset.

  *Type*: string. *Default*: the smallest `ml.r5` type whose memory is ten times larger than the size of the exported graph data on disk.

  *Note*: Neptune ML can select the instance type automatically. See [Selecting an instance for data processing](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-processing-instance-size).
+ **`processingInstanceVolumeSizeInGB`**   –   (*Optional*) The disk volume size of the processing instance. Both input data and processed data are stored on disk, so the volume size must be large enough to hold both data sets.

  *Type*: integer. *Default*: `0`.

  *Note*: If not specified or 0, Neptune ML chooses the volume size automatically based on the data size.
+ **`processingTimeOutInSeconds`**   –   (*Optional*) Timeout in seconds for the data processing job.

  *Type*: integer. *Default*: `86,400` (1 day).
+ **`modelType`**   –   (*Optional*) One of the two model types that Neptune ML currently supports: heterogeneous graph models (`heterogeneous`), and knowledge graph (`kge`).

  *Type*: string. *Default*: *none*.

  *Note*: If not specified, Neptune ML chooses the model type automatically based on the data.
+ **`configFileName`**   –   (*Optional*) A data specification file that describes how to load the exported graph data for training. The file is automatically generated by the Neptune export toolkit.

  *Type*: string. *Default*: `training-data-configuration.json`.
+ **`subnets`**   –   (*Optional*) The IDs of the subnets in the Neptune VPC.

  *Type*: list of strings. *Default*: *none*.
+ **`securityGroupIds`**   –   (*Optional*) The VPC security group IDs.

  *Type*: list of strings. *Default*: *none*.
+ **`volumeEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt data on the storage volume attached to the ML compute instances that run the processing job.

  *Type*: string. *Default*: *none*.
+ **`enableInterContainerTrafficEncryption`**   –   (*Optional*) Enable or disable inter-container traffic encryption in training or hyper-parameter tuning jobs.

  *Type*: boolean. *Default*: *True*.
**Note**  
The `enableInterContainerTrafficEncryption` parameter is only available in [engine release 1.2.0.2.R3](engine-releases-1.2.0.2.R3.md).
+ **`s3OutputEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt the output of the training job.

  *Type*: string. *Default*: *none*.

## Getting the status of a data-processing job using the Neptune ML `dataprocessing` command
<a name="machine-learning-api-dataprocessing-get-job-status"></a>

A sample Neptune ML `dataprocessing` command for the status of a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata get-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

For more information, see [get-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/get-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.get_ml_data_processing_job(
    id='(the job ID)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  "https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID)" \
  | python -m json.tool
```

------

**Parameters for `dataprocessing` job status**
+ **`id`**   –   (*Required*) The unique identifier of the data-processing job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

## Stopping a data-processing job using the Neptune ML `dataprocessing` command
<a name="machine-learning-api-dataprocessing-stop-job"></a>

A sample Neptune ML `dataprocessing` command for stopping a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata cancel-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

To also clean up Amazon S3 artifacts:

```
aws neptunedata cancel-ml-data-processing-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)" \
  --clean
```

For more information, see [cancel-ml-data-processing-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/cancel-ml-data-processing-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.cancel_ml_data_processing_job(
    id='(the job ID)',
    clean=True
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

To also clean up Amazon S3 artifacts:

```
awscurl "https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID)?clean=true" \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID)"
```

Or this:

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/dataprocessing/(the job ID)?clean=true"
```

------

**Parameters for `dataprocessing` stop job**
+ **`id`**   –   (*Required*) The unique identifier of the data-processing job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`clean`**   –   (*Optional*) This flag specifies that all Amazon S3 artifacts should be deleted when the job is stopped.

  *Type*: Boolean. *Default*: `FALSE`.

## Listing active data-processing jobs using the Neptune ML `dataprocessing` command
<a name="machine-learning-api-dataprocessing-list-jobs"></a>

A sample Neptune ML `dataprocessing` command for listing active jobs looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata list-ml-data-processing-jobs \
  --endpoint-url https://your-neptune-endpoint:port
```

To limit the number of results:

```
aws neptunedata list-ml-data-processing-jobs \
  --endpoint-url https://your-neptune-endpoint:port \
  --max-items 3
```

For more information, see [list-ml-data-processing-jobs](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/list-ml-data-processing-jobs.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.list_ml_data_processing_jobs(
    maxItems=3
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/dataprocessing \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

To limit the number of results:

```
awscurl "https://your-neptune-endpoint:port/ml/dataprocessing?maxItems=3" \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s "https://your-neptune-endpoint:port/ml/dataprocessing"
```

Or this:

```
curl -s "https://your-neptune-endpoint:port/ml/dataprocessing?maxItems=3"
```

------

**Parameters for `dataprocessing` list jobs**
+ **`maxItems`**   –   (*Optional*) The maximum number of items to return.

  *Type*: integer. *Default*: `10`. *Maximum allowed value*: `1024`.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

# Model training using the `modeltraining` command
<a name="machine-learning-api-modeltraining"></a>

You use the Neptune ML `modeltraining` command to create a model training job, check its status, stop it, or list all active model-training jobs.

## Creating a model-training job using the Neptune ML `modeltraining` command
<a name="machine-learning-api-modeltraining-create-job"></a>

A Neptune ML `modeltraining` command for creating a completely new job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your S3 bucket)/neptune-model-graph-autotrainer'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer"
      }'
```

------

A Neptune ML `modeltraining` command for creating an update job for incremental model training looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your S3 bucket)/neptune-model-graph-autotrainer" \
  --previous-model-training-job-id "(the job ID of a completed model-training job to update)"
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your S3 bucket)/neptune-model-graph-autotrainer',
    previousModelTrainingJobId='(the job ID of a completed model-training job to update)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer",
        "previousModelTrainingJobId" : "(the job ID of a completed model-training job to update)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your S3 bucket)/neptune-model-graph-autotrainer",
        "previousModelTrainingJobId" : "(the job ID of a completed model-training job to update)"
      }'
```

------

A Neptune ML `modeltraining` command for creating a new job with user provided custom model implementation looks like: 

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-training job ID)" \
  --data-processing-job-id "(the data-processing job-id of a completed job)" \
  --train-model-s3-location "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer" \
  --model-name "custom" \
  --custom-model-training-parameters '{
    "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
    "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
    "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
  }'
```

For more information, see [start-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_training_job(
    id='(a unique model-training job ID)',
    dataProcessingJobId='(the data-processing job-id of a completed job)',
    trainModelS3Location='s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer',
    modelName='custom',
    customModelTrainingParameters={
        'sourceS3DirectoryPath': 's3://(your Amazon S3 bucket)/(path to your Python module)',
        'trainingEntryPointScript': '(your training script entry-point name in the Python module)',
        'transformEntryPointScript': '(your transform script entry-point name in the Python module)'
    }
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltraining \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-training job ID)",
        "dataProcessingJobId" : "(the data-processing job-id of a completed job)",
        "trainModelS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-graph-autotrainer",
        "modelName": "custom",
        "customModelTrainingParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "trainingEntryPointScript": "(your training script entry-point name in the Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

------

**Parameters for `modeltraining` job creation**
+ **`id`**   –   (*Optional*) A unique identifier for the new job.

  *Type*: string. *Default*: An autogenerated UUID.
+ **`dataProcessingJobId`**   –   (*Required*) The job Id of the completed data-processing job that has created the data that the training will work with.

  *Type*: string.
+ **`trainModelS3Location`**   –   (*Required*) The location in Amazon S3 where the model artifacts are to be stored.

  *Type*: string.
+ **`previousModelTrainingJobId`**   –   (*Optional*) The job ID of a completed model-training job that you want to update incrementally based on updated data.

  *Type*: string. *Default*: *none*.
+ **`sagemakerIamRoleArn`**   –   (*Optional*) The ARN of an IAM role for SageMaker AI execution.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`modelName`**   –   (*Optional*) The model type for training. By default the ML model is automatically based on the `modelType` used in data processing, but you can specify a different model type here.

  *Type*: string. *Default*: `rgcn` for heterogeneous graphs and `kge` for knowledge graphs. *Valid values*: For heterogeneous graphs: `rgcn`. For `kge` graphs: `transe`, `distmult`, or `rotate`. For a custom model implementation: `custom`.
+ **`baseProcessingInstanceType`**   –   (*Optional*) The type of ML instance used in preparing and managing training of ML models.

  *Type*: string. *Note*: This is a CPU instance chosen based on memory requirements for processing the training data and model. See [Selecting an instance for model training and model transform](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size).
+ **`trainingInstanceType`**   –   (*Optional*) The type of ML instance used for model training. All Neptune ML models support CPU, GPU, and multiGPU training.

  *Type*: string. *Default*: `ml.p3.2xlarge`.

  *Note*: Choosing the right instance type for training depends on the task type, graph size, and your budget. See [Selecting an instance for model training and model transform](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size).
+ **`trainingInstanceVolumeSizeInGB`**   –   (*Optional*) The disk volume size of the training instance. Both input data and the output model are stored on disk, so the volume size must be large enough to hold both data sets.

  *Type*: integer. *Default*: `0`.

  *Note*: If not specified or 0, Neptune ML selects a disk volume size based on the recommendation generated in the data processing step. See [Selecting an instance for model training and model transform](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size).
+ **`trainingTimeOutInSeconds`**   –   (*Optional*) Timeout in seconds for the training job.

  *Type*: integer. *Default*: `86,400` (1 day).
+ **`maxHPONumberOfTrainingJobs`**   –   Maximum total number of training jobs to start for the hyperparameter tuning job.

  *Type*: integer. *Default*: `2`.

  *Note*: Neptune ML automatically tunes the hyper-parameters of the machine learning model. To obtain a model that performs well, use at least 10 jobs (in other words, set `maxHPONumberOfTrainingJobs` to 10). In general, the more tuning runs, the better the results.
+ **`maxHPOParallelTrainingJobs`**   –   Maximum number of parallel training jobs to start for the hyperparameter tuning job.

  *Type*: integer. *Default*: `2`.

  *Note*: The number of parallel jobs you can run is limited by the available resources on your training instance.
+ **`subnets`**   –   (*Optional*) The IDs of the subnets in the Neptune VPC.

  *Type*: list of strings. *Default*: *none*.
+ **`securityGroupIds`**   –   (*Optional*) The VPC security group IDs.

  *Type*: list of strings. *Default*: *none*.
+ **`volumeEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt data on the storage volume attached to the ML compute instances that run the training job.

  *Type*: string. *Default*: *none*.
+ **`s3OutputEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt the output of the processing job.

  *Type*: string. *Default*: *none*.
+ **`enableInterContainerTrafficEncryption`**   –   (*Optional*) Enable or disable inter-container traffic encryption in training or hyper-parameter tuning jobs.

  *Type*: boolean. *Default*: *True*.
**Note**  
The `enableInterContainerTrafficEncryption` parameter is only available in [engine release 1.2.0.2.R3](engine-releases-1.2.0.2.R3.md).
+ **`enableManagedSpotTraining`**   –   (*Optional*) Optimizes the cost of training machine learning models by using Amazon Elastic Compute Cloud spot instances. For more information, see [Managed Spot Training in Amazon SageMaker](https://docs.aws.amazon.com/sagemaker/latest/dg/model-managed-spot-training.html).

  *Type*: Boolean. *Default*: *False*.
+ **`customModelTrainingParameters`**  –   (*Optional*) The configuration for custom model training. This is a JSON object with the following fields:
  + **`sourceS3DirectoryPath`**   –   (*Required*) The path to the Amazon S3 location where the Python module implementing your model is located. This must point to a valid existing Amazon S3 location that contains, at a minimum, a training script, a transform script, and a `model-hpo-configuration.json` file.
  + **`trainingEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that performs model training and takes hyperparameters as command-line arguments, including fixed hyperparameters.

    *Default*: `training.py`.
  + **`transformEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that should be run after the best model from the hyperparameter search has been identified, to compute the model artifacts necessary for model deployment. It should be able to run with no command-line arguments.

    *Default*: `transform.py`.
+ **`maxWaitTime`**   –   (*Optional*) The maximum time to wait, in seconds, when performing model training using spot instances. Should be greater than `trainingTimeOutInSeconds`.

  *Type*: integer.

## Getting the status of a model-training job using the Neptune ML `modeltraining` command
<a name="machine-learning-api-modeltraining-get-job-status"></a>

A sample Neptune ML `modeltraining` command for the status of a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata get-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

For more information, see [get-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/get-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.get_ml_model_training_job(
    id='(the job ID)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  "https://your-neptune-endpoint:port/ml/modeltraining/(the job ID)" \
  | python -m json.tool
```

------

**Parameters for `modeltraining` job status**
+ **`id`**   –   (*Required*) The unique identifier of the model-training job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

## Stopping a model-training job using the Neptune ML `modeltraining` command
<a name="machine-learning-api-modeltraining-stop-job"></a>

A sample Neptune ML `modeltraining` command for stopping a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata cancel-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

To also clean up Amazon S3 artifacts:

```
aws neptunedata cancel-ml-model-training-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)" \
  --clean
```

For more information, see [cancel-ml-model-training-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/cancel-ml-model-training-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.cancel_ml_model_training_job(
    id='(the job ID)',
    clean=True
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

To also clean up Amazon S3 artifacts:

```
awscurl "https://your-neptune-endpoint:port/ml/modeltraining/(the job ID)?clean=true" \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/modeltraining/(the job ID)"
```

Or this:

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/modeltraining/(the job ID)?clean=true"
```

------

**Parameters for `modeltraining` stop job**
+ **`id`**   –   (*Required*) The unique identifier of the model-training job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`clean`**   –   (*Optional*) This flag specifies that all Amazon S3 artifacts should be deleted when the job is stopped.

  *Type*: Boolean. *Default*: `FALSE`.

## Listing active model-training jobs using the Neptune ML `modeltraining` command
<a name="machine-learning-api-modeltraining-list-jobs"></a>

A sample Neptune ML `modeltraining` command for listing active jobs looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata list-ml-model-training-jobs \
  --endpoint-url https://your-neptune-endpoint:port
```

To limit the number of results:

```
aws neptunedata list-ml-model-training-jobs \
  --endpoint-url https://your-neptune-endpoint:port \
  --max-items 3
```

For more information, see [list-ml-model-training-jobs](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/list-ml-model-training-jobs.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.list_ml_model_training_jobs(
    maxItems=3
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltraining \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

To limit the number of results:

```
awscurl "https://your-neptune-endpoint:port/ml/modeltraining?maxItems=3" \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s "https://your-neptune-endpoint:port/ml/modeltraining" | python -m json.tool
```

Or this:

```
curl -s "https://your-neptune-endpoint:port/ml/modeltraining?maxItems=3" | python -m json.tool
```

------

**Parameters for `modeltraining` list jobs**
+ **`maxItems`**   –   (*Optional*) The maximum number of items to return.

  *Type*: integer. *Default*: `10`. *Maximum allowed value*: `1024`.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

# Model transform using the `modeltransform` command
<a name="machine-learning-api-modeltransform"></a>

You use the Neptune ML `modeltransform` command to create a model transform job, check its status, stop it, or list all active model-transform jobs.

## Creating a model-transform job using the Neptune ML `modeltransform` command
<a name="machine-learning-api-modeltransform-create-job"></a>

A Neptune ML `modeltransform` command for creating an incremental transform job, without model retraining, looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --data-processing-job-id "(the job-id of a completed data-processing job)" \
  --ml-model-training-job-id "(the job-id of a completed model-training job)" \
  --model-transform-output-s3-location "s3://(your S3 bucket)/neptune-model-transform"
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    dataProcessingJobId='(the job-id of a completed data-processing job)',
    mlModelTrainingJobId='(the job-id of a completed model-training job)',
    modelTransformOutputS3Location='s3://(your S3 bucket)/neptune-model-transform'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "dataProcessingJobId" : "(the job-id of a completed data-processing job)",
        "mlModelTrainingJobId" : "(the job-id of a completed model-training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "dataProcessingJobId" : "(the job-id of a completed data-processing job)",
        "mlModelTrainingJobId" : "(the job-id of a completed model-training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform"
      }'
```

------

A Neptune ML `modeltransform` command for creating a job from a completed SageMaker AI training job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --training-job-name "(name of a completed SageMaker training job)" \
  --model-transform-output-s3-location "s3://(your S3 bucket)/neptune-model-transform"
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    trainingJobName='(name of a completed SageMaker training job)',
    modelTransformOutputS3Location='s3://(your S3 bucket)/neptune-model-transform'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your S3 bucket)/neptune-model-transform"
      }'
```

------

A Neptune ML `modeltransform` command for creating a job that uses a custom model implementation looks like:

------
#### [ AWS CLI ]

```
aws neptunedata start-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique model-transform job ID)" \
  --training-job-name "(name of a completed SageMaker training job)" \
  --model-transform-output-s3-location "s3://(your Amazon S3 bucket)/neptune-model-transform/" \
  --custom-model-transform-parameters '{
    "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
    "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
  }'
```

For more information, see [start-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/start-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.start_ml_model_transform_job(
    id='(a unique model-transform job ID)',
    trainingJobName='(name of a completed SageMaker training job)',
    modelTransformOutputS3Location='s3://(your Amazon S3 bucket)/neptune-model-transform/',
    customModelTransformParameters={
        'sourceS3DirectoryPath': 's3://(your Amazon S3 bucket)/(path to your Python module)',
        'transformEntryPointScript': '(your transform script entry-point name in the Python module)'
    }
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-transform/",
        "customModelTransformParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/modeltransform \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique model-transform job ID)",
        "trainingJobName" : "(name of a completed SageMaker training job)",
        "modelTransformOutputS3Location" : "s3://(your Amazon S3 bucket)/neptune-model-transform/",
        "customModelTransformParameters" : {
          "sourceS3DirectoryPath": "s3://(your Amazon S3 bucket)/(path to your Python module)",
          "transformEntryPointScript": "(your transform script entry-point name in the Python module)"
        }
      }'
```

------

**Parameters for `modeltransform` job creation**
+ **`id`**   –   (*Optional*) A unique identifier for the new job.

  *Type*: string. *Default*: An autogenerated UUID.
+ **`dataProcessingJobId`**   –   The job Id of a completed data-processing job.

  *Type*: string.

  *Note*: You must include either both `dataProcessingJobId` and `mlModelTrainingJobId`, or `trainingJobName`.
+ **`mlModelTrainingJobId`**   –   The job Id of a completed model-training job.

  *Type*: string.

  *Note*: You must include either both `dataProcessingJobId` and `mlModelTrainingJobId`, or `trainingJobName`.
+ **`trainingJobName`**   –   The name of a completed SageMaker AI training job.

  *Type*: string.

  *Note*: You must include either both the `dataProcessingJobId` and the `mlModelTrainingJobId` parameters, or the `trainingJobName` parameter.
+ **`sagemakerIamRoleArn`**   –   (*Optional*) The ARN of an IAM role for SageMaker AI execution.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`customModelTransformParameters `**   –   (*Optional*) Configuration information for a model transform using a custom model. The `customModelTransformParameters` object contains the following fields, which must have values compatible with the saved model parameters from the training job:
  + **`sourceS3DirectoryPath`**   –   (*Required*) The path to the Amazon S3 location where the Python module implementing your model is located. This must point to a valid existing Amazon S3 location that contains, at a minimum, a training script, a transform script, and a `model-hpo-configuration.json` file.
  + **`transformEntryPointScript`**   –   (*Optional*) The name of the entry point in your module of a script that should be run after the best model from the hyperparameter search has been identified, to compute the model artifacts necessary for model deployment. It should be able to run with no command-line arguments.

    *Default*: `transform.py`.
+ **`baseProcessingInstanceType`**   –   (*Optional*) The type of ML instance used in preparing and managing training of ML models.

  *Type*: string. *Note*: This is a CPU instance chosen based on memory requirements for processing the transform data and model. See [Selecting an instance for model training and model transform](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size).
+ **`baseProcessingInstanceVolumeSizeInGB`**   –   (*Optional*) The disk volume size of the training instance. Both input data and the output model are stored on disk, so the volume size must be large enough to hold both data sets.

  *Type*: integer. *Default*: `0`.

  *Note*: If not specified or 0, Neptune ML selects a disk volume size based on the recommendation generated in the data processing step. See [Selecting an instance for model training and model transform](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size).
+ **`subnets`**   –   (*Optional*) The IDs of the subnets in the Neptune VPC.

  *Type*: list of strings. *Default*: *none*.
+ **`securityGroupIds`**   –   (*Optional*) The VPC security group IDs.

  *Type*: list of strings. *Default*: *none*.
+ **`volumeEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt data on the storage volume attached to the ML compute instances that run the transform job.

  *Type*: string. *Default*: *none*.
+ **`enableInterContainerTrafficEncryption`**   –   (*Optional*) Enable or disable inter-container traffic encryption in training or hyper-parameter tuning jobs.

  *Type*: boolean. *Default*: *True*.
**Note**  
The `enableInterContainerTrafficEncryption` parameter is only available in [engine release 1.2.0.2.R3](engine-releases-1.2.0.2.R3.md).
+ **`s3OutputEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt the output of the processing job.

  *Type*: string. *Default*: *none*.

## Getting the status of a model-transform job using the Neptune ML `modeltransform` command
<a name="machine-learning-api-modeltransform-get-job-status"></a>

A sample Neptune ML `modeltransform` command for the status of a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata get-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

For more information, see [get-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/get-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.get_ml_model_transform_job(
    id='(the job ID)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  "https://your-neptune-endpoint:port/ml/modeltransform/(the job ID)" \
  | python -m json.tool
```

------

**Parameters for `modeltransform` job status**
+ **`id`**   –   (*Required*) The unique identifier of the model-transform job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

## Stopping a model-transform job using the Neptune ML `modeltransform` command
<a name="machine-learning-api-modeltransform-stop-job"></a>

A sample Neptune ML `modeltransform` command for stopping a job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata cancel-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)"
```

To also clean up Amazon S3 artifacts:

```
aws neptunedata cancel-ml-model-transform-job \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the job ID)" \
  --clean
```

For more information, see [cancel-ml-model-transform-job](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/cancel-ml-model-transform-job.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.cancel_ml_model_transform_job(
    id='(the job ID)',
    clean=True
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform/(the job ID) \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

To also clean up Amazon S3 artifacts:

```
awscurl "https://your-neptune-endpoint:port/ml/modeltransform/(the job ID)?clean=true" \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/modeltransform/(the job ID)"
```

Or this:

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/modeltransform/(the job ID)?clean=true"
```

------

**Parameters for `modeltransform` stop job**
+ **`id`**   –   (*Required*) The unique identifier of the model-transform job.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.
+ **`clean`**   –   (*Optional*) This flag specifies that all Amazon S3 artifacts should be deleted when the job is stopped.

  *Type*: Boolean. *Default*: `FALSE`.

## Listing active model-transform jobs using the Neptune ML `modeltransform` command
<a name="machine-learning-api-modeltransform-list-jobs"></a>

A sample Neptune ML `modeltransform` command for listing active jobs looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata list-ml-model-transform-jobs \
  --endpoint-url https://your-neptune-endpoint:port
```

To limit the number of results:

```
aws neptunedata list-ml-model-transform-jobs \
  --endpoint-url https://your-neptune-endpoint:port \
  --max-items 3
```

For more information, see [list-ml-model-transform-jobs](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/list-ml-model-transform-jobs.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.list_ml_model_transform_jobs(
    maxItems=3
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/modeltransform \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

To limit the number of results:

```
awscurl "https://your-neptune-endpoint:port/ml/modeltransform?maxItems=3" \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s "https://your-neptune-endpoint:port/ml/modeltransform" | python -m json.tool
```

Or this:

```
curl -s "https://your-neptune-endpoint:port/ml/modeltransform?maxItems=3" | python -m json.tool
```

------

**Parameters for `modeltransform` list jobs**
+ **`maxItems`**   –   (*Optional*) The maximum number of items to return.

  *Type*: integer. *Default*: `10`. *Maximum allowed value*: `1024`.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role that provides Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will occur.

# Managing inference endpoints using the `endpoints` command
<a name="machine-learning-api-endpoints"></a>

You use the Neptune ML `endpoints` command to create an inference endpoint, check its status, delete it, or list existing inference endpoints.

## Creating an inference endpoint using the Neptune ML `endpoints` command
<a name="machine-learning-api-endpoints-create-job"></a>

A Neptune ML `endpoints` command for creating an inference endpoint from a model created by a training job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --ml-model-training-job-id "(the model-training job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    mlModelTrainingJobId='(the model-training job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

------

A Neptune ML `endpoints` command for updating an existing inference endpoint from a model created by a training job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --update \
  --ml-model-training-job-id "(the model-training job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    update=True,
    mlModelTrainingJobId='(the model-training job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "update" : "true",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "update" : "true",
        "mlModelTrainingJobId": "(the model-training job-id of a completed job)"
      }'
```

------

A Neptune ML `endpoints` command for creating an inference endpoint from a model created by a model-transform job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --ml-model-transform-job-id "(the model-transform job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    mlModelTransformJobId='(the model-transform job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

------

A Neptune ML `endpoints` command for updating an existing inference endpoint from a model created by a model-transform job looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata create-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(a unique ID for the new endpoint)" \
  --update \
  --ml-model-transform-job-id "(the model-transform job-id of a completed job)"
```

For more information, see [create-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/create-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.create_ml_endpoint(
    id='(a unique ID for the new endpoint)',
    update=True,
    mlModelTransformJobId='(the model-transform job-id of a completed job)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "update" : "true",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl \
  -X POST https://your-neptune-endpoint:port/ml/endpoints \
  -H 'Content-Type: application/json' \
  -d '{
        "id" : "(a unique ID for the new endpoint)",
        "update" : "true",
        "mlModelTransformJobId": "(the model-transform job-id of a completed job)"
      }'
```

------

**Parameters for `endpoints` inference endpoint creation**
+ **`id`**   –   (*Optional*) A unique identifier for the new inference endpoint.

  *Type*: string. *Default*: An autogenerated timestamped name.
+ **`mlModelTrainingJobId`**   –   The job Id of the completed model-training job that has created the model that the inference endpoint will point to.

  *Type*: string.

  *Note*: You must supply either the `mlModelTrainingJobId` or the `mlModelTransformJobId`.
+ **`mlModelTransformJobId`**   –   The job Id of the completed model-transform job.

  *Type*: string.

  *Note*: You must supply either the `mlModelTrainingJobId` or the `mlModelTransformJobId`.
+ **`update`**   –   (*Optional*) If present, this parameter indicates that this is an update request.

  *Type*: Boolean. *Default*: `false`

  *Note*: You must supply either the `mlModelTrainingJobId` or the `mlModelTransformJobId`.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role providing Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will be thrown.
+ **`modelName`**   –   (*Optional*) Model type for training. By default the ML model is automatically based on the `modelType` used in data processing, but you can specify a different model type here.

  *Type*: string. *Default*: `rgcn` for heterogeneous graphs and `kge` for knowledge graphs. *Valid values*: For heterogeneous graphs: `rgcn`. For knowledge graphs: `kge`, `transe`, `distmult`, or `rotate`.
+ **`instanceType`**   –   (*Optional*) The type of ML instance used for online servicing.

  *Type*: string. *Default*: `ml.m5.xlarge`.

  *Note*: Choosing the ML instance for an inference endpoint depends on the task type, the graph size, and your budget. See [Selecting an instance for an inference endpoint](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-inference-endpoint-instance-size).
+ **`instanceCount`**   –   (*Optional*) The minimum number of Amazon EC2 instances to deploy to an endpoint for prediction.

  *Type*: integer. *Default*: `1`.
+ **`volumeEncryptionKMSKey`**   –   (*Optional*) The AWS Key Management Service (AWS KMS) key that SageMaker AI uses to encrypt data on the storage volume attached to the ML compute instance(s) that run the endpoints.

  *Type*: string. *Default*: *none*.

## Getting the status of an inference endpoint using the Neptune ML `endpoints` command
<a name="machine-learning-api-endpoints-get-endpoint-status"></a>

A sample Neptune ML `endpoints` command for the status of an instance endpoint looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata get-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the inference endpoint ID)"
```

For more information, see [get-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/get-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.get_ml_endpoint(
    id='(the inference endpoint ID)'
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID) \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  "https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID)" \
  | python -m json.tool
```

------

**Parameters for `endpoints` instance-endpoint status**
+ **`id`**   –   (*Required*) The unique identifier of the inference endpoint.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role providing Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will be thrown.

## Deleting an instance endpoint using the Neptune ML `endpoints` command
<a name="machine-learning-api-endpoints-delete-endpoint"></a>

A sample Neptune ML `endpoints` command for deleting an instance endpoint looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata delete-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the inference endpoint ID)"
```

To also clean up related artifacts:

```
aws neptunedata delete-ml-endpoint \
  --endpoint-url https://your-neptune-endpoint:port \
  --id "(the inference endpoint ID)" \
  --clean
```

For more information, see [delete-ml-endpoint](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/delete-ml-endpoint.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.delete_ml_endpoint(
    id='(the inference endpoint ID)',
    clean=True
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID) \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

To also clean up related artifacts:

```
awscurl "https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID)?clean=true" \
  --region us-east-1 \
  --service neptune-db \
  -X DELETE
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID)"
```

Or this:

```
curl -s \
  -X DELETE "https://your-neptune-endpoint:port/ml/endpoints/(the inference endpoint ID)?clean=true"
```

------

**Parameters for `endpoints` deleting an inference endpoint**
+ **`id`**   –   (*Required*) The unique identifier of the inference endpoint.

  *Type*: string.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role providing Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will be thrown.
+ **`clean`**   –   (*Optional*) Indicates that all artifacts related to this endpoint should also be deleted.

  *Type*: Boolean. *Default*: `FALSE`.

## Listing inference endpoints using the Neptune ML `endpoints` command
<a name="machine-learning-api-endpoints-list-endpoints"></a>

A Neptune ML `endpoints` command for listing inference endpoints looks like this:

------
#### [ AWS CLI ]

```
aws neptunedata list-ml-endpoints \
  --endpoint-url https://your-neptune-endpoint:port
```

To limit the number of results:

```
aws neptunedata list-ml-endpoints \
  --endpoint-url https://your-neptune-endpoint:port \
  --max-items 3
```

For more information, see [list-ml-endpoints](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/list-ml-endpoints.html) in the AWS CLI Command Reference.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.list_ml_endpoints(
    maxItems=3
)

print(response)
```

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/ml/endpoints \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

To limit the number of results:

```
awscurl "https://your-neptune-endpoint:port/ml/endpoints?maxItems=3" \
  --region us-east-1 \
  --service neptune-db \
  -X GET
```

**Note**  
This example assumes that your AWS credentials are configured in your environment. Replace *us-east-1* with the Region of your Neptune cluster.

------
#### [ curl ]

```
curl -s "https://your-neptune-endpoint:port/ml/endpoints" \
  | python -m json.tool
```

Or this:

```
curl -s "https://your-neptune-endpoint:port/ml/endpoints?maxItems=3" \
  | python -m json.tool
```

------

**Parameters for `dataprocessing` list inference endpoints**
+ **`maxItems`**   –   (*Optional*) The maximum number of items to return.

  *Type*: integer. *Default*: `10`. *Maximum allowed value*: `1024`.
+ **`neptuneIamRoleArn`**   –   (*Optional*) The ARN of an IAM role providing Neptune access to SageMaker AI and Amazon S3 resources.

  *Type*: string. *Note*: This must be listed in your DB cluster parameter group or an error will be thrown.

# Neptune ML management API errors and exceptions
<a name="machine-learning-api-exceptions"></a>

All Neptune ML management API exceptions return a 400 HTTP code. After receiving any of these exceptions, the command that generated the exception should not be retried.

****
+ **`MissingParameterException`**   –   Error message:

  `Required credentials are missing. Please add IAM role to the cluster or pass as a parameter to this request.`
+ **`InvalidParameterException`**   –   Error messages:
  + `Invalid ML instance type.`
  + `Invalid ID provided. ID can be 1-48 alphanumeric characters.`
  + `Invalid ID provided. Must contain only letters, digits, or hyphens.`
  + `Invalid ID provided. Please check whether a resource with the given ID exists.`
  + `Another resource with same ID already exists. Please use a new ID.`
  + `Failed to stop the job because it has already completed or failed.`
+ **`BadRequestException`**   –   Error messages:
  + `Invalid S3 URL or incorrect S3 permissions. Please check your S3 configuration.`
  + `Provided ModelTraining job has not completed.`
  + `Provided SageMaker AI Training job has not completed.`
  + `Provided MLDataProcessing job is not completed.`
  + `Provided MLModelTraining job doesn't exist.`
  + `Provided ModelTransformJob doesn't exist.`
  + `Unable to find SageMaker AI resource. Please check your input.`

# Neptune ML limits
<a name="machine-learning-limits"></a>
+ The types of inference currently supported are node classification, node regression, edge classification, edge regression and link prediction (see [Neptune ML capabilities](machine-learning.md#machine-learning-capabilities)).
+ The maximum graph size that Neptune ML can support depends on the amount of memory and storage required during [data preparation](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-processing-instance-size), [model training](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-training-transform-instance-size), and [inference](machine-learning-on-graphs-instance-selection.md#machine-learning-on-graphs-inference-endpoint-instance-size).
  + The maximum size of memory of a SageMaker AI data-processing instance is 768 GB. As a result, the data-processing stage fails if it needs more than 768 GB of memory.
  + The maximum size of memory of a SageMaker AI training instance is 732 GB. As a result, the training stage fails if it needs more than 732 GB of memory.
+ The maximum size of an inference payload for a SageMaker AI endpoint is 6 MiB. As a result, inductive inference fails if the subgraph payload exceeds this size.
+ Neptune ML is currently available only in Regions where Neptune and the other services it depends on (such as AWS Lambda, Amazon API Gateway and Amazon SageMaker AI) are all supported.

  There are differences in China (Beijing) and China (Ningxia) having to do with the default use of IAM authentication, as is [explained here](https://docs.amazonaws.cn/en_us/aws/latest/userguide/api-gateway.html#feature-diff) along with other differences.
+ The link prediction inference endpoints launched by Neptune ML currently can only predict possible links with nodes that were present in the graph during training.

  For example, consider a graph with `User` and `Movie` vertices and `Rated` edges. Using a corresponding Neptune ML link-prediction recommendation model, you can add a new user to the graph and have the model predict movies for them, but the model can only recommend movies that were present during model training. Although the `User` node embedding is calculated in real-time using its local subgraph and the GNN model, and can therefore change with time as users rate movies, it's compared to the static, pre-computed movie embeddings for the final recommendation.
+ The KGE models supported by Neptune ML only work for link prediction tasks, and the representations are specific to vertices and edge types present in the graph during training. This means that all vertices and edge types referred to in an inference query must have been present in the graph during training. Predictions for new edge types or vertices cannot be made without retraining the model.

## SageMaker AI resource limitations
<a name="machine-learning-limits-sagemaker"></a>

Depending on your activities and resource usage over time, you may encounter error messages saying that [you've exceeded your quota](https://docs.aws.amazon.com/sagemaker/latest/dg/regions-quotas.html) ([ResourceLimitExceeded](https://repost.aws/knowledge-center/sagemaker-resource-limit-exceeded-error)). and you need to scale up your SageMaker AI resources, follow the steps in the [Request a service quota increase for SageMaker resources](https://docs.aws.amazon.com/sagemaker/latest/dg/regions-quotas.html#service-limit-increase-request-procedure) procedure on this page to request a quota increase from AWS Support.

SageMaker AI resource names correspond to Neptune ML stages as follows:
+ The SageMaker AI `ProcessingJob` is used by Neptune data processing, model training, and model transform jobs.
+ The SageMaker AI `HyperParameterTuningJob` is used by Neptune model training jobs.
+ The SageMaker AI `TrainingJob` is used by Neptune model training jobs.
+ The SageMaker AI `Endpoint` is used by Neptune inference endpoints.