commit
fea9f00597
|
@ -1,14 +1,38 @@
|
||||||
|
APIs Console Project Setup:
|
||||||
|
------------
|
||||||
|
If you have not yet, you must set your APIs Console project to enable Prediction
|
||||||
|
API and Google Storage. Go to APIs Console https://code.google.com/apis/console/
|
||||||
|
and select the project you want to use. Next, go to Services, and enable both
|
||||||
|
Prediction API and Google Storage. You may also need to enable Billing (Billing)
|
||||||
|
in the left menu.
|
||||||
|
|
||||||
|
|
||||||
Data Setup:
|
Data Setup:
|
||||||
----------
|
----------
|
||||||
Before you can run the prediction sample prediction.rb, you must load some csv
|
Before you can run the prediction sample prediction.rb, you must load some csv
|
||||||
formatted data into Google Storage. You can do this by running setup.sh with a
|
formatted data into Google Storage.
|
||||||
bucket/object name of your choice. You must first create the bucket you want to
|
|
||||||
use. This can be done with the gsutil function or via the web UI (Storage
|
1 - You must first create the bucket you want to use. This can be done
|
||||||
Access) in the Google APIs Console. i.e.:
|
with the gsutil function or via the web UI (Storage Access) in the Google
|
||||||
|
APIs Console. i.e.
|
||||||
|
# gsutil mb gs://BUCKET
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
Go to APIs Console -> Storage Access (on left) and the Google Storage Manager,
|
||||||
|
and create your bucket there.
|
||||||
|
|
||||||
|
2 - We now load the data you want to use to Google Storage. We have supplied a
|
||||||
|
basic language identification dataset in the sample for testing.
|
||||||
|
|
||||||
# chmod 744 setup.sh
|
# chmod 744 setup.sh
|
||||||
# ./setup.sh BUCKET/OBJECT
|
# ./setup.sh BUCKET/OBJECT
|
||||||
Note you need gsutil in your path for this to work.
|
Note you need gsutil in your path for this to work.
|
||||||
|
|
||||||
|
If you have your own dataset, you can do this manually as well.
|
||||||
|
gsutil cp your_dataset.csv gs://BUCKET/your_dataset.csv
|
||||||
|
|
||||||
|
|
||||||
In the script, you must then modify the datafile string. This must correspond with the
|
In the script, you must then modify the datafile string. This must correspond with the
|
||||||
bucket/object of your dataset (if you are using your own dataset). We have
|
bucket/object of your dataset (if you are using your own dataset). We have
|
||||||
provided a setup.sh which will upload some basic sample data. The section is
|
provided a setup.sh which will upload some basic sample data. The section is
|
||||||
|
@ -28,7 +52,7 @@ API. You can also set it up so the user can grant access.
|
||||||
First, run the google-api script to generate access and refresh tokens. Ex.
|
First, run the google-api script to generate access and refresh tokens. Ex.
|
||||||
|
|
||||||
# cd google-api-ruby-client
|
# cd google-api-ruby-client
|
||||||
# ruby-1.9.2-p290 bin/google-api oauth-2-login --scope=https://www.googleapis.com/auth/prediction --client-id=NUMBER.apps.googleusercontent.com --client-secret=CLIENT_SECRET
|
# ruby bin/google-api oauth-2-login --scope=https://www.googleapis.com/auth/prediction --client-id=NUMBER.apps.googleusercontent.com --client-secret=CLIENT_SECRET
|
||||||
|
|
||||||
Fill in your client-id and client-secret from the API Access page. You will
|
Fill in your client-id and client-secret from the API Access page. You will
|
||||||
probably have to set a redirect URI in your client ID
|
probably have to set a redirect URI in your client ID
|
||||||
|
@ -46,6 +70,25 @@ you are loading it as a yaml, ensure you rename/move the file, as the
|
||||||
move the .google-api.yaml file to the sample directory.
|
move the .google-api.yaml file to the sample directory.
|
||||||
|
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
-------
|
||||||
|
At this, point, you should have
|
||||||
|
- Enabled your APIs Console account
|
||||||
|
- Created a storage bucket, if required
|
||||||
|
- Uploaded some data to Google Storage
|
||||||
|
- Modified the script to point the 'datafile' variable to the BUCKET/OBJECT name
|
||||||
|
- Modified the script to put your credentials in, either in the code or by
|
||||||
|
loading the generated .yaml file
|
||||||
|
|
||||||
|
We can now run the service!
|
||||||
|
# ruby prediction.rb
|
||||||
|
|
||||||
|
This should start a service on http://localhost:4567. When you hit the service,
|
||||||
|
your ruby logs should show the Prediction API calls, and print the prediction
|
||||||
|
output in the debug.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This sample currently does not cover some newer features of Prediction API such
|
This sample currently does not cover some newer features of Prediction API such
|
||||||
as streaming training, hosted models or class weights. If there are any
|
as streaming training, hosted models or class weights. If there are any
|
||||||
questions or suggestions to improve the script please email us at
|
questions or suggestions to improve the script please email us at
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
# Original Author:: Bob Aman, Winton Davies, Robert Kaplow
|
# Original Author:: Bob Aman, Winton Davies, Robert Kaplow
|
||||||
# Maintainer:: Robert Kaplow (mailto:rkaplow@google.com)
|
# Maintainer:: Robert Kaplow (mailto:rkaplow@google.com)
|
||||||
|
|
||||||
$:.unshift('lib')
|
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'sinatra'
|
require 'sinatra'
|
||||||
require 'datamapper'
|
require 'datamapper'
|
||||||
|
@ -61,7 +60,7 @@ before do
|
||||||
@client.authorization.redirect_uri = to('/oauth2callback')
|
@client.authorization.redirect_uri = to('/oauth2callback')
|
||||||
|
|
||||||
# Workaround for now as expires_in may be nil, but when converted to int it becomes 0.
|
# Workaround for now as expires_in may be nil, but when converted to int it becomes 0.
|
||||||
@client.authorization.expires_in = Time.now + 1800 if @client.authorization.expires_in.to_i == 0
|
@client.authorization.expires_in = 1800 if @client.authorization.expires_in.to_i == 0
|
||||||
|
|
||||||
if session[:token_id]
|
if session[:token_id]
|
||||||
# Load the access token here if it's available
|
# Load the access token here if it's available
|
||||||
|
@ -109,6 +108,7 @@ get '/' do
|
||||||
# Do a prediction.
|
# Do a prediction.
|
||||||
# FILL IN DESIRED INPUT:
|
# FILL IN DESIRED INPUT:
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
|
# Note, the input features should match the features of the dataset.
|
||||||
prediction,score = get_prediction(datafile, ["Alice noticed with some surprise."])
|
prediction,score = get_prediction(datafile, ["Alice noticed with some surprise."])
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -127,10 +127,11 @@ end
|
||||||
def train(datafile)
|
def train(datafile)
|
||||||
input = "{\"id\" : \"#{datafile}\"}"
|
input = "{\"id\" : \"#{datafile}\"}"
|
||||||
puts "training input: #{input}"
|
puts "training input: #{input}"
|
||||||
status, headers, body = @client.execute(@prediction.training.insert,
|
result = @client.execute(:api_method => @prediction.training.insert,
|
||||||
{},
|
:merged_body => input,
|
||||||
input,
|
:headers => {'Content-Type' => 'application/json'}
|
||||||
{'Content-Type' => 'application/json'})
|
)
|
||||||
|
status, headers, body = result.response
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -141,8 +142,9 @@ end
|
||||||
# then the correct string is "bucket/object"
|
# then the correct string is "bucket/object"
|
||||||
# @return [Integer] status The HTTP status code of the training job.
|
# @return [Integer] status The HTTP status code of the training job.
|
||||||
def get_training_status(datafile)
|
def get_training_status(datafile)
|
||||||
status, headers, body = @client.execute(@prediction.training.get,
|
result = @client.execute(:api_method => @prediction.training.get,
|
||||||
{'data' => datafile})
|
:parameters => {'data' => datafile})
|
||||||
|
status, headers, body = result.response
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -157,11 +159,14 @@ end
|
||||||
|
|
||||||
def is_done?(datafile)
|
def is_done?(datafile)
|
||||||
status = get_training_status(datafile)
|
status = get_training_status(datafile)
|
||||||
while true do
|
# We use an exponential backoff approach here.
|
||||||
|
test_counter = 0
|
||||||
|
while test_counter < 10 do
|
||||||
puts "Attempting to check model #{datafile} - Status: #{status} "
|
puts "Attempting to check model #{datafile} - Status: #{status} "
|
||||||
return true if status == 200
|
return true if status == 200
|
||||||
sleep 10
|
sleep 5 * (test_counter + 1)
|
||||||
status = get_training_status(datafile)
|
status = get_training_status(datafile)
|
||||||
|
test_counter += 1
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -184,12 +189,15 @@ def get_prediction(datafile,input_features)
|
||||||
# We take the input features and put it in the right input (json) format.
|
# We take the input features and put it in the right input (json) format.
|
||||||
input="{\"input\" : { \"csvInstance\" : #{input_features}}}"
|
input="{\"input\" : { \"csvInstance\" : #{input_features}}}"
|
||||||
puts "Prediction Input: #{input}"
|
puts "Prediction Input: #{input}"
|
||||||
status, headers, body = @client.execute(@prediction.training.predict,
|
result = @client.execute(:api_method => @prediction.training.predict,
|
||||||
{'data' => datafile},
|
:parameters => {'data' => datafile},
|
||||||
input,
|
:merged_body => input,
|
||||||
{'Content-Type' => 'application/json'})
|
:headers => {'Content-Type' => 'application/json'})
|
||||||
prediction_data = JSON.parse(body[0])
|
status, headers, body = result.response
|
||||||
|
prediction_data = result.data
|
||||||
|
puts status
|
||||||
|
puts body
|
||||||
|
puts prediction_data
|
||||||
# Categorical
|
# Categorical
|
||||||
if prediction_data["outputLabel"] != nil
|
if prediction_data["outputLabel"] != nil
|
||||||
# Pull the most likely label.
|
# Pull the most likely label.
|
||||||
|
|
Loading…
Reference in New Issue