TL;DR --I think you often make SageMaker inferences from Python, but I think the front end may be PHP. I wrote how to perform SageMaker inference from PHP running on EC2. --PHP can't handle numpy, so if it's an image, it's encoded in Base64 and sent.
This is a necessary task, not just PHP. Let's decide between the front end and the ML Engineer.
Since SageMaker is basic Python, you may want to use the convenient numpy. With numpy, you can easily pass data to various models such as TensorFlow, PyTorch, MXNet. On the other hand, if the sender is PHP, it is difficult to send data with the Python library numpy. So, instead of numpy, try using a format that PHP can handle, such as json or Base64 for images. For now, consider encoding an image on EC2 to Base64 and sending it to SageMaker.
Here, I will host the model of DeepLab, which is a pretrained model of Semantic segmentation of GluonCV. The flow up to deployment has been raised to Gist. https://gist.github.com/harusametime/ac3050d25c47b23534784ce8fb09da6b
Deployment requires a script for inference, and here we also implement how to handle Base64 images. First is the implementation of the model_fn function for loading the model. This can be called with a single function of gluoncv. Since we are assuming an instance that can use GPU, if you only have CPU, please set mx.cpu () to ctx.
def model_fn(model_dir):
net = gluoncv.model_zoo.get_deeplab_resnet50_ade(pretrained=True, ctx=mx.gpu())
return net
Now next is the implementation of transform_fn that passes data to the above model and predicts it. After first decoding base64, the image file will be in data, so open it with PIL Image and convert it to numpy conversion and mxnet array. It is a flow to predict with predict after executing test_transform of DeepLab preprocessing. Since it is Semantic Segmentation, multiple label candidates are displayed for each pixel. Here, the most plausible label is given, and the one with the highest probability with argmax is given. Finally, it returns the response in json format.
def transform_fn(net, data, input_content_type, output_content_type):
data = base64.b64decode(data)
data = Image.open(BytesIO(data))
data = np.array(data)
data = mx.nd.array(data,ctx=mx.gpu())
data = test_transform(data,ctx=mx.gpu())
output = net.predict(data)
predict = mx.nd.squeeze(mx.nd.argmax(output, 1)).asnumpy().tolist()
response_body = json.dumps(predict)
return response_body, output_content_type
I think it's been about 15 years since I've touched PHP, but let's do it. PHP requires the AWS SDK for PHP, just as you need the Python SDK (Boto3) to perform SageMaker inference from Python.
Select EC2 from the new IAM Role creation screen to create a role that can be used with EC2.
Grant an AmazonSageMakerFullAccess policy so that you can work with SageMaker from that role. Then give it a name and save it.
The saved role can be given to the instance on the EC2 screen.
Please refer to the Official Installation Guide. First, PHP version 5.5 or later is recommended. I'm using PHP 5.3, so I upgraded it. Just uninstall and reinstall php. There may be a smarter way. I included php-xml because it was needed for the AWS SDK.
yum -y remove php-*
yum -y remove httpd-tools
yum clean all
yum -y install php
yum -y install php-xml
Once you have php, it's time to install Composer. You can follow the Installation Guide (https://getcomposer.org/download/), but I created the How do I install Composer programmatically? file linked from the guide and ran it from the shell.
Once Composer is in place, it's time to install the AWS SDK.
composer require aws/aws-sdk-php
When you execute this, the installation is completed. There will be a folder called vendor
in the executed directory, and a file called autoload.php
in it. If you call this file from a PHP script, it will read the entire AWS SDK.
When you perform inference, you run InvokeEndpoint, so look for usage in the AWS SDK for PHP documentation.
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-runtime.sagemaker-2017-05-13.html
$result = $client->invokeEndpoint([
'Accept' => '<string>',
'Body' => <string || resource || Psr\Http\Message\StreamInterface>, // REQUIRED
'ContentType' => '<string>',
'CustomAttributes' => '<string>',
'EndpointName' => '<string>', // REQUIRED
'InferenceId' => '<string>',
'TargetModel' => '<string>',
'TargetVariant' => '<string>',
]);
REQUIRED is Body
and EndpointName
. For Body, put the Base64 image, and for EndpointName, put the name of the endpoint created above. If you don't know, you can check it from the SageMaker console.
Then, if you put this around and write the php code, it looks like this.
<?php
require 'vendor/autoload.php';
use Aws\SageMakerRuntime\SageMakerRuntimeClient;
$im = file_get_contents("./image.jpg ");
$base64img = base64_encode($im);
$client = new SageMakerRuntimeClient([
'region' => 'us-west-2',
'version' => '2017-05-13'
]);
$result = $client->invokeEndpoint([
'Body' => $base64img, // REQUIRED
'EndpointName' => 'Endpoint name', // REQUIRED
]);
print($result['Body']);
?>
When I run it, it looks like this.
[ec2-user@ip-10-0-0-144 ~]$ php predict.php
[[5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0,
...(Omitted on the way)
3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0,
3.0, 3.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
Since it is a two-dimensional array, it corresponds to the vertical and horizontal directions of the image, and labels 5, 3 and 0 are included as values. In the ADE20K dataset, 5 is the ceiling, 3 is the floor, and 0 is the wall, so you can expect the image given to be an indoor image, with the ceiling at the beginning (upper).
Recommended Posts