A B
is an masters student at NYU's Tisch Interactive Telecommunications Program (ITP). Before that, I worked in DC for nonprofits and campaigns, and had a music blog. I enjoy making pizza and pulled pork, and I'm terrible at smiling for photos. Please check out my portfolio here.

HEARHERE.ORG

I made a thing

May 24, 2011

hearhere

Yesterday I launched hearhere.org, basically a mashup between youtube and eventful. It allows you to select venues they like (with a sweet sorting animation thanks to quicksand) and then creates an audio/video playlist of the shows coming up at those venues. The playlist will continue playing, event by event, automatically, so it can easily be used in the background.

Each playlist has a unique short-url so you can share your playlist with others (currently, even playlists that are identical have different urls, which is silly, but I opted for speed here, and can fix this later).

Another mode of operation is text search, where you simply enter the search terms you'd like, and hearhere gives you a playlist of them, which is useful for festivals and other lineups.

I wrote hearhere in python, and it runs on Google App Engine, which I've enjoyed working with so far, though I hope the pricing changes don't make it too costly to run it.

 

Keep Reading This

Incomplete features I intend to add include the ability to submit and vote on videos, so the videos displayed would be better/more relevant, comments, and a closer tie in with the eventful api to allow users to declare they're attending events. 

NEURAL NET VISUALIZATION

Congress, The Military, and Unemployment

May 11, 2011

For my machine learning class I created a neural network and a visualization to show how it learns.

What is a neural network? Basically, it's a computer model inspired by the way your brain works. The simplest version only has inputs and outputs. The interesting part is the synapses between the inputs and outputs, which start with small random weights (think multipliers), and get adjusted in small increments over many "epochs" in order to cause the network's output to approach the outputs desired.

Where it gets really interesting is when you start adding more layers, besides inputs and outputs, called hidden layers. This allows the neural net to, in a sense, hold abstractions, and generalize from the training data. 

