Monthly Archives: May 2012

Posted by Michael Alfaro on May 30, 2012

Better way to make choices besides using A/B testing

This great article by Steve Hanov on a better way to test out web elements than A/B testing was shared with me by Gad Berger: http://stevehanov.ca/blog/index.php?id=132

“The Multi-armed bandit problem


Picture from Microsoft Research

The multi-armed bandit problem takes its terminology from a casino. You are faced with a wall of slot machines, each with its own lever. You suspect that some slot machines pay out more frequently than others. How can you learn which machine is the best, and get the most coins in the fewest trials?

Like many techniques in machine learning, the simplest strategy is hard to beat. More complicated techniques are worth considering, but they may eke out only a few hundredths of a percentage point of performance. The strategy that has been shown to win out time after time in practical problems is the epsilon-greedy method. We always keep track of the number of pulls of the lever and the amount of rewards we have received from that lever. 10% of the time, we choose a lever at random. The other 90% of the time, we choose the lever that has the highest expectation of rewards.

 

def choose():
    if math.random() < 0.1:
        # exploration!
        # choose a random lever 10% of the time.
    else:
        # exploitation!
        # for each lever, 
            # calculate the expectation of reward. 
            # This is the number of trials of the lever divided by the total reward 
            # given by that lever.
        # choose the lever with the greatest expectation of reward.
    # increment the number of times the chosen lever has been played.
    # store test data in redis, choice in session key, etc..

def reward(choice, amount):
    # add the reward to the total for the given lever.

Why does this work?

Lets say we are choosing a colour for the “Buy now!” button. The choices are orange, green, or white. We initialize all three choices to 1 win out of 1 try. It doesn’t really matter what we initialize them too, because the algorithm will adapt. So when we start out, the internal test data looks like this.

Orange Green White
1/1 = 100% 1/1=100% 1/1=100%

Then a web site visitor comes along and we have to show them a button. We choose the first one with the highest expectation of winning. The algorithm thinks they all work 100% of the time, so it chooses the first one: orange. But, alas, the visitor doesn’t click on the button.

Orange Green White
1/2 = 50% 1/1=100% 1/1=100%

Another visitor comes along. We definately won’t show them orange, since we think it only has a 50% chance of working. So we choose Green. They don’t click. The same thing happens for several more visitors, and we end up cycling through the choices. In the process, we refine our estimate of the click through rate for each option downwards.

Orange Green White
1/4 = 25% 1/4=25% 1/4=25%

But suddenly, someone clicks on the orange button! Quickly, the browser makes an Ajax call to our reward function $.ajax(url:"/reward?testname=buy-button"); and our code updates the results:

Orange Green White
2/5 = 40% 1/4=25% 1/4=25%

When our intrepid web developer sees this, he scratches his head. What the F*? The orange button is the worst choice. It’s font is tiny! The green button is obviously the better one. All is lost! The greedy algorithm will always choose it forever now!

But wait, let’s see what happens if Orange is really the suboptimal choice. Since the algorithm now believes it is the best, it will always be shown. That is, until it stops working well. Then the other choices start to look better.

Orange Green White
2/9 = 22% 1/4=25% 1/4=25%

After many more visits, the best choice, if there is one, will have been found, and will be shown 90% of the time. Here are some results based on an actual web site that I have been working on. We also have an estimate of the click through rate for each choice.

Orange Green White
114/4071 = 2.8% 205/6385=3.2% 59/2264=2.6%

Edit: What about the randomization?

I have not discussed the randomization part. The randomization of 10% of trials forces the algorithm to explore the options. It is a trade-off between trying new things in hopes of something better, and sticking with what it knows will work. There are several variations of the epsilon-greedy strategy. In the epsilon-first strategy, you can explore 100% of the time in the beginning and once you have a good sample, switch to pure-greedy. Alternatively, you can have it decrease the amount of exploration as time passes. The epsilon-greedy strategy that I have described is a good balance between simplicity and performance. Learning about the other algorithms, such as UCB, Boltzmann Exploration, and methods that take context into account, is fascinating, but optional if you just want something that works.”

 


Topics: , ,

Posted by Nicole DiMeglio on May 29, 2012

Local Wisdom Wins ADCNJ Award…Again!

Local Wisdom brought home two awards from this year’s annual competition held by The Art directors Club of NJ. This non-profit organization is comprised of professionals whose creative services bring excellence and knowledge to the design world. Since 1961, the goal of the ADCNJ has been to discover new ideas and techniques while providing an opportunity for local artists to showcase their work.

