google-prediction 0.1.1 → 0.1.2
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.
- data/lib/google-prediction.rb +157 -159
- metadata +6 -5
data/lib/google-prediction.rb
CHANGED
@@ -1,178 +1,176 @@
|
|
1
|
-
# Provides an interface to the Google Prediction API.
|
2
|
-
#
|
3
|
-
# Author:: Sam King (samking@cs.stanford.edu)
|
4
|
-
# Copyright:: InSTEDD[http://instedd.org]
|
5
|
-
# License:: GPLv3
|
6
|
-
|
7
1
|
$:.unshift(File.dirname(__FILE__)) unless
|
8
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
9
3
|
|
10
4
|
require 'curb'
|
11
5
|
require 'json'
|
12
6
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
# Provides an interface to the Google Prediction API.
|
8
|
+
#
|
9
|
+
# Author:: Sam King (samking@cs.stanford.edu)
|
10
|
+
# Copyright:: InSTEDD[http://instedd.org]
|
11
|
+
# License:: GPLv3
|
12
|
+
#
|
13
|
+
# ---
|
14
|
+
#
|
15
|
+
# = Usage
|
16
|
+
#
|
17
|
+
# auth_token = GooglePrediction.get_auth_token('foo@gmail.com', 'password')
|
18
|
+
# => long string of letters and numbers
|
19
|
+
#
|
20
|
+
# predictor = GooglePrediction.new(auth_token, 'bucket', 'object')
|
21
|
+
#
|
22
|
+
# predictor.#train
|
23
|
+
# => {"data"=>{"data"=>"bucket/object"}}
|
24
|
+
#
|
25
|
+
# predictor.#check_training
|
26
|
+
# => "Training has not completed"
|
27
|
+
#
|
28
|
+
# wait_some_time
|
29
|
+
#
|
30
|
+
# predictor.#check_training
|
31
|
+
# => "no estimate available" or something between "0.0" and "1.0"
|
32
|
+
#
|
33
|
+
# predictor.#predict "awesome company"
|
34
|
+
# => "Google"
|
35
|
+
# predictor.#predict "awesome nonprofit"
|
36
|
+
# => "InSTEDD"
|
37
|
+
# predictor.#predict 13
|
38
|
+
# => "lucky"
|
39
|
+
# predictor.#predict [3, 5, 7, 11]
|
40
|
+
# => "prime"
|
41
|
+
class GooglePrediction
|
42
|
+
PREDICTION_URL_PREFIX = 'https://www.googleapis.com/prediction/v1/training'
|
43
|
+
|
44
|
+
attr_reader :auth_code
|
45
|
+
attr_reader :bucket
|
46
|
+
attr_reader :object
|
47
|
+
|
48
|
+
# Gets the auth code from Google's ClientLogin using the provided email
|
49
|
+
# and password.
|
20
50
|
#
|
21
|
-
#
|
51
|
+
# This will fail if Google requires a Captcha. If so, follow the
|
52
|
+
# instructions at
|
53
|
+
# http://code.google.com/apis/predict/docs/getting-started.html
|
54
|
+
# and pass in the new URL and new arguments using the optional parameters.
|
55
|
+
def self.get_auth_token(email, password, url='https://www.google.com/accounts/ClientLogin', args={})
|
56
|
+
curl = Curl::Easy.new(url)
|
57
|
+
post_args = {
|
58
|
+
"accountType" => "HOSTED_OR_GOOGLE",
|
59
|
+
"Email" => email,
|
60
|
+
"Passwd" => curl.escape(password),
|
61
|
+
"source" => "companyName-applicationName-versionID",
|
62
|
+
"service" => "xapi"
|
63
|
+
}
|
64
|
+
args.each {|key, val| post_args[key] = val }
|
65
|
+
post_fields = post_args.map {|k,v| Curl::PostField.content(k, v) }
|
66
|
+
curl.http_post(post_fields)
|
67
|
+
curl.body_str.match('Auth.*')[0][5..-1]
|
68
|
+
end
|
69
|
+
|
70
|
+
# auth_code: the login code generated from self.get_auth_token
|
22
71
|
#
|
23
|
-
#
|
24
|
-
# => {"data"=>{"data"=>"bucket/object"}}
|
72
|
+
# bucket: the name of the bucket in Google Storage
|
25
73
|
#
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# => "no estimate available" or something between "0.0" and "1.0"
|
33
|
-
#
|
34
|
-
# predictor.#predict "awesome company"
|
35
|
-
# => "Google"
|
36
|
-
# predictor.#predict "awesome nonprofit"
|
37
|
-
# => "InSTEDD"
|
38
|
-
# predictor.#predict 13
|
39
|
-
# => "lucky"
|
40
|
-
# predictor.#predict [3, 5, 7, 11]
|
41
|
-
# => "prime"
|
42
|
-
class GooglePrediction
|
43
|
-
PREDICTION_URL_PREFIX = 'https://www.googleapis.com/prediction/v1/training'
|
44
|
-
|
45
|
-
attr_reader :auth_code
|
46
|
-
attr_reader :bucket
|
47
|
-
attr_reader :object
|
48
|
-
|
49
|
-
# Gets the auth code from Google's ClientLogin using the provided email
|
50
|
-
# and password.
|
51
|
-
#
|
52
|
-
# This will fail if Google requires a Captcha. If so, follow the
|
53
|
-
# instructions at
|
54
|
-
# http://code.google.com/apis/predict/docs/getting-started.html
|
55
|
-
# and pass in the new URL and new arguments using the optional parameters.
|
56
|
-
def self.get_auth_token(email, password, url='https://www.google.com/accounts/ClientLogin', args={})
|
57
|
-
curl = Curl::Easy.new(url)
|
58
|
-
post_args = {
|
59
|
-
"accountType" => "HOSTED_OR_GOOGLE",
|
60
|
-
"Email" => email,
|
61
|
-
"Passwd" => curl.escape(password),
|
62
|
-
"source" => "companyName-applicationName-versionID",
|
63
|
-
"service" => "xapi"
|
64
|
-
}
|
65
|
-
args.each {|key, val| post_args[key] = val }
|
66
|
-
post_fields = post_args.map {|k,v| Curl::PostField.content(k, v) }
|
67
|
-
curl.http_post(post_fields)
|
68
|
-
curl.body_str.match('Auth.*')[0][5..-1]
|
69
|
-
end
|
70
|
-
|
71
|
-
# auth_code: the login code generated from self.get_auth_token
|
72
|
-
#
|
73
|
-
# bucket: the name of the bucket in Google Storage
|
74
|
-
#
|
75
|
-
# object: the filename of the object to do prediction on
|
76
|
-
def initialize(auth_code, bucket, object)
|
77
|
-
@auth_code=auth_code
|
78
|
-
@bucket=bucket
|
79
|
-
@object=object
|
80
|
-
end
|
81
|
-
|
82
|
-
# Starts training on the specified object.
|
83
|
-
#
|
84
|
-
# Returns
|
85
|
-
# {"data"=>{"data"=>"bucket/object"}}
|
86
|
-
# on success, and
|
87
|
-
# {"errors"=>{"errors"=>[{all of your errors}], "code"=>code, "message"=>message}}
|
88
|
-
# on error.
|
89
|
-
def train
|
90
|
-
url = PREDICTION_URL_PREFIX + "?data=" + @bucket + "%2F" + @object
|
91
|
-
curl = Curl::Easy.new(url)
|
92
|
-
curl.post_body = JSON.generate({:data => {}})
|
93
|
-
curl.headers = {"Content-Type" => "application/json",
|
94
|
-
"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
95
|
-
curl.http("POST")
|
96
|
-
JSON.parse(curl.body_str)
|
97
|
-
end
|
98
|
-
|
99
|
-
# Gets the training status of the specified object.
|
100
|
-
#
|
101
|
-
# If the training is incomplete, returns "Training has not completed".
|
102
|
-
# If the training did not have enough data to do cross-fold validation,
|
103
|
-
# returns "no estimate available".
|
104
|
-
# If the training went as desired, returns the accuracy of the training
|
105
|
-
# from 0 to 1.
|
106
|
-
#
|
107
|
-
# Returns
|
108
|
-
# {"errors"=>{"errors"=>[{all of your errors}], "code"=>code, "message"=>message}}
|
109
|
-
# on error.
|
110
|
-
def check_training
|
111
|
-
url = PREDICTION_URL_PREFIX + "/" + @bucket + "%2F" + @object
|
112
|
-
curl = Curl::Easy.new(url)
|
113
|
-
curl.headers = {"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
114
|
-
curl.http_get
|
115
|
-
|
116
|
-
# response will be
|
117
|
-
# {"data"=>{"data"=>"bucket/object", "modelinfo"=>accuracy_prediction}}
|
118
|
-
# on success
|
119
|
-
response = JSON.parse(curl.body_str)
|
120
|
-
return response["data"]["modelinfo"] unless response["data"].nil?
|
121
|
-
return response
|
122
|
-
end
|
74
|
+
# object: the filename of the object to do prediction on
|
75
|
+
def initialize(auth_code, bucket, object)
|
76
|
+
@auth_code=auth_code
|
77
|
+
@bucket=bucket
|
78
|
+
@object=object
|
79
|
+
end
|
123
80
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
elsif submission.is_a? Array
|
141
|
-
post_body[:data][:input] = {:numeric => submission}
|
142
|
-
else
|
143
|
-
raise Exception.new("submission must be String, Fixnum, or Array")
|
144
|
-
end
|
145
|
-
curl.post_body = JSON.generate(post_body)
|
146
|
-
curl.headers = {"Content-Type" => "application/json",
|
147
|
-
"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
148
|
-
curl.http("POST")
|
81
|
+
# Starts training on the specified object.
|
82
|
+
#
|
83
|
+
# Returns
|
84
|
+
# {"data"=>{"data"=>"bucket/object"}}
|
85
|
+
# on success, and
|
86
|
+
# {"errors"=>{"errors"=>[{all of your errors}], "code"=>code, "message"=>message}}
|
87
|
+
# on error.
|
88
|
+
def train
|
89
|
+
url = PREDICTION_URL_PREFIX + "?data=" + @bucket + "%2F" + @object
|
90
|
+
curl = Curl::Easy.new(url)
|
91
|
+
curl.post_body = JSON.generate({:data => {}})
|
92
|
+
curl.headers = {"Content-Type" => "application/json",
|
93
|
+
"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
94
|
+
curl.http("POST")
|
95
|
+
JSON.parse(curl.body_str)
|
96
|
+
end
|
149
97
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
98
|
+
# Gets the training status of the specified object.
|
99
|
+
#
|
100
|
+
# If the training is incomplete, returns "Training has not completed".
|
101
|
+
# If the training did not have enough data to do cross-fold validation,
|
102
|
+
# returns "no estimate available".
|
103
|
+
# If the training went as desired, returns the accuracy of the training
|
104
|
+
# from 0 to 1.
|
105
|
+
#
|
106
|
+
# Returns
|
107
|
+
# {"errors"=>{"errors"=>[{all of your errors}], "code"=>code, "message"=>message}}
|
108
|
+
# on error.
|
109
|
+
def check_training
|
110
|
+
url = PREDICTION_URL_PREFIX + "/" + @bucket + "%2F" + @object
|
111
|
+
curl = Curl::Easy.new(url)
|
112
|
+
curl.headers = {"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
113
|
+
curl.http_get
|
114
|
+
|
115
|
+
# response will be
|
116
|
+
# {"data"=>{"data"=>"bucket/object", "modelinfo"=>accuracy_prediction}}
|
117
|
+
# on success
|
118
|
+
response = JSON.parse(curl.body_str)
|
119
|
+
return response["data"]["modelinfo"] unless response["data"].nil?
|
120
|
+
return response
|
121
|
+
end
|
157
122
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
123
|
+
# Submission must be either a string, a single number,
|
124
|
+
# or an array of numbers
|
125
|
+
#
|
126
|
+
# Gets the prediction for the label of the submission based on the training.
|
127
|
+
#
|
128
|
+
# Returns the prediction on success and
|
129
|
+
# {"errors"=>{"errors"=>[{all of your errors}], "code"=>code, "message"=>message}}
|
130
|
+
# on error.
|
131
|
+
def predict(submission)
|
132
|
+
url = PREDICTION_URL_PREFIX + "/" + @bucket + "%2F" + @object + "/predict"
|
133
|
+
curl = Curl::Easy.new(url)
|
134
|
+
post_body = {:data => {:input => {}}}
|
135
|
+
if submission.is_a? String
|
136
|
+
post_body[:data][:input] = {:text => [submission]}
|
137
|
+
elsif submission.is_a? Fixnum
|
138
|
+
post_body[:data][:input] = {:numeric => [submission]}
|
139
|
+
elsif submission.is_a? Array
|
140
|
+
post_body[:data][:input] = {:numeric => submission}
|
141
|
+
else
|
142
|
+
raise Exception.new("submission must be String, Fixnum, or Array")
|
162
143
|
end
|
144
|
+
curl.post_body = JSON.generate(post_body)
|
145
|
+
curl.headers = {"Content-Type" => "application/json",
|
146
|
+
"Authorization" => "GoogleLogin auth=#{@auth_code}"}
|
147
|
+
curl.http("POST")
|
148
|
+
|
149
|
+
# response will be
|
150
|
+
# {"data"=>{"output"=>{"output_label"=>label}}}
|
151
|
+
# on success
|
152
|
+
response = JSON.parse(curl.body_str)
|
153
|
+
return response["data"]["output"]["output_label"] unless response["data"].nil?
|
154
|
+
return response
|
155
|
+
end
|
163
156
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
157
|
+
# Wrapper. Creates a new object and runs #train on it.
|
158
|
+
def self.train(auth_code, bucket, object)
|
159
|
+
predictor = GooglePrediction.new(auth_code, bucket, object)
|
160
|
+
predictor.train
|
161
|
+
end
|
169
162
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
163
|
+
# Wrapper. Creates a new object and runs #check_training on it.
|
164
|
+
def self.check_training(auth_code, bucket, object)
|
165
|
+
predictor = GooglePrediction.new(auth_code, bucket, object)
|
166
|
+
predictor.check_training
|
167
|
+
end
|
175
168
|
|
169
|
+
# Wrapper. Creates a new object and runs #predict on it.
|
170
|
+
def self.predict(auth_code, bucket, object, submission)
|
171
|
+
predictor = GooglePrediction.new(auth_code, bucket, object)
|
172
|
+
predictor.predict(submission)
|
176
173
|
end
|
177
174
|
|
178
175
|
end
|
176
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-prediction
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sam King
|
@@ -70,8 +70,9 @@ homepage: http://code.google.com/p/ruby-google-prediction/
|
|
70
70
|
licenses: []
|
71
71
|
|
72
72
|
post_install_message:
|
73
|
-
rdoc_options:
|
74
|
-
|
73
|
+
rdoc_options:
|
74
|
+
- -SNm
|
75
|
+
- GooglePrediction
|
75
76
|
require_paths:
|
76
77
|
- lib
|
77
78
|
required_ruby_version: !ruby/object:Gem::Requirement
|