pycall 0.1.0.alpha.20170711 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +13 -1
- data/CHANGES.md +35 -0
- data/Gemfile +0 -5
- data/README.md +41 -49
- data/Rakefile +22 -1
- data/appveyor.yml +9 -26
- data/examples/classifier_comparison.rb +52 -52
- data/examples/hist.rb +11 -11
- data/examples/notebooks/classifier_comparison.ipynb +51 -66
- data/examples/notebooks/forest_importances.ipynb +26 -49
- data/examples/notebooks/iruby_integration.ipynb +15 -36
- data/examples/notebooks/lorenz_attractor.ipynb +16 -47
- data/examples/notebooks/polar_axes.ipynb +29 -64
- data/examples/notebooks/sum_benchmarking.ipynb +109 -103
- data/examples/notebooks/xkcd_style.ipynb +12 -12
- data/examples/plot_forest_importances_faces.rb +8 -8
- data/examples/sum_benchmarking.rb +15 -19
- data/ext/pycall/extconf.rb +3 -0
- data/ext/pycall/gc.c +74 -0
- data/ext/pycall/libpython.c +217 -0
- data/ext/pycall/pycall.c +2184 -0
- data/ext/pycall/pycall_internal.h +700 -0
- data/ext/pycall/range.c +69 -0
- data/ext/pycall/ruby_wrapper.c +432 -0
- data/lib/pycall.rb +91 -19
- data/lib/pycall/dict.rb +28 -82
- data/lib/pycall/error.rb +10 -0
- data/lib/pycall/import.rb +45 -40
- data/lib/pycall/init.rb +44 -20
- data/lib/pycall/libpython.rb +6 -380
- data/lib/pycall/libpython/finder.rb +170 -0
- data/lib/pycall/list.rb +21 -51
- data/lib/pycall/pretty_print.rb +9 -0
- data/lib/pycall/pyerror.rb +14 -20
- data/lib/pycall/pyobject_wrapper.rb +157 -158
- data/lib/pycall/python/PyCall/__init__.py +1 -0
- data/lib/pycall/python/PyCall/six.py +23 -0
- data/lib/pycall/pytypeobject_wrapper.rb +79 -0
- data/lib/pycall/slice.rb +3 -22
- data/lib/pycall/tuple.rb +1 -7
- data/lib/pycall/version.rb +1 -1
- data/lib/pycall/wrapper_object_cache.rb +61 -0
- data/pycall.gemspec +4 -2
- data/tasks/pycall.rake +7 -0
- metadata +65 -27
- data/lib/pycall/eval.rb +0 -57
- data/lib/pycall/exception.rb +0 -13
- data/lib/pycall/pyobject.rb +0 -58
- data/lib/pycall/ruby_wrapper.rb +0 -137
- data/lib/pycall/type_object.rb +0 -11
- data/lib/pycall/types.rb +0 -19
- data/lib/pycall/utils.rb +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3989138be85724905ddd029fb3f74a7168070c02
|
4
|
+
data.tar.gz: 8ab3173bf2d1c2f92deec6b98241cc28d9768a03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 574f866b421b1010e907ff83ca9ce45725cd642af94004a1ab979a2b24f1605dfdeaa29c6090a159a6ac713d97cb9be4f20dc343e8edc21156e143b3845e8b95
|
7
|
+
data.tar.gz: fb03c20e8e60bc674c484f871848106ffe2ab5722ac1ba2331ea6f77075743320eef7d0bc9d320744486b1698a00a9c801182b4442d0e2f85905822d5f83818f
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -9,9 +9,12 @@ rvm:
|
|
9
9
|
- 2.1.10
|
10
10
|
|
11
11
|
env:
|
12
|
+
global:
|
13
|
+
- PYCALL_DEBUG_FIND_LIBPYTHON=1
|
14
|
+
matrix:
|
12
15
|
- PYTHON=python
|
13
16
|
- PYTHON=python3 LIBPYTHON=wrong_value
|
14
|
-
- LIBPYTHON=/
|
17
|
+
- LIBPYTHON=/opt/python/3.5.3/lib/libpython3.5m.so
|
15
18
|
|
16
19
|
addons:
|
17
20
|
apt:
|
@@ -19,11 +22,20 @@ addons:
|
|
19
22
|
- python3
|
20
23
|
- python3-dev
|
21
24
|
- python3-all
|
25
|
+
- python3-all-dev
|
22
26
|
|
23
27
|
before_install:
|
24
28
|
- gem update --system
|
25
29
|
- gem update bundler
|
26
30
|
|
27
31
|
before_script:
|
32
|
+
- bundle exec rake clobber compile
|
28
33
|
- echo === python investigator.py ===
|
29
34
|
- python lib/pycall/python/investigator.py
|
35
|
+
- python3 lib/pycall/python/investigator.py
|
36
|
+
- pip install numpy
|
37
|
+
- pip3 install numpy
|
38
|
+
|
39
|
+
matrix:
|
40
|
+
allow_failures:
|
41
|
+
- env: PYTHON=python # Ignore failed on python 2.7
|
data/CHANGES.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# The change history of PyCall
|
2
|
+
|
3
|
+
## 1.0.0
|
4
|
+
|
5
|
+
* `#[]` and `#[]=` accept a `Range` and an `Enumerable`, which is genated by
|
6
|
+
`Range#step`, as a slice.
|
7
|
+
|
8
|
+
* Rewrite almost all fundamental parts of PyCall as C extension.
|
9
|
+
|
10
|
+
* PyCall now calls `Py_DecRef` in the finalizer of `PyCall::PyPtr`.
|
11
|
+
|
12
|
+
* Change the system of object mapping between Python and Ruby, drastically.
|
13
|
+
Now PyCall does not have `PyObject` class for wrapper objects.
|
14
|
+
Instead, PyCall generally makes `Object` instances and extends them by
|
15
|
+
`PyObjectWrapper` module.
|
16
|
+
But for Python module objects, PyCall makes anonymous `Module` instances
|
17
|
+
that are extended by `PyObjectWrapper` module.
|
18
|
+
Moreover for Python type objects, PyCall makes `Class` instances and extends
|
19
|
+
them by `PyTypeObjectWrapper` module.
|
20
|
+
|
21
|
+
* Change `PyCall.eval` to be a wrapper of `__builtins__.eval` in Python.
|
22
|
+
This means that `filename:` and `input_type:` parameters are dropped.
|
23
|
+
Instead, two new parameters `globals:` and `locals:` are introduced.
|
24
|
+
`globals:` is used for specifying a dictionary that is the global
|
25
|
+
namespace referred by the evaluated expression.
|
26
|
+
`locals:` is used for specifying a mapping object that is the local
|
27
|
+
namespace referred by the evaluated expression.
|
28
|
+
|
29
|
+
* Add `PyCall.exec` for the replacement of the former `PyCall.eval`
|
30
|
+
with `input_type: :file`.
|
31
|
+
It has `globals:` and `locals:` parameters for the same meaning as
|
32
|
+
the new `PyCall.eval` described above.
|
33
|
+
|
34
|
+
* Drop `PyCall.wrap_ruby_callable` and `PyCall.wrap_ruby_object` always
|
35
|
+
craetes a callable Python object taht has an ID of the given Ruby object.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,10 @@
|
|
3
3
|
[](https://travis-ci.org/mrkn/pycall)
|
4
4
|
[](https://ci.appveyor.com/project/mrkn/pycall/branch/master)
|
5
5
|
|
6
|
-
This library provides the features to directly call and partially interoperate
|
6
|
+
This library provides the features to directly call and partially interoperate
|
7
|
+
with Python from the Ruby language. You can import arbitrary Python modules
|
8
|
+
into Ruby modules, call Python functions with automatic type conversion from
|
9
|
+
Ruby to Python.
|
7
10
|
|
8
11
|
## Installation
|
9
12
|
|
@@ -23,77 +26,66 @@ Or install it yourself as:
|
|
23
26
|
|
24
27
|
## Usage
|
25
28
|
|
26
|
-
Here is a simple example to call Python's `math.sin` function and compare it to
|
29
|
+
Here is a simple example to call Python's `math.sin` function and compare it to
|
30
|
+
the `Math.sin` in Ruby:
|
27
31
|
|
28
32
|
require 'pycall/import'
|
29
33
|
include PyCall::Import
|
30
34
|
pyimport :math
|
31
|
-
math.sin
|
32
|
-
# ^ This period is necessary
|
35
|
+
math.sin(math.pi / 4) - Math.sin(Math::PI / 4) # => 0.0
|
33
36
|
|
34
|
-
Type conversions from Ruby to Python are automatically performed for numeric,
|
37
|
+
Type conversions from Ruby to Python are automatically performed for numeric,
|
38
|
+
boolean, string, arrays, and hashes.
|
35
39
|
|
36
|
-
|
40
|
+
## PyCall object system
|
37
41
|
|
38
|
-
|
42
|
+
PyCall wraps pointers of Python objects in `PyCall::PyPtr` objects.
|
43
|
+
`PyCall::PyPtr` class has two subclasses, `PyCall::PyTypePtr` and
|
44
|
+
`PyCall::PyRubyPtr`. `PyCall::PyTypePtr` is specialized for type (and classobj
|
45
|
+
in 2.7) objects, and `PyCall::PyRubyPtr` is for the objects that wraps pointers
|
46
|
+
of Ruby objects.
|
39
47
|
|
40
|
-
|
48
|
+
These `PyCall::PyPtr` objects are used mainly in PyCall infrastructure.
|
49
|
+
Instead, we usually treats the instances of `Object`, `Class`, `Module`, or
|
50
|
+
other classes that are extended by `PyCall::PyObjectWrapper` module.
|
41
51
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
```ruby
|
49
|
-
require 'pycall'
|
50
|
-
|
51
|
-
class Ndarray
|
52
|
-
import PyCall::PyObjectWrapper
|
53
|
-
wrap_class PyCall.import_module('numpy').ndarray
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
Defineing incarnation classes using `wrap_class` registeres automatic type conversion, so it changes the class of wrapper object. For example:
|
58
|
-
|
59
|
-
require 'pycall/import'
|
60
|
-
include PyCall::Import
|
61
|
-
pyimport :numpy, as: :np
|
62
|
-
x1 = np.array(PyCall.tuple(10))
|
63
|
-
x1.class # => PyCall::PyObject
|
64
|
-
|
65
|
-
class Ndarray
|
66
|
-
import PyCall::PyObjectWrapper
|
67
|
-
wrap_class PyCall.import_module('numpy').ndarray
|
68
|
-
# NOTE: From here, numpy.ndarray objects are converted to Ndarray objects
|
69
|
-
end
|
70
|
-
|
71
|
-
x2 = np.array(PyCall.tuple(10))
|
72
|
-
x2.class # => Ndarray
|
73
|
-
|
74
|
-
|
75
|
-
**NOTE: I will write an efficient wrapper for numpy by RubyKaigi 2017.**
|
52
|
+
`PyCall::PyObjectWrapper` is a mix-in module for objects that wraps Python
|
53
|
+
objects. A wrapper object should have `PyCall::PyPtr` object in its instance
|
54
|
+
variable `@__pyptr__`. `PyCall::PyObjectWrapper` assumes the existance of
|
55
|
+
`@__pyptr__`, and provides general translation mechanisms between Ruby object
|
56
|
+
system and Python object system. For example, `PyCall::PyObjectWrapper`
|
57
|
+
translates Ruby's coerce system into Python's swapped operation protocol.
|
76
58
|
|
77
59
|
### Specifying the Python version
|
78
60
|
|
79
|
-
If you want to use a specific version of Python instead of the default,
|
61
|
+
If you want to use a specific version of Python instead of the default,
|
62
|
+
you can change the Python version by setting the `PYTHON` environment variable
|
63
|
+
to the path of the `python` executable.
|
80
64
|
|
81
65
|
## Development
|
82
66
|
|
83
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
67
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
68
|
+
Then, run `rake spec` to run the tests. You can also run `bin/console`
|
69
|
+
for an interactive prompt that will allow you to experiment.
|
84
70
|
|
85
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
71
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
72
|
+
To release a new version, update the version number in `version.rb`,
|
73
|
+
and then run `bundle exec rake release`, which will create a git tag for the
|
74
|
+
version, push git commits and tags, and push the `.gem` file to
|
75
|
+
[rubygems.org](https://rubygems.org).
|
86
76
|
|
87
77
|
## Contributing
|
88
78
|
|
89
|
-
Bug reports and pull requests are welcome on GitHub at
|
79
|
+
Bug reports and pull requests are welcome on GitHub at
|
80
|
+
https://github.com/mrkn/pycall.
|
90
81
|
|
91
82
|
|
92
83
|
## Acknowledgement
|
93
84
|
|
94
|
-
[PyCall.jl](https://github.com/JuliaPy/PyCall.jl) is referred too many times
|
85
|
+
[PyCall.jl](https://github.com/JuliaPy/PyCall.jl) is referred too many times
|
86
|
+
to implement this library.
|
95
87
|
|
96
88
|
## License
|
97
89
|
|
98
|
-
The gem is available as open source under the terms of the
|
99
|
-
|
90
|
+
The gem is available as open source under the terms of the
|
91
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,8 +1,29 @@
|
|
1
|
-
require "bundler
|
1
|
+
require "bundler"
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
require "rake/extensiontask"
|
2
6
|
require "rspec/core/rake_task"
|
3
7
|
|
4
8
|
Dir[File.expand_path('../tasks/**/*.rake', __FILE__)].each {|f| load f }
|
5
9
|
|
10
|
+
gem_spec = eval(File.read('pycall.gemspec'))
|
11
|
+
Rake::ExtensionTask.new('pycall', gem_spec) do |ext|
|
12
|
+
ext.lib_dir = File.join(*['lib', ENV['FAT_DIR']].compact)
|
13
|
+
ext.cross_compile = true
|
14
|
+
ext.cross_platform = %w[x86-mingw32 x64-mingw32]
|
15
|
+
ext.cross_compiling do |s|
|
16
|
+
s.files.concat %w[lib/2.2/pycall.so lib/2.3/pycall.so lib/2.4/pycall.so]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Compile binaries for mingw platform using rake-compiler-dock"
|
21
|
+
task 'build:mingw' do
|
22
|
+
require 'rake_compiler_dock'
|
23
|
+
RakeCompilerDock.sh "bundle && rake cross native gem RUBY_CC_VERSION=2.1.6:2.2.2:2.3.0:2.4.0"
|
24
|
+
end
|
25
|
+
|
6
26
|
RSpec::Core::RakeTask.new(:spec)
|
7
27
|
|
8
28
|
task :default => :spec
|
29
|
+
task spec: :compile
|
data/appveyor.yml
CHANGED
@@ -6,10 +6,6 @@ environment:
|
|
6
6
|
PYTHONDIR: "C:\\Python27"
|
7
7
|
PYTHON: "C:\\Python27\\python.exe"
|
8
8
|
|
9
|
-
- ruby_version: "21"
|
10
|
-
PYTHONDIR: "C:\\Python33"
|
11
|
-
PYTHON: "C:\\Python33\\python.exe"
|
12
|
-
|
13
9
|
- ruby_version: "21"
|
14
10
|
PYTHONDIR: "C:\\Python34"
|
15
11
|
PYTHON: "C:\\Python34\\python.exe"
|
@@ -27,10 +23,6 @@ environment:
|
|
27
23
|
PYTHONDIR: "C:\\Python27-x64"
|
28
24
|
PYTHON: "C:\\Python27-x64\\python.exe"
|
29
25
|
|
30
|
-
- ruby_version: "21-x64"
|
31
|
-
PYTHONDIR: "C:\\Python33-x64"
|
32
|
-
PYTHON: "C:\\Python33-x64\\python.exe"
|
33
|
-
|
34
26
|
- ruby_version: "21-x64"
|
35
27
|
PYTHONDIR: "C:\\Python34-x64"
|
36
28
|
PYTHON: "C:\\Python34-x64\\python.exe"
|
@@ -48,10 +40,6 @@ environment:
|
|
48
40
|
PYTHONDIR: "C:\\Python27"
|
49
41
|
PYTHON: "C:\\Python27\\python.exe"
|
50
42
|
|
51
|
-
- ruby_version: "22"
|
52
|
-
PYTHONDIR: "C:\\Python33"
|
53
|
-
PYTHON: "C:\\Python33\\python.exe"
|
54
|
-
|
55
43
|
- ruby_version: "22"
|
56
44
|
PYTHONDIR: "C:\\Python34"
|
57
45
|
PYTHON: "C:\\Python34\\python.exe"
|
@@ -69,10 +57,6 @@ environment:
|
|
69
57
|
PYTHONDIR: "C:\\Python27-x64"
|
70
58
|
PYTHON: "C:\\Python27-x64\\python.exe"
|
71
59
|
|
72
|
-
- ruby_version: "22-x64"
|
73
|
-
PYTHONDIR: "C:\\Python33-x64"
|
74
|
-
PYTHON: "C:\\Python33-x64\\python.exe"
|
75
|
-
|
76
60
|
- ruby_version: "22-x64"
|
77
61
|
PYTHONDIR: "C:\\Python34-x64"
|
78
62
|
PYTHON: "C:\\Python34-x64\\python.exe"
|
@@ -90,10 +74,6 @@ environment:
|
|
90
74
|
PYTHONDIR: "C:\\Python27"
|
91
75
|
PYTHON: "C:\\Python27\\python.exe"
|
92
76
|
|
93
|
-
- ruby_version: "23"
|
94
|
-
PYTHONDIR: "C:\\Python33"
|
95
|
-
PYTHON: "C:\\Python33\\python.exe"
|
96
|
-
|
97
77
|
- ruby_version: "23"
|
98
78
|
PYTHONDIR: "C:\\Python34"
|
99
79
|
PYTHON: "C:\\Python34\\python.exe"
|
@@ -111,10 +91,6 @@ environment:
|
|
111
91
|
PYTHONDIR: "C:\\Python27-x64"
|
112
92
|
PYTHON: "C:\\Python27-x64\\python.exe"
|
113
93
|
|
114
|
-
- ruby_version: "23-x64"
|
115
|
-
PYTHONDIR: "C:\\Python33-x64"
|
116
|
-
PYTHON: "C:\\Python33-x64\\python.exe"
|
117
|
-
|
118
94
|
- ruby_version: "23-x64"
|
119
95
|
PYTHONDIR: "C:\\Python34-x64"
|
120
96
|
PYTHON: "C:\\Python34-x64\\python.exe"
|
@@ -144,12 +120,19 @@ build: off
|
|
144
120
|
install:
|
145
121
|
- "SET PATH=%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%"
|
146
122
|
- "SET PATH=C:\\Ruby%ruby_version%\\bin;%PATH%"
|
147
|
-
- bundle install
|
123
|
+
- "bundle install"
|
124
|
+
- "pip install numpy"
|
148
125
|
|
149
126
|
before_test:
|
127
|
+
- "bundle exec rake -rdevkit clobber compile"
|
150
128
|
- ECHO "=== python investigator.py ==="
|
151
129
|
- "python lib\\pycall\\python\\investigator.py"
|
152
130
|
|
153
131
|
test_script:
|
154
|
-
- "SET
|
132
|
+
- "SET PYCALL_DEBUG_FIND_LIBPYTHON=1"
|
155
133
|
- rake
|
134
|
+
|
135
|
+
matrix:
|
136
|
+
allow_failures:
|
137
|
+
- PYTHONDIR: "C:\\Python27"
|
138
|
+
- PYTHONDIR: "C:\\Python27-x64"
|
@@ -34,18 +34,18 @@ names = [
|
|
34
34
|
]
|
35
35
|
|
36
36
|
classifiers = [
|
37
|
-
KNeighborsClassifier.(3),
|
38
|
-
SVC.(kernel: 'linear', C: 0.025),
|
39
|
-
SVC.(gamma: 2, C: 1),
|
40
|
-
DecisionTreeClassifier.(max_depth: 5),
|
41
|
-
RandomForestClassifier.(max_depth: 5, n_estimators: 10, max_features: 1),
|
42
|
-
AdaBoostClassifier.(),
|
43
|
-
GaussianNB.(),
|
44
|
-
LinearDiscriminantAnalysis.(),
|
45
|
-
QuadraticDiscriminantAnalysis.()
|
37
|
+
KNeighborsClassifier.new(3),
|
38
|
+
SVC.new(kernel: 'linear', C: 0.025),
|
39
|
+
SVC.new(gamma: 2, C: 1),
|
40
|
+
DecisionTreeClassifier.new(max_depth: 5),
|
41
|
+
RandomForestClassifier.new(max_depth: 5, n_estimators: 10, max_features: 1),
|
42
|
+
AdaBoostClassifier.new(),
|
43
|
+
GaussianNB.new(),
|
44
|
+
LinearDiscriminantAnalysis.new(),
|
45
|
+
QuadraticDiscriminantAnalysis.new()
|
46
46
|
]
|
47
47
|
|
48
|
-
x, y = make_classification
|
48
|
+
x, y = *make_classification(
|
49
49
|
n_features: 2,
|
50
50
|
n_redundant: 0,
|
51
51
|
n_informative: 2,
|
@@ -53,83 +53,83 @@ x, y = make_classification.(
|
|
53
53
|
n_clusters_per_class: 1
|
54
54
|
)
|
55
55
|
|
56
|
-
np.random.seed
|
57
|
-
x += 2 * np.random.random_sample
|
58
|
-
linearly_separable = PyCall.tuple(x, y)
|
56
|
+
np.random.seed(42)
|
57
|
+
x += 2 * np.random.random_sample(x.shape)
|
58
|
+
linearly_separable = PyCall.tuple([x, y]) # FIXME: allow PyCall.tuple(x, y)
|
59
59
|
|
60
60
|
datasets = [
|
61
|
-
make_moons
|
62
|
-
make_circles
|
61
|
+
make_moons(noise: 0.3, random_state: 0),
|
62
|
+
make_circles(noise: 0.2, factor: 0.5, random_state: 1),
|
63
63
|
linearly_separable
|
64
64
|
]
|
65
65
|
|
66
|
-
fig = plt.figure
|
66
|
+
fig = plt.figure(figsize: [27, 9])
|
67
67
|
i = 1
|
68
|
-
all =
|
68
|
+
all = 0..-1
|
69
69
|
datasets.each do |ds|
|
70
|
-
x, y = ds
|
71
|
-
x = StandardScaler.
|
72
|
-
x_train, x_test, y_train, y_test = train_test_split
|
70
|
+
x, y = *ds
|
71
|
+
x = StandardScaler.new.fit_transform(x)
|
72
|
+
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size: 0.4)
|
73
73
|
|
74
|
-
x_min, x_max = np.min
|
75
|
-
y_min, y_max = np.min
|
74
|
+
x_min, x_max = np.min(x[all, 0]) - 0.5, np.max(x[all, 0]) + 0.5
|
75
|
+
y_min, y_max = np.min(x[all, 1]) - 0.5, np.max(x[all, 1]) + 0.5
|
76
76
|
|
77
|
-
xx, yy = np.meshgrid
|
78
|
-
np.linspace
|
79
|
-
np.linspace
|
77
|
+
xx, yy = np.meshgrid(
|
78
|
+
np.linspace(x_min, x_max, ((x_max - x_min)/h).round),
|
79
|
+
np.linspace(y_min, y_max, ((y_max - y_min)/h).round),
|
80
80
|
)
|
81
|
-
mesh_points = np.dstack
|
81
|
+
mesh_points = np.dstack(PyCall.tuple([xx.ravel(), yy.ravel()]))[0, all, all]
|
82
82
|
|
83
83
|
# just plot the dataset first
|
84
|
-
cm = plt.cm.RdBu
|
85
|
-
cm_bright = mplc.ListedColormap.(["#FF0000", "#0000FF"])
|
86
|
-
ax = plt.subplot
|
84
|
+
cm = plt.cm.__dict__[:RdBu]
|
85
|
+
cm_bright = mplc.ListedColormap.new(["#FF0000", "#0000FF"])
|
86
|
+
ax = plt.subplot(datasets.length, classifiers.length + 1, i)
|
87
87
|
# plot the training points
|
88
|
-
ax.scatter
|
88
|
+
ax.scatter(x_train[all, 0], x_train[all, 1], c: y_train, cmap: cm_bright)
|
89
89
|
# and testing points
|
90
|
-
ax.scatter
|
90
|
+
ax.scatter(x_test[all, 0], x_test[all, 1], c: y_test, cmap: cm_bright, alpha: 0.6)
|
91
91
|
|
92
|
-
ax.set_xlim
|
93
|
-
ax.set_ylim
|
94
|
-
ax.set_xticks
|
95
|
-
ax.set_yticks
|
92
|
+
ax.set_xlim(np.min(xx), np.max(xx))
|
93
|
+
ax.set_ylim(np.min(yy), np.max(yy))
|
94
|
+
ax.set_xticks(PyCall.tuple())
|
95
|
+
ax.set_yticks(PyCall.tuple())
|
96
96
|
i += 1
|
97
97
|
|
98
98
|
# iterate over classifiers
|
99
99
|
names.zip(classifiers).each do |name, clf|
|
100
|
-
ax = plt.subplot
|
101
|
-
clf.fit
|
102
|
-
scor = clf.score
|
100
|
+
ax = plt.subplot(datasets.length, classifiers.length + 1, i)
|
101
|
+
clf.fit(x_train, y_train)
|
102
|
+
scor = clf.score(x_test, y_test)
|
103
103
|
|
104
104
|
# Plot the decision boundary. For that, we will assign a color to each
|
105
105
|
# point in the mesh [x_min, x_max]x[y_min, y_max]
|
106
106
|
begin
|
107
107
|
# not implemented for some
|
108
|
-
z = clf.decision_function
|
108
|
+
z = clf.decision_function(mesh_points)
|
109
109
|
rescue
|
110
|
-
z = clf.predict_proba
|
110
|
+
z = clf.predict_proba(mesh_points)[all, 1]
|
111
111
|
end
|
112
112
|
|
113
113
|
# Put the result into a color plot
|
114
|
-
z = z.reshape
|
115
|
-
ax.contourf
|
114
|
+
z = z.reshape(xx.shape)
|
115
|
+
ax.contourf(xx, yy, z, cmap: cm, alpha: 0.8)
|
116
116
|
|
117
117
|
# Plot also the training points
|
118
|
-
ax.scatter
|
118
|
+
ax.scatter(x_train[all, 0], x_train[all, 1], c: y_train, cmap: cm_bright)
|
119
119
|
# and testing points
|
120
|
-
ax.scatter
|
120
|
+
ax.scatter(x_test[all, 0], x_test[all, 1], c: y_test, cmap: cm_bright, alpha: 0.6)
|
121
121
|
|
122
|
-
ax.set_xlim
|
123
|
-
ax.set_ylim
|
124
|
-
ax.set_xticks
|
125
|
-
ax.set_yticks
|
126
|
-
ax.set_title
|
122
|
+
ax.set_xlim(np.min(xx), np.max(xx))
|
123
|
+
ax.set_ylim(np.min(yy), np.max(yy))
|
124
|
+
ax.set_xticks(PyCall.tuple())
|
125
|
+
ax.set_yticks(PyCall.tuple())
|
126
|
+
ax.set_title(name)
|
127
127
|
|
128
|
-
ax.text
|
128
|
+
ax.text(np.max(xx) - 0.3, np.min(yy) + 0.3, "%.2f" % scor, size: 15, horizontalalignment: 'right')
|
129
129
|
|
130
130
|
i += 1
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
fig.subplots_adjust
|
135
|
-
plt.show
|
134
|
+
fig.subplots_adjust(left: 0.02, right: 0.98)
|
135
|
+
plt.show()
|