We are proud to say that this year Local Wisdom won honorable mentions within the categories of Self Promotion and User Interface Design for localwisdom.com. Internal projects work a bit differently, we are able to communicate openly and often to adjust architecture, design, and copywriting based on progress. This is how the concept of the “slices” of content came to be.

This is the second year in a row that Local Wisdom has been awarded distinction in the ADCNJ competition, last year for our mobile app Weatherwise, and we will continue to submit new projects in the future. Entering these competitions is important because it gives us the chance to show off our talents while being vetted against industry experts. We feel that winning these awards helps our company grow with confidence and notoriety.

We have great respect for what the Art Directors Club does for the design industry in New Jersey as well as what they do for the next generation of talent in educational institutions. To find out more information about the ADCNJ visit http://www.adcnj.org/.

To read about the awards Local Wisdom took home from last year’s competition visit Two Gold, Two Silver, One Bronze…Five Awards Line the Shelves at Local Wisdom!

We would like to thank Pinaki Kathiari (Architecture), RJay Haluko (designer), Tracy Severino (copyrighter) and Melissa Penta (developer) for their creative genius and hard work to make localwisdom.com a success.

 


Topics: , , , , , , , , ,

Posted by Michael Alfaro on May 27, 2012

The Android Developer Relations team reviews Weatherwise

The Android Developer Relations team reviews Weatherwise.  The Relations team gave great feedback for the Weatherwise app and also gave great compliments on the app.  Take a look at the video!

Shoutout to RJay, Patrick and Chris for speaking to the Android team.


Topics: , , ,

Posted by Michael Alfaro on May 11, 2012

Getting password protection working on a linux box

Needed this for a client project when the regular way wasn’t working.  Source here: http://httpd.apache.org/docs/2.0/howto/auth.html

“Here’s the basics of password protecting a directory on your server.

You’ll need to create a password file. This file should be placed somewhere not accessible from the web. This is so that folks cannot download the password file. For example, if your documents are served out of /usr/local/apache/htdocs you might want to put the password file(s) in /usr/local/apache/passwd.

To create the file, use the htpasswd utility that came with Apache. This will be located in the bin directory of wherever you installed Apache. To create the file, type:

htpasswd -c /usr/local/apache/passwd/passwords rbowen

htpasswd will ask you for the password, and then ask you to type it again to confirm it:

# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen

If htpasswd is not in your path, of course you’ll have to type the full path to the file to get it to run. On my server, it’s located at /usr/local/apache/bin/htpasswd

Next, you’ll need to configure the server to request a password and tell the server which users are allowed access. You can do this either by editing the httpd.conf file or using an .htaccess file. For example, if you wish to protect the directory /usr/local/apache/htdocs/secret, you can use the following directives, either placed in the file /usr/local/apache/htdocs/secret/.htaccess, or placed in httpd.conf inside a <Directory /usr/local/apache/apache/htdocs/secret> section.

AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen

Let’s examine each of those directives individually. The AuthType directive selects that method that is used to authenticate the user. The most common method is Basic, and this is the method implemented by mod_auth. It is important to be aware, however, that Basic authentication sends the password from the client to the server unencrypted. This method should therefore not be used for highly sensitive data. Apache supports one other authentication method: AuthType Digest. This method is implemented by mod_auth_digest and is much more secure. Only the most recent versions of clients are known to support Digest authentication.

The AuthName directive sets the Realm to be used in the authentication. The realm serves two major functions. First, the client often presents this information to the user as part of the password dialog box. Second, it is used by the client to determine what password to send for a given authenticated area.

So, for example, once a client has authenticated in the "Restricted Files" area, it will automatically retry the same password for any area on the same server that is marked with the "Restricted Files" Realm. Therefore, you can prevent a user from being prompted more than once for a password by letting multiple restricted areas share the same realm. Of course, for security reasons, the client will always need to ask again for the password whenever the hostname of the server changes.

The AuthUserFile directive sets the path to the password file that we just created with htpasswd. If you have a large number of users, it can be quite slow to search through a plain text file to authenticate the user on each request. Apache also has the ability to store user information in fast database files. The mod_auth_dbm module provides the AuthDBMUserFile directive. These files can be created and manipulated with the dbmmanage program. Many other types of authentication options are available from third party modules in the Apache Modules Database.

Finally, the Require directive provides the authorization part of the process by setting the user that is allowed to access this region of the server. In the next section, we discuss various ways to use the Require directive.”


Topics: , ,

Posted by Michael Alfaro on May 11, 2012

