Skip to content

Commit 0c28310

Browse files
authored
Merge branch 'master' into doc_inputs
2 parents e24d53a + 12c222b commit 0c28310

File tree

10 files changed

+183
-162
lines changed

10 files changed

+183
-162
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v2.52.1 (2021-08-06)
4+
5+
### Bug Fixes and Other Changes
6+
7+
* revert #2251 changes for sklearn processor
8+
39
## v2.52.0 (2021-08-05)
410

511
### Features

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.52.1.dev0
1+
2.52.2.dev0

doc/api/inference/model.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ Model
1515
:members:
1616
:undoc-members:
1717
:show-inheritance:
18+
19+
.. autoclass:: sagemaker.serverless.model.LambdaModel
20+
:members:
21+
:undoc-members:
22+
:show-inheritance:

doc/api/inference/predictors.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ Make real-time predictions against SageMaker endpoints with Python objects
77
:members:
88
:undoc-members:
99
:show-inheritance:
10+
11+
.. autoclass:: sagemaker.serverless.predictor.LambdaPredictor
12+
:members:
13+
:undoc-members:
14+
:show-inheritance:

doc/overview.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,50 @@ You can also find these notebooks in the **Advanced Functionality** section of t
10631063
For information about using sample notebooks in a SageMaker notebook instance, see `Use Example Notebooks <https://docs.aws.amazon.com/sagemaker/latest/dg/howitworks-nbexamples.html>`__
10641064
in the AWS documentation.
10651065
1066+
********************
1067+
Serverless Inference
1068+
********************
1069+
1070+
You can use the SageMaker Python SDK to perform serverless inference on Lambda.
1071+
1072+
To deploy models to Lambda, you must complete the following prerequisites:
1073+
1074+
- `Package your model and inference code as a container image. <https://docs.aws.amazon.com/lambda/latest/dg/images-create.html>`_
1075+
- `Create a role that lists Lambda as a trusted entity. <https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html#permissions-executionrole-console>`_
1076+
1077+
After completing the prerequisites, you can deploy your model to Lambda using
1078+
the `LambdaModel`_ class.
1079+
1080+
.. code:: python
1081+
1082+
from sagemaker.serverless import LambdaModel
1083+
1084+
image_uri = "123456789012.dkr.ecr.us-west-2.amazonaws.com/my-lambda-repository:latest"
1085+
role = "arn:aws:iam::123456789012:role/MyLambdaExecutionRole"
1086+
1087+
model = LambdaModel(image_uri=image_uri, role=role)
1088+
predictor = model.deploy("my-lambda-function", timeout=20, memory_size=4092)
1089+
1090+
The ``deploy`` method returns a `LambdaPredictor`_ instance. Use the
1091+
`LambdaPredictor`_ ``predict`` method to perform inference on Lambda.
1092+
1093+
.. code:: python
1094+
1095+
url = "https://example.com/cat.jpeg"
1096+
predictor.predict({"url": url}) # {'class': 'tabby'}
1097+
1098+
Once you are done performing inference on Lambda, free the `LambdaModel`_ and
1099+
`LambdaPredictor`_ resources using the ``delete_model`` and ``delete_predictor``
1100+
methods.
1101+
1102+
.. code:: python
1103+
1104+
model.delete_model()
1105+
predictor.delete_predictor()
1106+
1107+
.. _LambdaModel : https://sagemaker.readthedocs.io/en/stable/api/inference/model.html#sagemaker.serverless.model.LambdaModel
1108+
.. _LambdaPredictor : https://sagemaker.readthedocs.io/en/stable/api/inference/predictors.html#sagemaker.serverless.predictor.LambdaPredictor
1109+
10661110
******************
10671111
SageMaker Workflow
10681112
******************

