Google Prediction API always returns a score of 1.0 or 0.0 - google-api-ruby-client

I'm using the the insert function of the google-api-ruby-client and passing in an array of trainingInstances.
When I call predict I used to get scores like 0.653264 and 0.346736 (using two output categories).
After doing some refactoring I now always get scores of 1.0 and 0.0 and no probabilities in between.
The prediction accuracy (measured by me) is still close to the accuracy given by the status function so it looks like the trained model is working. I just want to know why I'm not getting scores in between 1 and 0 as I would like to use those in my application.
Any insight would be much appreciated.
Here is a sample of the training data I'm using:
"Completed Registration",32.54,2,0,1,12
"Completed Registration",27.05,2,0,1,7
"Completed Registration",27.29,1,0,3,7
"Completed Registration",24.15,1,0,1,6
"Completed Registration",26.36,2,0,1,6
"Completed Registration",27.0,3,1,3,5
"Completed Registration",22.15,3,1,3,5
"Completed Registration",27.9,2,1,1,1
"Completed Registration",21.21,2,0,3,0
"Completed Registration",24.36,3,0,3,0
"Completed Registration",53.52,2,1,3,0
"Completed Registration",24.15,8,0,3,-6
"Cancelled Registration",,2,0,3,76
"Cancelled Registration",,2,0,3,76
"Cancelled Registration",,3,1,3,69
"Cancelled Registration",38.27,5,0,1,63
"Cancelled Registration",37.25,2,0,3,50
"Cancelled Registration",35.59,5,1,3,49
"Cancelled Registration",19.52,2,0,3,30
"Cancelled Registration",26.7,2,0,3,28
I've run tests on the Google API explorer and uploaded the training data in a CSV file.
The data I first uploaded (a few weeks ago) results in a range of scores. But the exact same data uploaded today results in scores of only 1 or 0.
Could this be a character encoding problem?

In case other people have the same question I'm posting an answer here. It turns out that internally the API can use different classifiers depending on the training data. It looks like the difference was caused by a change to the API and not by my refactoring.
Here is an explanation from someone at Google https://groups.google.com/forum/#!topic/prediction-api-discuss/7QPhONKhZjc

Related

Using grafana counter to visualize weather data

I'm trying to visualize my weather data using grafana. I've already made the prometheus part and now I face an issue that hunts me for quite a while.
I created an counter that adds temperature indoor every five minutes.
var tempIn = prometheus.NewCounter(prometheus.CounterOpts{
Name: "tempin",
Help: "Temperature indoor",
})
for {
tempIn.Add(station.Body.Devices[0].DashboardData.Temperature)
time.Sleep(time.Second*300)
}
How can I now visualize this data that it shows current temperature and stores it for unlimited time so I can look at it even 1 year later like an normal graph?
tempin{instance="localhost:9999"} will only display added up temperature so its useless for me. I need the current temperature not the added up one. I also tried rate(tempin{instance="localhost:9999"}[5m])
How to solve this issue?
Although a counter is not the best solution for this use case, you can use the operator increase.
Increase(tempin{instance="localhost:9999"}[5m])
This will tell you how much the counter increased in the last five minutes

How to send Base64 image to Google Cloud Vision API label detection in Ruby?