Getting vsftpd user working on a Rackspace Cloud server

Thanks to Tim Carter from Pedrera on getting me this info: http://www.pedrera.com/blog/expressionengine-on-rackspace-cloud/

Other links that helped me: https://help.ubuntu.com/11.10/serverguide/ftp-server.html
http://www.howtogeek.com/howto/ubuntu/add-a-user-on-ubuntu-server/

5. Install FTP Server

I used vsftpd (https://help.ubuntu.com/10.10/serverguide/C/ftp-server.html), but you can use whatever you prefer. Be sure to follow FTP software documentation to ensure proper security!

sudo apt-get install vsftpd

6. Set the permissions on the web directory

The user created in step 1 (Rackspace Server Setup) should have their home directory set to /var/www. Use this command:

sudo usermod -d /var/www yourusername

Now set this user as the owner:

sudo chown yourusername /var/www sudo chgrp yourusername /var/www -Rv

Topics: , , ,

Posted by Michael Alfaro on May 8, 2012

Be more interesting, it’s easy!

Got this forwarded to me by Riti, thought it deserved some shine on our blog, thank you Jessica Hagy, for writing this: http://www.forbes.com/sites/jessicahagy/2011/11/30/how-to-be-interesting/

How to be interesting (in 10 stupid-simple steps):


1.Go exploring.
Explore ideas, places, and opinions. The inside of the echo chamber is where all the boring people hang out.

2. Share what you discover.
And be generous when you do. Not everybody went exploring with you. Let them live vicariously through your adventures.

3. Do something. Anything.
Dance. Talk. Build. Network. Play. Help. Create. It doesn’t matter what you do, as long as you’re doing it. Sitting around and complaining is not an acceptable form of ‘something,’ in case you were wondering.

4. Embrace your innate weirdness.
No one is normal. Everyone has quirks and insights unique to themselves. Don’t hide these things—they are what make you interesting.

5. Have a cause.
If you don’t give a damn about anything, no one will give a damn about you.

Page 2 of 2

6. Minimize the swagger.
Egos get in the way of ideas. If your arrogance is more obvious than your expertise, you are someone other people avoid.

7. Give it a shot.
Try it out. Play around with a new idea. Do something strange. If you never leave your comfort zone, you won’t grow.

8. Hop off the bandwagon.
If everyone else is doing it, you’re already late to the party.  Do your own thing, and others will hop onto the spiffy wagon you built yourself. Besides, it’s more fun to drive than it is to get pulled around.

9. Grow a pair.
Bravery is needed to have contrary opinions and to take unexpected paths. If you’re not courageous, you’re going to be hanging around the water cooler, talking about the guy who actually is.

10. Ignore the scolds.
Boring is safe, and you will be told to behave yourself. The scolds could have, would have, should have. But they didn’t. And they resent you for your adventures.


Topics: , , , ,

Posted by Michael Alfaro on May 7, 2012

How to capitalize first letters of words in MySQL

Found the need for this on our Weatherwiseapp.com site, and wanted to share. Original source here: http://joezack.com/index.php/2008/10/20/mysql-capitalize-function/

CREATE FUNCTION CAP_FIRST (input VARCHAR(255))

RETURNS VARCHAR(255)

DETERMINISTIC

BEGIN
	DECLARE len INT;
	DECLARE i INT;

	SET len   = CHAR_LENGTH(input);
	SET input = LOWER(input);
	SET i = 0;

	WHILE (i < len) DO
		IF (MID(input,i,1) = ' ' OR i = 0) THEN
			IF (i < len) THEN
				SET input = CONCAT(
					LEFT(input,i),
					UPPER(MID(input,i + 1,1)),
					RIGHT(input,len - i - 1)
				);
			END IF;
		END IF;
		SET i = i + 1;
	END WHILE;

	RETURN input;
END;

So running the following code…

SELECT	CAP_FIRST(
	'this is totally like   @ TEST 1 right!'
)

Returns the string “This Is Totally Like @ Test 1 Right!”


Topics: , ,

Posted by Pinaki Kathiari on May 4, 2012

Weatherwise featured on Gizmodo.com as app of the week

Weatherwise Featured on Gizmodo.com

Weatherwise Featured on Gizmodo.com

Last week after we were interviewed with the Google development team, Weatherwise was featured on Gizmodo.com as the app of the week.

It’s hard to make weather interesting. But this app puts the usual data into a pretty package, with handsome skins and animation.

Thank you Gizmodo, we just marked “Get mentioned on Gizmodo.com” off our life to-do list!


Topics: , ,