src/sagemaker/sklearn/processing.py

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,67 +17,93 @@
1717
"""
1818
from __future__ import absolute_import
1919

20-
from sagemaker.processing import FrameworkProcessor
21-
from sagemaker.sklearn.estimator import SKLearn
20+
from sagemaker import image_uris, Session
21+
from sagemaker.processing import ScriptProcessor
22+
from sagemaker.sklearn import defaults
2223

2324

24-
class SKLearnProcessor(FrameworkProcessor):
25-
"""Initialize an ``SKLearnProcessor`` instance.
26-
27-
The SKLearnProcessor handles Amazon SageMaker processing tasks for jobs using scikit-learn.
28-
29-
Unless ``image_uri`` is specified, the scikit-learn environment is an
30-
Amazon-built Docker container that executes functions defined in the supplied
31-
``code`` Python script.
32-
33-
The arguments have the exact same meaning as in ``FrameworkProcessor``.
34-
35-
.. tip::
36-
37-
You can find additional parameters for initializing this class at
38-
:class:`~sagemaker.processing.FrameworkProcessor`.
39-
"""
40-
41-
estimator_cls = SKLearn
25+
class SKLearnProcessor(ScriptProcessor):
26+
"""Handles Amazon SageMaker processing tasks for jobs using scikit-learn."""
4227

4328
def __init__(
4429
self,
45-
framework_version, # New arg
30+
framework_version,
4631
role,
47-
instance_count,
4832
instance_type,
49-
py_version="py3", # New kwarg
50-
image_uri=None,
33+
instance_count,
5134
command=None,
5235
volume_size_in_gb=30,
5336
volume_kms_key=None,
5437
output_kms_key=None,
55-
code_location=None, # New arg
5638
max_runtime_in_seconds=None,
5739
base_job_name=None,
5840
sagemaker_session=None,
5941
env=None,
6042
tags=None,
6143
network_config=None,
6244
):
63-
"""This processor executes a Python script in a scikit-learn execution environment."""
64-
super().__init__(
65-
self.estimator_cls,
66-
framework_version,
67-
role,
68-
instance_count,
69-
instance_type,
70-
py_version,
71-
image_uri,
72-
command,
73-
volume_size_in_gb,
74-
volume_kms_key,
75-
output_kms_key,
76-
code_location,
77-
max_runtime_in_seconds,
78-
base_job_name,
79-
sagemaker_session,
80-
env,
81-
tags,
82-
network_config,
45+
"""Initialize an ``SKLearnProcessor`` instance.
46+
47+
The SKLearnProcessor handles Amazon SageMaker processing tasks for jobs using scikit-learn.
48+
49+
Args:
50+
framework_version (str): The version of scikit-learn.
51+
role (str): An AWS IAM role name or ARN. The Amazon SageMaker training jobs
52+
and APIs that create Amazon SageMaker endpoints use this role
53+
to access training data and model artifacts. After the endpoint
54+
is created, the inference code might use the IAM role, if it
55+
needs to access an AWS resource.
56+
instance_type (str): Type of EC2 instance to use for
57+
processing, for example, 'ml.c4.xlarge'.
58+
instance_count (int): The number of instances to run
59+
the Processing job with. Defaults to 1.
60+
command ([str]): The command to run, along with any command-line flags.
61+
Example: ["python3", "-v"]. If not provided, ["python3"] or ["python2"]
62+
will be chosen based on the py_version parameter.
63+
volume_size_in_gb (int): Size in GB of the EBS volume to
64+
use for storing data during processing (default: 30).
65+
volume_kms_key (str): A KMS key for the processing
66+
volume.
67+
output_kms_key (str): The KMS key id for all ProcessingOutputs.
68+
max_runtime_in_seconds (int): Timeout in seconds.
69+
After this amount of time Amazon SageMaker terminates the job
70+
regardless of its current status.
71+
base_job_name (str): Prefix for processing name. If not specified,
72+
the processor generates a default job name, based on the
73+
training image name and current timestamp.
74+
sagemaker_session (sagemaker.session.Session): Session object which
75+
manages interactions with Amazon SageMaker APIs and any other
76+
AWS services needed. If not specified, the processor creates one
77+
using the default AWS configuration chain.
78+
env (dict): Environment variables to be passed to the processing job.
79+
tags ([dict]): List of tags to be passed to the processing job.
80+
network_config (sagemaker.network.NetworkConfig): A NetworkConfig
81+
object that configures network isolation, encryption of
82+
inter-container traffic, security group IDs, and subnets.
83+
"""
84+
if not command:
85+
command = ["python3"]
86+
87+
session = sagemaker_session or Session()
88+
region = session.boto_region_name
89+
90+
image_uri = image_uris.retrieve(
91+
defaults.SKLEARN_NAME, region, version=framework_version, instance_type=instance_type
92+
)
93+
94+
super(SKLearnProcessor, self).__init__(
95+
role=role,
96+
image_uri=image_uri,
97+
instance_count=instance_count,
98+
instance_type=instance_type,
99+
command=command,
100+
volume_size_in_gb=volume_size_in_gb,
101+
volume_kms_key=volume_kms_key,
102+
output_kms_key=output_kms_key,
103+
max_runtime_in_seconds=max_runtime_in_seconds,
104+
base_job_name=base_job_name,
105+
sagemaker_session=session,
106+
env=env,
107+
tags=tags,
108+
network_config=network_config,
83109
)

tests/integ/test_local_mode.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,12 @@ def test_local_processing_sklearn(sagemaker_local_session_no_local_code, sklearn
349349

350350
job_description = sklearn_processor.latest_job.describe()
351351

352-
assert len(job_description["ProcessingInputs"]) == 3
352+
assert len(job_description["ProcessingInputs"]) == 2
353353
assert job_description["ProcessingResources"]["ClusterConfig"]["InstanceCount"] == 1
354354
assert job_description["ProcessingResources"]["ClusterConfig"]["InstanceType"] == "local"
355355
assert job_description["AppSpecification"]["ContainerEntrypoint"] == [
356-
"/bin/bash",
357-
"/opt/ml/processing/input/entrypoint/runproc.sh",
356+
"python3",
357+
"/opt/ml/processing/input/code/dummy_script.py",
358358
]
359359
assert job_description["RoleArn"] == "<no_role>"
360360

tests/integ/test_processing.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def test_sklearn(sagemaker_session, sklearn_latest_version, cpu_instance_type):
125125
role=ROLE,
126126
instance_type=cpu_instance_type,
127127
instance_count=1,
128+
command=["python3"],
128129
sagemaker_session=sagemaker_session,
129130
base_job_name="test-sklearn",
130131
)
@@ -138,16 +139,16 @@ def test_sklearn(sagemaker_session, sklearn_latest_version, cpu_instance_type):
138139

139140
job_description = sklearn_processor.latest_job.describe()
140141

141-
assert len(job_description["ProcessingInputs"]) == 3
142+
assert len(job_description["ProcessingInputs"]) == 2
142143
assert job_description["ProcessingResources"]["ClusterConfig"]["InstanceCount"] == 1
143144
assert (
144145
job_description["ProcessingResources"]["ClusterConfig"]["InstanceType"] == cpu_instance_type
145146
)
146147
assert job_description["ProcessingResources"]["ClusterConfig"]["VolumeSizeInGB"] == 30
147148
assert job_description["StoppingCondition"] == {"MaxRuntimeInSeconds": 86400}
148149
assert job_description["AppSpecification"]["ContainerEntrypoint"] == [
149-
"/bin/bash",
150-
"/opt/ml/processing/input/entrypoint/runproc.sh",
150+
"python3",
151+
"/opt/ml/processing/input/code/dummy_script.py",
151152
]
152153
assert ROLE in job_description["RoleArn"]
153154

@@ -203,7 +204,6 @@ def test_sklearn_with_customizations(
203204
assert job_description["ProcessingInputs"][0]["InputName"] == "dummy_input"
204205

205206
assert job_description["ProcessingInputs"][1]["InputName"] == "code"
206-
assert job_description["ProcessingInputs"][2]["InputName"] == "entrypoint"
207207

208208
assert job_description["ProcessingJobName"].startswith("test-sklearn-with-customizations")
209209

@@ -220,8 +220,8 @@ def test_sklearn_with_customizations(
220220

221221
assert job_description["AppSpecification"]["ContainerArguments"] == ["-v"]
222222
assert job_description["AppSpecification"]["ContainerEntrypoint"] == [
223-
"/bin/bash",
224-
"/opt/ml/processing/input/entrypoint/runproc.sh",
223+
"python3",
224+
"/opt/ml/processing/input/code/dummy_script.py",
225225
]
226226
assert job_description["AppSpecification"]["ImageUri"] == image_uri
227227

@@ -245,6 +245,7 @@ def test_sklearn_with_custom_default_bucket(
245245
sklearn_processor = SKLearnProcessor(
246246
framework_version=sklearn_latest_version,
247247
role=ROLE,
248+
command=["python3"],
248249
instance_type=cpu_instance_type,
249250
instance_count=1,
250251
volume_size_in_gb=100,
@@ -287,9 +288,6 @@ def test_sklearn_with_custom_default_bucket(
287288
assert job_description["ProcessingInputs"][0]["InputName"] == "dummy_input"
288289
assert custom_bucket_name in job_description["ProcessingInputs"][0]["S3Input"]["S3Uri"]
289290

290-
assert job_description["ProcessingInputs"][1]["InputName"] == "code"
291-
assert custom_bucket_name in job_description["ProcessingInputs"][1]["S3Input"]["S3Uri"]
292-
293291
assert job_description["ProcessingInputs"][2]["InputName"] == "entrypoint"
294292
assert custom_bucket_name in job_description["ProcessingInputs"][2]["S3Input"]["S3Uri"]
295293

@@ -308,8 +306,8 @@ def test_sklearn_with_custom_default_bucket(
308306

309307
assert job_description["AppSpecification"]["ContainerArguments"] == ["-v"]
310308
assert job_description["AppSpecification"]["ContainerEntrypoint"] == [
311-
"/bin/bash",
312-
"/opt/ml/processing/input/entrypoint/runproc.sh",
309+
"python3",
310+
"/opt/ml/processing/input/code/dummy_script.py",
313311
]
314312
assert job_description["AppSpecification"]["ImageUri"] == image_uri
315313

@@ -326,6 +324,7 @@ def test_sklearn_with_no_inputs_or_outputs(
326324
sklearn_processor = SKLearnProcessor(
327325
framework_version=sklearn_latest_version,
328326
role=ROLE,
327+
command=["python3"],
329328
instance_type=cpu_instance_type,
330329
instance_count=1,
331330
volume_size_in_gb=100,
@@ -338,16 +337,12 @@ def test_sklearn_with_no_inputs_or_outputs(
338337
)
339338

340339
sklearn_processor.run(
341-
code=os.path.join(DATA_DIR, "dummy_script.py"),
342-
arguments=["-v"],
343-
wait=True,
344-
logs=True,
340+
code=os.path.join(DATA_DIR, "dummy_script.py"), arguments=["-v"], wait=True, logs=True
345341
)
346342

347343
job_description = sklearn_processor.latest_job.describe()
348344

349345
assert job_description["ProcessingInputs"][0]["InputName"] == "code"
350-
assert job_description["ProcessingInputs"][1]["InputName"] == "entrypoint"
351346

352347
assert job_description["ProcessingJobName"].startswith("test-sklearn-with-no-inputs")
353348

@@ -361,8 +356,8 @@ def test_sklearn_with_no_inputs_or_outputs(
361356

362357
assert job_description["AppSpecification"]["ContainerArguments"] == ["-v"]
363358
assert job_description["AppSpecification"]["ContainerEntrypoint"] == [
364-
"/bin/bash",
365-
"/opt/ml/processing/input/entrypoint/runproc.sh",
359+
"python3",
360+
"/opt/ml/processing/input/code/dummy_script.py",
366361
]
367362
assert job_description["AppSpecification"]["ImageUri"] == image_uri
368363

tests/integ/test_sklearn.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,6 @@ def sklearn_training_job(
4646
sagemaker_session.boto_region_name
4747

4848

49-
def test_framework_processing_job_with_deps(
50-
sagemaker_session,
51-
sklearn_latest_version,
52-
sklearn_latest_py_version,
53-
cpu_instance_type,
54-
):
55-
return _run_processing_job(
56-
sagemaker_session,
57-
cpu_instance_type,
58-
sklearn_latest_version,
59-
sklearn_latest_py_version,
60-
)
61-
62-
6349
def test_training_with_additional_hyperparameters(
6450
sagemaker_session,
6551
sklearn_latest_version,

0 commit comments

Comments
 (0)