cloud-submit 0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. cloud_submit-0.1/.gitignore +8 -0
  2. cloud_submit-0.1/LICENSE +19 -0
  3. cloud_submit-0.1/PKG-INFO +12 -0
  4. cloud_submit-0.1/README.md +29 -0
  5. cloud_submit-0.1/docs/examples/aws/src/csub/build_config.py +153 -0
  6. cloud_submit-0.1/docs/examples/aws/src/fit.py +42 -0
  7. cloud_submit-0.1/docs/examples/aws/src/generate.py +32 -0
  8. cloud_submit-0.1/docs/examples/aws/src/parameters.py +8 -0
  9. cloud_submit-0.1/docs/examples/aws/userconfig/template.yaml +112 -0
  10. cloud_submit-0.1/docs/examples/basic/src/csub/build_config.py +102 -0
  11. cloud_submit-0.1/docs/examples/basic/src/fit.py +41 -0
  12. cloud_submit-0.1/docs/examples/basic/src/generate.py +24 -0
  13. cloud_submit-0.1/docs/examples/basic/src/parameters.py +8 -0
  14. cloud_submit-0.1/docs/examples/basic/userconfig/template.yaml +7 -0
  15. cloud_submit-0.1/docs/examples/multi-worker/src/csub/build_config.py +105 -0
  16. cloud_submit-0.1/docs/examples/multi-worker/src/fit.py +70 -0
  17. cloud_submit-0.1/docs/examples/multi-worker/src/generate.py +27 -0
  18. cloud_submit-0.1/docs/examples/multi-worker/src/parameters.py +10 -0
  19. cloud_submit-0.1/docs/examples/multi-worker/userconfig/template.yaml +7 -0
  20. cloud_submit-0.1/pyproject.toml +29 -0
  21. cloud_submit-0.1/src/cloud_submit/__init__.py +30 -0
  22. cloud_submit-0.1/src/cloud_submit/cli.py +1014 -0
  23. cloud_submit-0.1/src/cloud_submit/config.py +164 -0
  24. cloud_submit-0.1/src/cloud_submit/controller.py +375 -0
  25. cloud_submit-0.1/src/cloud_submit/environment_handler.py +398 -0
  26. cloud_submit-0.1/src/cloud_submit/envs/aws/__init__.py +2 -0
  27. cloud_submit-0.1/src/cloud_submit/envs/aws/local_environment_handler.py +478 -0
  28. cloud_submit-0.1/src/cloud_submit/envs/aws/local_execution_handler.py +5 -0
  29. cloud_submit-0.1/src/cloud_submit/envs/aws/remote_environment_handler.py +401 -0
  30. cloud_submit-0.1/src/cloud_submit/envs/aws/remote_execution_handler.py +87 -0
  31. cloud_submit-0.1/src/cloud_submit/envs/aws/s3_tools.py +46 -0
  32. cloud_submit-0.1/src/cloud_submit/envs/local/environment_handler.py +121 -0
  33. cloud_submit-0.1/src/cloud_submit/envs/local/execution_handler.py +5 -0
  34. cloud_submit-0.1/src/cloud_submit/execution/base_execution_handler.py +49 -0
  35. cloud_submit-0.1/src/cloud_submit/execution/config.py +248 -0
  36. cloud_submit-0.1/src/cloud_submit/execution/execute.py +108 -0
  37. cloud_submit-0.1/src/cloud_submit/execution/utils.py +98 -0
  38. cloud_submit-0.1/src/cloud_submit/images.py +58 -0
  39. cloud_submit-0.1/src/cloud_submit/utils.py +67 -0
