Skip to content

Commit f4af925

Browse files
Omede Firouzmengxr
authored andcommitted
[SPARK-7022] [PYSPARK] [ML] Add ML.Tuning.ParamGridBuilder to PySpark
Author: Omede Firouz <[email protected]> Author: Omede <[email protected]> Closes #5601 from oefirouz/paramgrid and squashes the following commits: c9e2481 [Omede Firouz] Make test a doctest 9a8ce22 [Omede] Fix linter issues 8b8a6d2 [Omede Firouz] [SPARK-7022][PySpark][ML] Add ML.Tuning.ParamGridBuilder to PySpark
1 parent 49549d5 commit f4af925

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

python/pyspark/ml/tuning.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
__all__ = ['ParamGridBuilder']
19+
20+
21+
class ParamGridBuilder(object):
22+
"""
23+
Builder for a param grid used in grid search-based model selection.
24+
25+
>>> from classification import LogisticRegression
26+
>>> lr = LogisticRegression()
27+
>>> output = ParamGridBuilder().baseOn({lr.labelCol: 'l'}) \
28+
.baseOn([lr.predictionCol, 'p']) \
29+
.addGrid(lr.regParam, [1.0, 2.0, 3.0]) \
30+
.addGrid(lr.maxIter, [1, 5]) \
31+
.addGrid(lr.featuresCol, ['f']) \
32+
.build()
33+
>>> expected = [ \
34+
{lr.regParam: 1.0, lr.featuresCol: 'f', lr.maxIter: 1, lr.labelCol: 'l', lr.predictionCol: 'p'}, \
35+
{lr.regParam: 2.0, lr.featuresCol: 'f', lr.maxIter: 1, lr.labelCol: 'l', lr.predictionCol: 'p'}, \
36+
{lr.regParam: 3.0, lr.featuresCol: 'f', lr.maxIter: 1, lr.labelCol: 'l', lr.predictionCol: 'p'}, \
37+
{lr.regParam: 1.0, lr.featuresCol: 'f', lr.maxIter: 5, lr.labelCol: 'l', lr.predictionCol: 'p'}, \
38+
{lr.regParam: 2.0, lr.featuresCol: 'f', lr.maxIter: 5, lr.labelCol: 'l', lr.predictionCol: 'p'}, \
39+
{lr.regParam: 3.0, lr.featuresCol: 'f', lr.maxIter: 5, lr.labelCol: 'l', lr.predictionCol: 'p'}]
40+
>>> fail_count = 0
41+
>>> for e in expected:
42+
... if e not in output:
43+
... fail_count += 1
44+
>>> if len(expected) != len(output):
45+
... fail_count += 1
46+
>>> fail_count
47+
0
48+
"""
49+
50+
def __init__(self):
51+
self._param_grid = {}
52+
53+
def addGrid(self, param, values):
54+
"""
55+
Sets the given parameters in this grid to fixed values.
56+
"""
57+
self._param_grid[param] = values
58+
59+
return self
60+
61+
def baseOn(self, *args):
62+
"""
63+
Sets the given parameters in this grid to fixed values.
64+
Accepts either a parameter dictionary or a list of (parameter, value) pairs.
65+
"""
66+
if isinstance(args[0], dict):
67+
self.baseOn(*args[0].items())
68+
else:
69+
for (param, value) in args:
70+
self.addGrid(param, [value])
71+
72+
return self
73+
74+
def build(self):
75+
"""
76+
Builds and returns all combinations of parameters specified
77+
by the param grid.
78+
"""
79+
param_maps = [{}]
80+
for (param, values) in self._param_grid.items():
81+
new_param_maps = []
82+
for value in values:
83+
for old_map in param_maps:
84+
copied_map = old_map.copy()
85+
copied_map[param] = value
86+
new_param_maps.append(copied_map)
87+
param_maps = new_param_maps
88+
89+
return param_maps
90+
91+
92+
if __name__ == "__main__":
93+
import doctest
94+
doctest.testmod()

python/run-tests

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ function run_ml_tests() {
9898
echo "Run ml tests ..."
9999
run_test "pyspark/ml/feature.py"
100100
run_test "pyspark/ml/classification.py"
101+
run_test "pyspark/ml/tuning.py"
101102
run_test "pyspark/ml/tests.py"
102103
}
103104

0 commit comments

Comments
 (0)