Hi I'm building a program in Ruby to generate alt attributes for images on a webpage. I'm scraping the page for the images then sending their src, in other words a URL, to google-cloud-vision for label detection and other Cloud Vision methods. It takes about 2-6 seconds per image. I'm wondering if there's any way to reduce response time. I first used TinyPNG to compress the images. Cloud Vision was a tad faster but the time it took to compress more than outweighed the improvement. How can I improve response time? I'll list some ideas.
1) Since we're sending a URL to Google Cloud, it takes time for Google Cloud to receive a response, that is from the img_src, before it can even analyze the image. Is it faster to send a base64 encoded image? What's the fastest form in which to send (or really, for Google to receive) an image?
cloud_vision = Google::Cloud::Vision.new project: PROJECT_ID
#vision = cloud_vision.image(#file_name)
#vision.labels #or #vision.web, etc.
2) My current code for label detection. First question: is it faster to send a JSON request rather than call Ruby (label or web) methods on a Google Cloud Project? If so, should I limit responses? Labels with less than a 0.6 confidence score don't seem of much help. Would that speed up image rec/processing time?
Open to any suggestions on how to speed up response time from Cloud Vision.
TL;DR - You can take advantage of the batching supporting in the annotation API for Cloud Vision.
Longer version
Google Cloud Vision API supports batching multiple requests in a single call to the images:annotate API. There are also these limits which are enforced for Cloud Vision:
Maximum of 16 images per request
Maximum 4 MB per image
Maximum of 8 MB total request size.
You could reduce the number of requests by batching 16 at a time (assuming you do not exceed any of the image size restrictions within the request):
#!/usr/bin/env ruby
require "google/cloud/vision"
image_paths = [
...
"./wakeupcat.jpg",
"./cat_meme_1.jpg",
"./cat_meme_2.jpg",
...
]
vision = Google::Cloud::Vision.new
length = image_paths.length
start = 0
request_count = 0
while start < length do
last = [start + 15, length - 1].min
current_image_paths = image_paths[start..last]
printf "Sending %d images in the request. start: %d last: %d\n", current_image_paths.length, start, last
result = vision.annotate *current_image_paths, labels: 1
printf "Result: %s\n", result
start += 16
request_count += 1
end
printf "Made %d requests\n", request_count
So you're using Ruby to scrape some images off a page and then send the image to Google, yeah?
Why you might not want to base64 encode the image:
Headless scraping becomes more network intensive. You have to download the image to then process it.
Now you also have to worry about adding in the base64 encode process
Potential storage concerns if you aren't just holding the image in memory (and if you do this, debugging becomes somewhat more challenging
Why you might want to base64 encode the image:
The image is not publicly accessible
You have to store the image anyway
Once you have weighed the choices, if you still want to get the image into base64 here is how you do it:
require 'base64'
Base64.encode(image_binary)
It really is that easy.
But how do I get that image in binary?
require 'curb'
# This line is an example and is not intended to be valid
img_binary = Curl::Easy.perform("http://www.imgur.com/sample_image.png").body_str
How do I send that to Google?
Google has a pretty solid write-up of this process here: Make a Vision API Request in JSON
If you can't click it (or are too lazy to) I have provided a zero-context copy-and-paste of what a request body should look like to their API here:
request_body_json = {
"requests":[
{
"image":{
"content":"/9j/7QBEUGhvdG9...image contents...eYxxxzj/Coa6Bax//Z"
},
"features":[
{
"type":"LABEL_DETECTION",
"maxResults":1
}
]
}
]
}
So now we know what a request should look like in the body. If you're already sending the img_src in a POST request, then it's as easy as this:
require 'base64'
require 'curb'
requests = []
for image in array_of_image_urls
img_binary = Curl::Easy.perform(image).body_str
image_in_base64 = Base64.encode(image_binary)
requests << { "image" => { "content" : image_in_base64 }, "imageContext" => "<OPTIONAL: SEE REFERENCE LINK>", "features" => [ {"type" => "LABEL_DETECTION", "maxResults" => 1 }]}
end
# Now just POST requests.to_json with your Authorization and such (You did read the reference right?)
Play around with the hash formatting and values as required. This is the general idea which is the best I can give you when your question is SUPER vague.

Firebase serverTimeOffset and Firebase.ServerValue.TIMESTAMP differences

Context
I have multiple servers listening to a specific collection (/items). Each of them use NTS for time calibration and the ".info/serverTimeOffset" to measure the expected time difference with Firebase. It is consistently around 20ms.
I have many clients pushing items to the collection with the specific field:
{
...
created: Firebase.database.ServerValue.TIMESTAMP
}
What is expected:
When the server receives the item from Firebase and subtracts the item.created with the Firebase expected time (Date.now() + offset), this value should be positive and probably around 10ms (time for the item to be sent from Firebase to the server).
What is happening:
When the server receives the items, the item.created field is superior to the Firebase expected time. Like it was created in the future. Usually the difference is around -5ms
Question:
What is the Firebase.database.ServerValue.TIMESTAMP set to ? and how is it related to the ".info/serverTimeOffset" ?
The 27th September 2016 at 1am UTC, that difference jumped from -5ms to around -5000ms like a kind of re-calibration happened (it lasted until I reset the .info/serverTimeOffset) Did someone experienced something similar?