@@ -0,0 +1,8 @@
1
+ *.swp
2
+ __pycache__
3
+ dist
4
+
5
+ docs/examples/*/temp
6
+ docs/examples/*/images
7
+ docs/examples/*/artifacts
8
+ docs/examples/*/userconfig/default.yaml
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloud-submit
3
+ Version: 0.1
4
+ Summary: A tool for building processing pipelines in Python and executing them locally or in the cloud.
5
+ Author: Martin Wiebusch
6
+ License-File: LICENSE
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Requires-Python: >=3.7
11
+ Requires-Dist: click
12
+ Requires-Dist: pyyaml
@@ -0,0 +1,29 @@
1
+ # cloud-submit
2
+
3
+ A tool for packaging Python code with Docker and executing it in local and
4
+ cloud environments.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ $ pip install cloud-submit
10
+ ```
11
+
12
+ ## Documentation
13
+
14
+ This package provides a Python module called `cloud_submit` as well as a
15
+ command-line tool called `csub`.
16
+
17
+ Have a look at the
18
+ [examples](https://github.com/mwiebusch78/cloud-submit/tree/main/docs/examples)
19
+ to see how to set up a project directory. To run any of the examples you will
20
+ have to copy `userconfig/template.yaml` to `userconfig/default.yaml` and fill
21
+ in the blanks.
22
+
23
+ To run the AWS example you need to have the AWS CLI (v2) installed locally
24
+ and you need an AWS account. The comments in `userconfig/template.yaml` tell
25
+ you how you need to configure your AWS account so that the example can run.
26
+
27
+ Run `csub --help` to explore the functionality of `csub` and its subcommands.
28
+
29
+ Proper documentation will be added as soon as I have the time. (Promise!)
@@ -0,0 +1,153 @@
1
+ import datetime as dt
2
+ import cloud_submit as cs
3
+
4
+ # import AWS-specific environments that ship with cloud_submit.
5
+ import cloud_submit.envs.aws
6
+ from cloud_submit.envs.aws import LocalAWSEnv, RemoteAWSEnv
7
+
8
+ # csub automatically adds your project's src directory to sys.path, so
9
+ # you can import any modules defined there.
10
+ from parameters import PARAMS
11
+
12
+
13
+ PROJECT_NAME = 'basic-aws'
14
+
15
+
16
+ def build_config(project_root, userconfig):
17
+ """Create an instance of cloud_submit.Config describing your project.
18
+
19
+ Note:
20
+ The csub command expects a function with this name defined in
21
+ src/csub/build_config.py. It calls this function to obtain a
22
+ cloud_submit.Config object which describes the environments, images,
23
+ artifacts and pipelines defined in your project.
24
+
25
+ Args:
26
+ project_root (str): The root directory of your project.
27
+ userconfig (dict): A dict holding user-specific information. This
28
+ corresponds to the content of the file userconfigs/default.yaml
29
+ in your project directory (or some other yaml file in that directory
30
+ if csub was called with the --user option).
31
+
32
+ Returns:
33
+ config (cloud_submit.Config): The config object describing the project.
34
+ """
35
+
36
+ # Images
37
+
38
+ images = [
39
+ cs.BaseImage(
40
+ name='base',
41
+ instructions=r"""
42
+ FROM python
43
+ RUN \
44
+ cd /opt && \
45
+ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \
46
+ -o "awscliv2.zip" && \
47
+ unzip awscliv2.zip && \
48
+ ./aws/install && \
49
+ rm -rf awscliv2.zip aws
50
+ RUN pip install --root-user-action=ignore polars numpy
51
+ """,
52
+ ),
53
+ cs.ExecutionImage(
54
+ name='exec',
55
+ parent='base',
56
+ ),
57
+ ]
58
+
59
+ # Artifacts
60
+
61
+ artifacts = [
62
+ cs.Artifact('train_data.parquet', kind='file', scope='run'),
63
+ cs.Artifact('coefficients.json', kind='file', scope='run'),
64
+ cs.Artifact('predictions.parquet', kind='file', scope='run'),
65
+ ]
66
+
67
+ # Pipelines
68
+
69
+ train_pipeline = cs.Pipeline(
70
+ name='train',
71
+ steps=[
72
+ cs.Step(
73
+ name='generate',
74
+ spec=cs.Spec(
75
+ cpu=2,
76
+ memory=6.5,
77
+ disk=20,
78
+ ),
79
+ function='generate:generate_step',
80
+ image='exec',
81
+ params={
82
+ 'random_seed': PARAMS['random_seed'],
83
+ 'num_samples': PARAMS['num_samples'],
84
+ 'alpha': PARAMS['alpha'],
85
+ 'beta': PARAMS['beta'],
86
+ 'sigma': PARAMS['sigma'],
87
+ },
88
+ outputs={
89
+ 'train_data_path': cs.local('train_data.parquet'),
90
+ },
91
+ ),
92
+ cs.Step(
93
+ name='fit',
94
+ spec=cs.Spec(
95
+ cpu=2,
96
+ memory=6.5,
97
+ disk=20,
98
+ ),
99
+ function='fit:fit_step',
100
+ image='exec',
101
+ inputs={
102
+ 'train_data_path': cs.local('train_data.parquet'),
103
+ },
104
+ outputs={
105
+ 'coefficients_path': cs.local('coefficients.json'),
106
+ 'predictions_path': cs.local('predictions.parquet'),
107
+ },
108
+ ),
109
+ ],
110
+ )
111
+
112
+ config = cs.Config(
113
+ project_name=PROJECT_NAME,
114
+ user_name=userconfig['username'],
115
+ project_root=project_root,
116
+ images=images,
117
+ artifacts=artifacts,
118
+ pipelines=[train_pipeline],
119
+ environments=[
120
+ LocalAWSEnv(
121
+ name='local',
122
+ project=PROJECT_NAME,
123
+ user=userconfig['username'],
124
+ aws_account_id=userconfig['aws_account_id'],
125
+ aws_region=userconfig['aws_region'],
126
+ aws_profile=userconfig['aws_profile'],
127
+ docker_namespace=userconfig['docker_namespace'],
128
+ s3_bucket=userconfig['s3_bucket'],
129
+ s3_prefix=userconfig['s3_prefix'],
130
+ ),
131
+ RemoteAWSEnv(
132
+ name='remote',
133
+ project=PROJECT_NAME,
134
+ user=userconfig['username'],
135
+ aws_account_id=userconfig['aws_account_id'],
136
+ aws_region=userconfig['aws_region'],
137
+ aws_profile=userconfig['aws_profile'],
138
+ docker_namespace=userconfig['docker_namespace'],
139
+ s3_bucket=userconfig['s3_bucket'],
140
+ s3_prefix=userconfig['s3_prefix'],
141
+ ecs_cluster_arn=userconfig['ecs_cluster_arn'],
142
+ ecs_capacity_provider=userconfig['ecs_capacity_provider'],
143
+ ecs_infrastructure_role_arn=
144
+ userconfig['ecs_infrastructure_role_arn'],
145
+ ecs_execution_role_arn=userconfig['ecs_execution_role_arn'],
146
+ ecs_task_role_arn=userconfig['ecs_task_role_arn'],
147
+ stepfunctions_role_arn=userconfig['stepfunctions_role_arn'],
148
+ ),
149
+ ],
150
+ )
151
+
152
+ return config
153
+
@@ -0,0 +1,42 @@
1
+ import os
2
+ import json
3
+
4
+ import numpy as np
5
+ import polars as pl
6
+
7
+
8
+ def fit_step(
9
+ train_data_path,
10
+ coefficients_path,
11
+ predictions_path,
12
+ ):
13
+ print(f'Fitting model.')
14
+
15
+ train_data = pl.read_parquet(os.path.join(train_data_path, '*.parquet'))
16
+ x = train_data.get_column('x').to_numpy()
17
+ y = train_data.get_column('y').to_numpy()
18
+
19
+ # add intercept term
20
+ intercept = np.ones(len(x))
21
+ x = np.stack([intercept, x], axis=1)
22
+
23
+ # fit linear regression model
24
+ coeffs = np.linalg.solve(np.dot(x.T, x), np.dot(x.T, y))
25
+
26
+ # compute in-sample predictions
27
+ preds = np.dot(x, coeffs)
28
+ preds = train_data.with_columns(pl.Series('pred', preds))
29
+
30
+ # save coefficients
31
+ with open(coefficients_path, 'w') as stream:
32
+ json.dump(
33
+ {
34
+ 'alpha': float(coeffs[0]),
35
+ 'beta': float(coeffs[1]),
36
+ },
37
+ stream,
38
+ )
39
+
40
+ # save in-sample predictions
41
+ preds.write_parquet(predictions_path)
42
+
@@ -0,0 +1,32 @@
1
+ import os
2
+
3
+ import numpy as np
4
+ import polars as pl
5
+
6
+
7
+ def generate_step(
8
+ random_seed,
9
+ num_samples,
10
+ alpha,
11
+ beta,
12
+ sigma,
13
+ train_data_path,
14
+ ):
15
+ print(f'Generating training data.')
16
+
17
+ rng = np.random.default_rng(random_seed)
18
+ x = rng.normal(size=num_samples)
19
+ y = alpha + beta*x + sigma*rng.normal(size=num_samples)
20
+
21
+ train_data = pl.DataFrame([
22
+ pl.Series('x', x),
23
+ pl.Series('y', y),
24
+ ])
25
+
26
+ os.mkdir(train_data_path)
27
+ split_index = len(train_data)//2
28
+ train_data[:split_index].write_parquet(
29
+ os.path.join(train_data_path, 'part0.parquet'))
30
+ train_data[split_index:].write_parquet(
31
+ os.path.join(train_data_path, 'part1.parquet'))
32
+
@@ -0,0 +1,8 @@
1
+ PARAMS = {
2
+ # Parameters for data generation.
3
+ 'random_seed': 42, # The random seed.
4
+ 'num_samples': 100, # The number of training samples to generate.
5
+ 'alpha': 1.0, # The true value of the intercept coefficient.
6
+ 'beta': 2.0, # The true value of the linear coefficient.
7
+ 'sigma': 0.1, # The standard deviation of the error term.
8
+ }
@@ -0,0 +1,112 @@
1
+ # Your username is used for keeping your artifacts, images and cloud resources
2
+ # separate from those of other users.
3
+ username: # TODO: choose a user name.
4
+
5
+ # This is the ID of your AWS account. Make sure you specify it as a string,
6
+ # e.g. "123456789012".
7
+ aws_account_id: # TODO: add you AWS account ID.
8
+
9
+ # This is the region where your AWS resources were/are created
10
+ # (e.g. eu-north-1).
11
+ aws_region: # TODO: add your AWS region.
12
+
13
+ # This is the name of the profile that you want to use to authenticate with
14
+ # AWS. Look at ~/.aws/config to see what profiles you have configured.
15
+ # Normally there should be one called "default" which is the one that's used
16
+ # when you run aws commands without a --profile option.
17
+ aws_profile: default
18
+
19
+ # This is the docker namespace that will be used to store docker images
20
+ # needed in your project. You have to set up an Elastic Container Registy
21
+ # in AWS in the region you specified under `aws_region`. Images under this
22
+ # namespace must be mutable and you must allow repo creation on push for
23
+ # this namespace. It is also recommended to enable blob mounting on the
24
+ # registry.
25
+ docker_namespace: csub
26
+
27
+ # This is the name of the S3 bucket where your artifacts will be stored.
28
+ s3_bucket: # TODO: add the name of your S3 bucket.
29
+
30
+ # This is the S3 prefix under which your artifacts will be stored.
31
+ s3_prefix: csub
32
+
33
+ # If you want to run pipelines in AWS you have to set up a cluster in
34
+ # Elastic Container Service (ECS). The cluster must allow the use
35
+ # of managed EC2 instances (second option in the cluster creation form
36
+ # in the AWS console).
37
+ #
38
+ # If you only want to do local runs you can use an string value for this
39
+ # and all following parameters.
40
+ ecs_cluster_arn: n/a # TODO: add the ARN of your ECS cluster.
41
+
42
+ # The capacity provider should have been created automatically when you
43
+ # created the cluster. To find its name, view your cluster in the AWS console
44
+ # and look at the "Infrastructure" tab. Note that we need the *name* of the
45
+ # capacity provider, not its ARN.
46
+ ecs_capacity_provider: n/a # TODO: add the name of your capacity provider.
47
+
48
+ # The infrastructure role is the role used to manage the managed EC2 instances
49
+ # in your cluster. You should have created this role when you created the
50
+ # cluster.
51
+ ecs_infrastructure_role_arn: n/a # TODO: add the ARN of your infrastructure role
52
+
53
+ # To create the next two roles you can open the form for creating a task
54
+ # definition in ECS. In the "Task roles" sections it asks you to enter a
55
+ # "Task role" and a "Task execution role". Next to the dropdowns there are
56
+ # "Create new role" buttons which let you create those roles on the fly.
57
+ # You do not need to complete the task definition after you have created
58
+ # them.
59
+ ecs_task_role_arn: n/a # TODO: add the ARN of your task role
60
+ ecs_execution_role_arn: n/a # TODO: add the ARN of your task execution role
61
+
62
+ # The stepfunction role is used to orchestrate your ECS tasks via AWS
63
+ # Stepfunctions. This role should have the AWSLambdaRole policy and the
64
+ # following custom inline policy:
65
+ #
66
+ # {
67
+ # "Version": "2012-10-17",
68
+ # "Statement": [
69
+ # {
70
+ # "Sid": "ECSOrchestrationPermissions",
71
+ # "Effect": "Allow",
72
+ # "Action": [
73
+ # "ecs:RegisterTaskDefinition",
74
+ # "ecs:DeregisterTaskDefinition",
75
+ # "ecs:RunTask",
76
+ # "ecs:DescribeTasks",
77
+ # "ecs:StopTask"
78
+ # ],
79
+ # "Resource": "*"
80
+ # },
81
+ # {
82
+ # "Sid": "PassRolesToECSInstances",
83
+ # "Effect": "Allow",
84
+ # "Action": "iam:PassRole",
85
+ # "Resource": [
86
+ # "{INSTANCE_ROLE_ARN}",
87
+ # "{INFRASTRUCTURE_ROLE_ARN}",
88
+ # "{TASK_EXECUTION_ROLE_ARN}",
89
+ # "{TASK_ROLE_ARN}"
90
+ # ]
91
+ # },
92
+ # {
93
+ # "Sid": "EventBridgeSyncTracking",
94
+ # "Effect": "Allow",
95
+ # "Action": [
96
+ # "events:PutTargets",
97
+ # "events:PutRule",
98
+ # "events:DescribeRule"
99
+ # ],
100
+ # "Resource": "arn:aws:events:*:*:rule/StepFunctionsGetEventsForECSTaskRule"
101
+ # }
102
+ # ]
103
+ # }
104
+ #
105
+ # Here {INFRASTUCTURE_ROLE_ARN}, {TASK_EXECUTION_ROLE_ARN} and {TASK_ROLE_ARN}
106
+ # are the role ARNs you specified earlier and {INSTANCE_ROLE_ARN} is the ARN
107
+ # of another role that you set up when you created your cluster.
108
+ #
109
+ # Also note that the user you authenticate as when you submit a job (i.e. the
110
+ # user of the profile you specified under `aws_profile`) must have permission
111
+ # to assume the stepfunction role you specify here.
112
+ stepfunctions_role_arn: n/a # TODO: add your stepfunctions role ARN.
@@ -0,0 +1,102 @@
1
+ import datetime as dt
2
+ import cloud_submit as cs
3
+
4
+ # csub automatically adds your project's src directory to sys.path, so
5
+ # you can import any modules defined there.
6
+ from parameters import PARAMS
7
+
8
+
9
+ PROJECT_NAME = 'basic'
10
+
11
+
12
+ def build_config(project_root, userconfig):
13
+ """Create an instance of cloud_submit.Config describing your project.
14
+
15
+ Note:
16
+ The csub command expects a function with this name defined in
17
+ src/csub/build_config.py. It calls this function to obtain a
18
+ cloud_submit.Config object which describes the environments, images,
19
+ artifacts and pipelines defined in your project.
20
+
21
+ Args:
22
+ project_root (str): The root directory of your project.
23
+ userconfig (dict): A dict holding user-specific information. This
24
+ corresponds to the content of the file userconfigs/default.yaml
25
+ in your project directory (or some other yaml file in that directory
26
+ if csub was called with the --user option).
27
+
28
+ Returns:
29
+ config (cloud_submit.Config): The config object describing the project.
30
+ """
31
+
32
+ # Images
33
+
34
+ images = [
35
+ cs.BaseImage(
36
+ name='base',
37
+ instructions="""
38
+ FROM python
39
+ RUN pip install --root-user-action=ignore polars numpy
40
+ """,
41
+ ),
42
+ cs.ExecutionImage(
43
+ name='exec',
44
+ parent='base',
45
+ ),
46
+ ]
47
+
48
+ # Artifacts
49
+
50
+ artifacts = [
51
+ cs.Artifact('train_data.parquet', kind='file', scope='run'),
52
+ cs.Artifact('coefficients.json', kind='file', scope='run'),
53
+ cs.Artifact('predictions.parquet', kind='file', scope='run'),
54
+ ]
55
+
56
+ # Pipelines
57
+
58
+ train_pipeline = cs.Pipeline(
59
+ name='train',
60
+ steps=[
61
+ cs.Step(
62
+ name='generate',
63
+ function='generate:generate_step',
64
+ image='exec',
65
+ params={
66
+ 'random_seed': PARAMS['random_seed'],
67
+ 'num_samples': PARAMS['num_samples'],
68
+ 'alpha': PARAMS['alpha'],
69
+ 'beta': PARAMS['beta'],
70
+ 'sigma': PARAMS['sigma'],
71
+ },
72
+ outputs={
73
+ 'train_data_path': cs.local('train_data.parquet'),
74
+ },
75
+ ),
76
+ cs.Step(
77
+ name='fit',
78
+ function='fit:fit_step',
79
+ image='exec',
80
+ inputs={
81
+ 'train_data_path': cs.local('train_data.parquet'),
82
+ },
83
+ outputs={
84
+ 'coefficients_path': cs.local('coefficients.json'),
85
+ 'predictions_path': cs.local('predictions.parquet'),
86
+ },
87
+ ),
88
+ ],
89
+ )
90
+
91
+
92
+ config = cs.Config(
93
+ project_name=PROJECT_NAME,
94
+ user_name=userconfig['username'],
95
+ project_root=project_root,
96
+ images=images,
97
+ artifacts=artifacts,
98
+ pipelines=[train_pipeline],
99
+ )
100
+
101
+ return config
102
+
@@ -0,0 +1,41 @@
1
+ import json
2
+
3
+ import numpy as np
4
+ import polars as pl
5
+
6
+
7
+ def fit_step(
8
+ train_data_path,
9
+ coefficients_path,
10
+ predictions_path,
11
+ ):
12
+ print(f'Fitting model.')
13
+
14
+ train_data = pl.read_parquet(train_data_path)
15
+ x = train_data.get_column('x').to_numpy()
16
+ y = train_data.get_column('y').to_numpy()
17
+
18
+ # add intercept term
19
+ intercept = np.ones(len(x))
20
+ x = np.stack([intercept, x], axis=1)
21
+
22
+ # fit linear regression model
23
+ coeffs = np.linalg.solve(np.dot(x.T, x), np.dot(x.T, y))
24
+
25
+ # compute in-sample predictions
26
+ preds = np.dot(x, coeffs)
27
+ preds = train_data.with_columns(pl.Series('pred', preds))
28
+
29
+ # save coefficients
30
+ with open(coefficients_path, 'w') as stream:
31
+ json.dump(
32
+ {
33
+ 'alpha': float(coeffs[0]),
34
+ 'beta': float(coeffs[1]),
35
+ },
36
+ stream,
37
+ )
38
+
39
+ # save in-sample predictions
40
+ preds.write_parquet(predictions_path)
41
+
@@ -0,0 +1,24 @@
1
+ import numpy as np
2
+ import polars as pl
3
+
4
+
5
+ def generate_step(
6
+ random_seed,
7
+ num_samples,
8
+ alpha,
9
+ beta,
10
+ sigma,
11
+ train_data_path,
12
+ ):
13
+ print(f'Generating training data.')
14
+
15
+ rng = np.random.default_rng(random_seed)
16
+ x = rng.normal(size=num_samples)
17
+ y = alpha + beta*x + sigma*rng.normal(size=num_samples)
18
+
19
+ train_data = pl.DataFrame([
20
+ pl.Series('x', x),
21
+ pl.Series('y', y),
22
+ ])
23
+ train_data.write_parquet(train_data_path)
24
+
@@ -0,0 +1,8 @@
1
+ PARAMS = {
2
+ # Parameters for data generation.
3
+ 'random_seed': 42, # The random seed.
4
+ 'num_samples': 100, # The number of training samples to generate.
5
+ 'alpha': 1.0, # The true value of the intercept coefficient.
6
+ 'beta': 2.0, # The true value of the linear coefficient.
7
+ 'sigma': 0.1, # The standard deviation of the error term.
8
+ }
@@ -0,0 +1,7 @@
1
+ # Your username is used for keeping your artifacts, images and cloud resources
2
+ # separate from those of other users.
3
+ #
4
+ # (In this example we only use a single local environment, so there are no
5
+ # other users here. But the username becomes very important when you're running
6
+ # jobs in the cloud on an account that you share with other people.)
7
+ userconfig: # TODO: choose a user name.