For this project, I took data from the last 70 years, and built a network with four layers, six inputs, four neurons in each of the two hidden layers, and one output. (Specifically, I built a feedforward back-propagating supervised network, which is what I'm discussing here. There are many other types of neural nets.) 

As inputs, I used the number of Democrats and Republicans in the Senate and House, the active strength of the US Military, and the unemployment rate for the previous year. As output, I used the unemployment rate for that year, as that's what I wanted to predict.

The video above shows the neural net learning, by adjusting the synapses between the neurons, which are animated in gray, and then running through the training data, and then the testing data (i.e. data that it wasn't trained on, in this case, the most recent 15 years).

In the end, my neural network was much more accurate than I expected, the error on the testing data was 11%, meaning that, in theory, if you give the network inputs for a given year (House and Senate makeup, military, last year's unemp) it will predict the unemployment rate within 11% . So if the true rate was, say, 8.3%, the network would give you something between 9.21% and 7.387%. Not too bad. (Frankel and other economist friends, feel free to chime in about the various ways this is wrong and makes no sense.) 

Keep Reading This

More details:
To do this, I used the excellent Encog library for java. I like python more than java, so messed with pybrain a lot, but Encog has every feature conceivable. And works with processing, which made visualizing easier.

Before I got to what you see in the visualization, I tried a lot of different, similar neural nets. First, I tried it without the temporal data, that is, without the last year's unemployment. This gave me a 17% error rate on the last 15 year data. Next, I tried it with a random selection of 15 years, and the error rate went down slightly. Finally, I added the extra input of last year's unemployment, and, with a ton of training (much more than in the video), achieved an 11% error rate on the test data. I also messed with a great amount of variation as far as number of neurons in the hidden layers, from 2 to 500, but 4 turned out to be best.

There were two areas in which I had trouble, one was data normalization using Encog, so I ended up normalizing the data myself using a python script I was using to aggregate the data anyway (neural nets like data to be between 0 and 1).

Second, was displaying the actual values moving through the network while it was being tested. I rewrote most of my code in attempt to add this (and learned how to use the iterable object correctly), as I think it would be really useful for understanding the way the network works, but I couldn't get the values for each layer to display correctly. With some time, I'd really like to add that.

Source code available here, though this doesn't really resemble what's in the video. Below is the console output for the most successful run of the network. Because the weights start randomly, each training is different from every other training.

 

Epoch #5447 Error:1.4999955997114394E-4 Neural Network Results for Training Data: 0.66,0.28,0.534,0.324,0.18,0.73, actual=0.4983663395292939,ideal=0.495 0.66,0.28,0.534,0.324,0.3859,0.495, actual=0.23436250492049088,ideal=0.235 0.57,0.38,0.444,0.418,0.9045,0.235, actual=0.08452120095631022,ideal=0.095 0.57,0.38,0.444,0.418,1.1451,0.095, actual=0.0815033122889647,ideal=0.06 0.57,0.38,0.486,0.38,1.2056,0.06, actual=0.08130640799774146,ideal=0.095 0.57,0.38,0.486,0.38,0.3025,0.095, actual=0.24327423747050617,ideal=0.195 0.45,0.51,0.376,0.492,0.1582,0.195, actual=0.20086019727739185,ideal=0.195 0.45,0.51,0.376,0.492,0.1445,0.195, actual=0.2008001851266592,ideal=0.19 0.54,0.42,0.526,0.342,0.1613,0.19, actual=0.27778673711288804,ideal=0.295 0.54,0.42,0.526,0.342,0.1459,0.295, actual=0.28814359093564434,ideal=0.265 0.48,0.47,0.468,0.398,0.325,0.265, actual=0.16153750109068066,ideal=0.165 0.48,0.47,0.468,0.398,0.3635,0.165, actual=0.13558489288725128,ideal=0.15 0.46,0.48,0.426,0.442,0.3555,0.15, actual=0.17602786013114474,ideal=0.145 0.46,0.48,0.426,0.442,0.3303,0.145, actual=0.2199931108910821,ideal=0.275 0.48,0.47,0.464,0.406,0.2935,0.275, actual=0.23021456016162994,ideal=0.22 0.48,0.47,0.464,0.406,0.2807,0.22, actual=0.253903192793502,ideal=0.205 0.49,0.47,0.468,0.402,0.2795,0.205, actual=0.2555298780817681,ideal=0.215 0.49,0.47,0.468,0.402,0.2599,0.215, actual=0.26123536179631845,ideal=0.34 0.64,0.34,0.566,0.306,0.2504,0.34, actual=0.27390713255535215,ideal=0.275 0.64,0.34,0.566,0.306,0.2476,0.275, actual=0.29709252965041594,ideal=0.275 0.64,0.36,0.524,0.35,0.2483,0.275, actual=0.2855653767340758,ideal=0.335 0.64,0.36,0.524,0.35,0.2808,0.335, actual=0.24978578065111492,ideal=0.275 0.67,0.33,0.516,0.352,0.27,0.275, actual=0.27536312822913894,ideal=0.285 0.67,0.33,0.516,0.352,0.2687,0.285, actual=0.2765217655180545,ideal=0.26 0.68,0.32,0.59,0.28,0.2656,0.26, actual=0.2554208345203682,ideal=0.225 0.68,0.32,0.59,0.28,0.3093,0.225, actual=0.1939832730643538,ideal=0.19 0.64,0.36,0.496,0.374,0.3375,0.19, actual=0.19772126359928496,ideal=0.19 0.64,0.36,0.496,0.374,0.3547,0.19, actual=0.16332311108949626,ideal=0.18 0.58,0.42,0.486,0.384,0.346,0.18, actual=0.16442127838161877,ideal=0.175 0.58,0.42,0.486,0.384,0.3066,0.175, actual=0.24245546463834086,ideal=0.245 0.54,0.44,0.51,0.36,0.2714,0.245, actual=0.2558851329275245,ideal=0.295 0.54,0.44,0.51,0.36,0.2324,0.295, actual=0.2954853700500669,ideal=0.28 0.56,0.42,0.484,0.384,0.2253,0.28, actual=0.2681779921075669,ideal=0.245 0.56,0.42,0.484,0.384,0.2163,0.245, actual=0.26151565006675204,ideal=0.28 0.61,0.37,0.582,0.288,0.2129,0.28, actual=0.3470994484698628,ideal=0.425 0.61,0.37,0.582,0.288,0.2081,0.425, actual=0.37127167300622715,ideal=0.385 0.61,0.38,0.584,0.286,0.2075,0.385, actual=0.3441559331912948,ideal=0.355 0.61,0.38,0.584,0.286,0.2062,0.355, actual=0.34953890305512214,ideal=0.305 0.58,0.41,0.554,0.316,0.2031,0.305, actual=0.33600392793467077,ideal=0.29 0.58,0.41,0.554,0.316,0.2063,0.29, actual=0.3332303554084988,ideal=0.355 0.46,0.53,0.484,0.384,0.2101,0.355, actual=0.38391068153643754,ideal=0.38 0.46,0.53,0.484,0.384,0.213,0.38, actual=0.4706693478188674,ideal=0.485 0.46,0.54,0.538,0.332,0.2163,0.485, actual=0.4305970376393928,ideal=0.48 0.46,0.54,0.538,0.332,0.2184,0.48, actual=0.42942131121472155,ideal=0.375 0.47,0.53,0.506,0.364,0.2207,0.375, actual=0.3791308632978942,ideal=0.36 0.47,0.53,0.506,0.364,0.2233,0.36, actual=0.3408292536305523,ideal=0.35 0.55,0.45,0.516,0.354,0.2244,0.35, actual=0.3180255945111218,ideal=0.31 0.55,0.45,0.516,0.354,0.2209,0.31, actual=0.3054461292681537,ideal=0.275 0.55,0.45,0.52,0.35,0.2203,0.275, actual=0.30308948074905867,ideal=0.265 0.55,0.45,0.52,0.35,0.2144,0.265, actual=0.3008652986844994,ideal=0.28 0.56,0.44,0.534,0.334,0.2077,0.28, actual=0.3167321964928064,ideal=0.34 0.56,0.44,0.534,0.334,0.188,0.34, actual=0.33105436361549073,ideal=0.375 0.57,0.43,0.516,0.352,0.1775,0.375, actual=0.35928649461540163,ideal=0.345 0.57,0.43,0.516,0.352,0.1678,0.345, actual=0.3048710453119955,ideal=0.305 0.48,0.52,0.408,0.46,0.1583,0.305, actual=0.2624632144627692,ideal=0.28 ------------------------------- ------------------------------- Neural Network Results for NEW DATA: 0.48,0.52,0.408,0.46,0.1538,0.28, actual=0.23930077726065127, ideal=0.27, percentage error=0.11370082496055091 0.45,0.55,0.414,0.452,0.1504,0.27, actual=0.24239373755821966, ideal=0.245, percentage error=0.010637805884817685 0.45,0.55,0.414,0.452,0.147,0.245, actual=0.22977833679284043, ideal=0.225, percentage error=0.021237052412624118 0.45,0.55,0.422,0.446,0.1451,0.225, actual=0.22768245012752356, ideal=0.21, percentage error=0.08420214346439793 0.45,0.55,0.422,0.446,0.1449,0.21, actual=0.2253461254045889, ideal=0.2, percentage error=0.12673062702294444 0.5,0.5,0.424,0.442,0.1451,0.2, actual=0.21840667496538055, ideal=0.235, percentage error=0.07060989376433804 0.5,0.5,0.424,0.442,0.1478,0.235, actual=0.22297073742023873, ideal=0.29, percentage error=0.23113538820607327 0.48,0.51,0.41,0.458,0.15,0.29, actual=0.24921051256244264, ideal=0.3, percentage error=0.16929829145852449 0.48,0.51,0.41,0.458,0.1494,0.3, actual=0.25960230146033725, ideal=0.275, percentage error=0.055991631053319176 0.44,0.55,0.404,0.462,0.1455,0.275, actual=0.24845814093718874, ideal=0.255, percentage error=0.025654349265926538 0.44,0.55,0.404,0.462,0.1456,0.255, actual=0.23292273464134336, ideal=0.23, percentage error=0.012707541918884128 0.49,0.49,0.472,0.398,0.1451,0.23, actual=0.24803874970006634, ideal=0.23, percentage error=0.07842934652202753 0.49,0.49,0.472,0.398,0.1474,0.23, actual=0.24857095999001486, ideal=0.29, percentage error=0.14285875865512113 0.58,0.4,0.514,0.356,0.1493,0.29, actual=0.26828403415745933, ideal=0.465, percentage error=0.4230450878334208 0.58,0.4,0.514,0.356,0.1506,0.465, actual=0.5537600529394734, ideal=0.48, percentage error=0.15366677695723627 Average Error for Test data 0.11466037 Hey there. End of program.

LOOKING FOR LOVE

In Washington Square Park

May 9, 2011

For my video sculpture and computational cameras class projects, Eric Hagan and I created an interactive piece using a flashlight we modified to output only IR light, a simple webcam we modified to only see IR, a projector, and a lot of processing code.

The idea came out of a video sculpture I created that allowed the audience to illuminate a section of the climatic scene from the film 'The Shining' using an old flashlight. We decided to use the a similar technique, but enhance the technical aspects, film our own footage, add layers, and add something for the audience to search for, using the beam of the flashlight.

We raided the photography department a few floors up for developed, exposed film. Unfortunately, I'm not sure what worked best, as we were raiding the trash, and none of the film remnants were labeled. I suspect it had to do with ISO and developing process, but a couple pieces we found worked perfectly, letting almost no visible light through, and almost all of the IR. 

Keep Reading This

On a nice spring day, we filmed our footage in Washington Square Park. We masked out a couple of elements, and brought it into Processing. Unlike my previous project, our IR worked so well, we were able to put the camera with the projector, facing the surface we were projecting on, which made for a very natural interaction. After experimenting with the built in blend functions for masking/creating the spotlight affect, we wrote our own, which worked very well and was surprisingly fast.

We ran into some problems trying to add our extra element, both technically and content-wise. For content, we eventually decided to have it be a heart, somewhat to break away from the 'scary video sculpture' aesthetic, and somewhat because Waldo didn't seem worth the effort. Technically, we discovered a serious bug in Processing's copy function, trying to copy a frame of an animated, transparent gif, to a frame of video (not to the screen, mind you, that would have been easy, but we had more processing of the video to do). The copy() function in processing is supposed to respect transparency, but it turns out there is a know bug that it does not. After trying a lot of hacky work arounds, we choose to simply use the blend() function, which worked, but caused a slight flicker.

But it worked. And worked well. I'd sort of like to revisit the project, and go back to building something scary. A lot of people wanted us to put a camera on the other side of the wall and do x-ray vision, and that would be fun too. 

Source code here, though for size reasons, the source video is not included. It should be easy enough to drop in your own, and add some static masks. 

(More about my original comperas final project here.)

SPHERIFICATION

Some Joke About Balls Goes Here

May 4, 2011

Spherification of Red Tea

For my Design Frontiers in Biology and Materiality class I experimented with spherification of edible liquids (and one pureed delicious solid). Given that you're on the internet, and can't taste my spheres, the next best thing is to check out the photos I took.

Spherification uses a reaction between sodium alginate and calcium to create a thin skin around the sphere. The liquid you want to create spheres out of is mixed with the alginate, and then dropped into a bath of water and calcium (I used calcium chloride). Reverse spherification uses those same chemicals, but, you guessed it, in reverse. This is necessary for liquids that contain calcium already, as they would thicken too much if mixed with the alginate.

I bought all my chemicals from lepicerie.com. If you're going to try this, definitely be sure to purchase food grade chemicals.

Liquids I made into spheres: Water, red tea, apricot nectar, apple cider vinegar, wine (pinot noire), Sriracha hot sauce, and pureed bacon. I reverse-sphered: coffee , balsamic vinaigrette, and milk. 

Keep Reading This

I used a ratio of about 1 gram of alginate per 200ml of liquid, which in retrospect was a little much. Wine, for instance, thickened a bit more than I'd have liked, so while the spheres were tasty, biting into them was a bit more like eating an alcoholic gummy bear than a caviar. The tea and apricot didn't thicken as much, and had the desired effect. Bacon failed miserably and looked disgusting. Sriracha was so thick to being with that I diluted it some, but it was still to thick to form spheres in the air, dropped out of a syringe into the calcium bath: hence Sriracha spaghetti.

After dropping them in the bath, I waited about one minute, before removing them, and rinsing them in a water bath. This last step is important, because calcium chloride does not taste good. In the future, I may experiment to take them out sooner in some cases, to get a thinner shell

For the reverse-spherification I used calcium lactate gluconate instead of the calcium chloride, with the same ratio. It worked very poorly, as you can see here. The problem with the reverse is that, instead of a thin shell, you get a very thick, clear shell. This could be avoided with an decreased alginate in the bath, but that would probably necessitate a thickener in the spheres, such as xanthan gum.

A debate seems to exist about whether or not it's necessary to blend the alginate with your liquids, or just gently mix it to avoid air bubbles, as well as how long to wait do degas your liquids. I come down firmly on the side of an immersion blender, and learned that waiting to degas isn't that important, at least in my experience. Spheres with air trapped in them looked more visually interesting than the ones I degassed by leaving them in the refrigerator overnight, and had no disernable difference in texture. 

BUDGET CLIMB

Ever wanted to climb a bar graph?

March 29, 2011

Budget climb is a project I worked on for 3D Sensing and Visualization class, that we've also entered in the datavischallenge. I worked with Fred Truman and Frankie Cheung to build a cityscape-style representation of the US federal budget from the last 26 years, broken up by type of spending.

The cool thing about our project isn't the graphics, which are fairly basic, but instead, the interaction. In order to explore the data environment, we have to physically use our arms to climb, which gives us a real sense of the scale of each type of spending. Climbing military spending, especially for the Bush years, for instance, takes a lot of physical effort.

Source code, and binary (runnable) applications (both kinect and non-kinect flavors) available at budgetclimb.com.

Update: We made it to the finals in the DataVisChallenge and won $500. Which will almost certainly be spent on Bon Chon Chicken.

 

 

PONG HEAD

March 22, 2011

For Dano's Computational Cameras class (using skills from 3DSAV class), I built a version of the game Pong, where the users control the paddles with their bodies, and the loser's head becomes the ball. 

I used a Kinect, Openframeworks, and OpenNi to track the users. The code for the game itself is super simple, with no win conditions, and the ball speed starts fairly slow (though it gets pretty dang fast). Source code is available here.

VIDEO SELF PORTRAIT

March 22, 2011

Here's my video self portrait for Video Sculpture class. It was the first time I'd edited video since high school. Turns out not all that much has changed as far as Premiere and FCP go.

ATTEMPT AT SPHERIFICATION

Oh, Balls

March 7, 2011

Sphere1

For Design Frontiers class, I tried sperification of foods.  I used Sodium Alginate, Calcium Chloride and  Calcium Lactate Gluconate, and tried both sperification and reverse-sperification, with Root, a liquour, water, tomato juice, milk, and olive oil. I was really only successfull with the water and tomato juice, probably because I failed to use purified water for my water-bath.  I'd like to try this again in a more controlled environment. More photos after the jump.

Keep Reading This

POS NIETZCHE

March 7, 2011

pos-nietzche

Based largely on Heather's code, I wrote a script to analyze Beyond Good and Evil with parts of speech tagging and visualize the results. I chose to only display the verbs and nouns, and color them differently.

YOUTUBE API ON GAE

It really shouldn't have been this hard.

March 6, 2011

I'm working on an app using google app engine, and for the most part, it's going great. As I was deploying a more serious version of it, I bragged about the 'deploy' button on the app engine launcher, which really works well.

Except that once deployed, my code stopped working, failing about 1 in 3 times.  I got a 403L response code, which I'd never seen before, but evidently means that you're over your ratelimit with the gdata api. 

<error><domain>yt:quota</domain><code>too_many_recent_calls</code></error>

Googling found that other people had this problem. There are some answers in those, and there's even a 'hello youtube' example on Google Code, specifically for using Google App Engine and the Youtube API. But none of these worked, though they did make me realize what the likely problem was: GAE wasn't passing on my developer's key even thought the documentation definitely said it should have been, so I was hitting the ratelimit, along with everyone else without a developer's key on that same server/cloud/whatever. I learned how logging works, and confirmed this. I fought with urlib, urlfetch, and a bunch of properties of gdata's query object. 

In the end, it was incredibly simple to include my key manually:

query['key'] = key

Where key, is of course, the developer's key and query is (in my case) gdata.youtube.service.YouTubeVideoQuery().