Google Calendar API "The requested minimum modification time lies too far in the past." after just one day

My code fetches calendar events using service.events().list() with the following parameters:
timeMax: 2015-11-13T04:12:44.263000Z
timeMin: 2014-05-17T04:12:44.263000Z
updatedMin: 2014-11-12T14:56:20.395000Z # = yesterday
I know there's a limit on the updatedMin param that prevents it to be too far in the past, but lately I get the following error even when updatedMin is yesterday:
The requested minimum modification time lies too far in the past.
Everywhere this error is mentioned, they are talking about a limit that is approx. 20 days in the past, certainly not one day.
Any ideas what is causing this error?
#Tzach, I tried the above query in API explorer with the same values and it returned the results without any error unless its greater than 20days. As Luc said, better to switch to syncTokens which saves the bandwidth.

how to delay 'say' actions in siri proxy plugin

I've started to play with Ruby on Rails to make some plugins for Siri Proxy Server.
I am inexperienced with Ruby but have manage the basics.
what I have done:
################ Commands
listen_for (/show a demo to (.*)/i) do |name|
show_demo
request_completed
end
################ Actions
def show_demo(name)
say "Hi #{name}, let me do a quick demo for You."
say "For example if You tell me 'Turn on sidelight' I will turn the sidelights in Living room like now..."
system "/usr/local/bin/tdtool --on 2"
say "That was the sidelights, and now if like I can turn on the gallery for You, just tell me 'turn on gallery' like so... "
system "/usr/local/bin/tdtool --on 3"
say "This only part of things I can do after mod."
say "Now I will turn all devices off..."
system "/usr/local/bin/tdtool --off 3"
system "/usr/local/bin/tdtool --off 2"
say " Thank You #{name}, and goodbye."
end
The problem is when I'll start the demo all the actionssystem "..." are executed before Siri start to say anything .
How can I delay above action to put them in right place in time to execute them right after words I want?
Thank You in advance.
The problem is that say won't wait for Siri to actually say the words, it just sends a packet over to your iDevice and then goes on. The simplest approach i can think of would be to wait a few seconds, depending on how long the text is. So first we need a method that gives us the duration to wait (in seconds). I tried with the OSX built-in say command and got the following results:
$ time say "For example if You tell me 'Turn on sidelight' I will turn the sidelights in Living room like now..."
say 0,17s user 0,05s system 3% cpu 6,290 total
$ time say "That was the sidelights, and now if like I can turn on the gallery for You, just tell me 'turn on gallery' like so... "
say 0,17s user 0,06s system 2% cpu 8,055 total
$ time say "This only part of things I can do after mod."
say 0,13s user 0,04s system 5% cpu 2,996 total
So this means we have the following data:
# Characters w/o whitespace | Seconds to execute
------------------------------+---------------------
77 | 6.290
87 | 8.055
34 | 2.996
This leaves us with an average of about 0.0875 seconds per character. You may need to evaluate the average time for your scenario yourself and with more samples. This function will wrap say and then wait until the text was spoken out by Siri:
def say_and_wait text, seconds_per_char=0.0875
say text
num_speakable_chars = text.gsub(/[^\w]/,'').size
sleep num_speakable_chars * seconds_per_char
end
where gsub(/[^\w]/,'') will remove any non-word characters from the string. Now you can use this to simply say something and wait for it to be spoken out:
say_and_wait "This is a test, just checking if 0.875 seconds per character are a good fit."
Or you can also override the duration in special cases:
say_and_wait "I will wait for ten seconds here...", 10
Let me know if it works for you.

Resources