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