IBM i EXTRA
Blog
iCan

Categories

Rob McNelly

Rob McNelly




Bookmark and Share

Recent Comments

March 2011

Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

03/16/2011

$3 Million Healthcare Dare

Can an algorithm prevent unneeded hospital stays?

By Morgon Mae Schultz

A network of California doctors is issuing a $3 million dare asking data miners to fix healthcare. The Heritage Health Prize, which stands to be the largest-yet data-modeling competition, will challenge participants to write an algorithm identifying patients most at risk for unnecessary hospitalization—an economically draining component of U.S. healthcare woes. Ultimately, the algorithm will alert doctors to intervene before hospitalization with healthier, far cheaper preventive action.

The Problem

Hospitals are costly. Jonathan Gluck, senior executive with Heritage Provider Network, the competition’s sponsor, estimates that Americans spend between $30 billion and $40 billion annually on unnecessary hospitalizations. Unneeded admissions also put patients at risk for hospital-borne infections and divert resources from patients who really need them. More to the point, Heritage asserts, they’re symptomatic of a system that treats sickness rather than keeping people healthy.

“With all that’s going on with predictive modeling and data mining, the thought was, well, let’s see if we can kind of think outside the box and get new people involved in trying to solve these problems,” Gluck says. Some feared the algorithm will be used to avoid caring for costly patients, but Gluck stresses that Heritage is not an insurance company and, as a network of doctors, has no say in which patients it treats or doesn’t treat.

To understand why the network decided a huge data-mining prize was the best way to prevent unneeded lay-ups, Gluck says you need to know a little about its founder and CEO, Richard Merkin. Merkin is a medical doctor, philanthropist for youth and medical charities, and a core contributor to the X Prize Foundation, which runs innovation competitions in space exploration, genomics, ecology and other fields. Merkin is genuinely excited to bring new minds to the healthcare table and believes data miners hold great potential, according to Gluck. The contest was Merkin’s idea to not only yield a winning algorithm, but also to grab the attention of data miners globally and raise awareness about competitive innovation. “You could be the best company in the world and if you hired 20 really good minds to work on your problem, you’ve got 20 good minds. If you run a prize, and you’ve got 2,000 entries, I would assume you’ve got a better shot at success,” Gluck says.

Attracting Minds

The company is putting up substantial money, and serious data, to back up its hopes. The $3 million award is bigger than the Nobel Prize for medicine and the Netflix prize combined. (The former varies but has paid about $1.5 million each of the past 10 years. The latter, a famous data-mining competition, awarded $1 million.) It’s by far the biggest prize Kaggle, the data-contest administrator that will run the competition, has ever handled. The 11-month-old company accelerated a total infrastructure rebuild to accommodate it.

Competitions attract great minds based on three factors, according to Kaggle founder and CEO Anthony Goldbloom: by offering interesting, real-world data to researchers usually stuck with lackluster fictional or public data; by posing meaningful social problems; and with large prizes. And this contest, he says, ticks all boxes. “Firstly, there’s a ginormous prize up for grabs. Secondly, the data set is fantastic. And thirdly, it’s a really, really, really significant, meaningful problem,” Goldbloom says. “I mean the Netflix prize attracted something like 50,000 registrations and it was to make sure people didn’t see movies that they disliked. This is obviously far more significant.”

Goldbloom says the Heritage data set alone could attract scores of participants even if it weren’t linked to a fortune. He cites a chess-rating competition that posed what data miners considered an interesting problem. Two-hundred and fifty-eight teams competed for the top prize, a DVD signed by a chess grand master. A $25,000 prize attached to a less interesting problem attracted far fewer entries.

The Heritage set includes real patient data on perhaps hundreds of thousands of members—doctor’s visits, test results, prescriptions and whether they’ve been filled—scrubbed of identifying details by a group of health-privacy experts. Kaggle will conceal a late portion of the 2005-2010 data and challenge participants to predict hospitalizations based on the earlier portion. When entrants upload their predictions, Goldbloom says, they’ll get real-time feedback on the site’s leader board. “It’s literally like making data science a sport. These people will know in real time exactly how they’re doing.”

Kaggle will launch the contest April 4 and expects it to run for about two years.

Who Will Win?

Goldbloom and Gluck say the $3 million purse could go anywhere. In the contest to design a new chess-rating system, an IBM researcher took first place—no big surprise. But in a competition to predict viral load in HIV patients, the winner had learned to data mine by watching lectures Stanford University had posted online. “This guy just became interested in it. Started watching these Stanford lectures, and learned enough,” Goldbloom says. And the computer scientist who won Kaggle’s first contest was a 25-year-old in Slovenia. The underdog factor is so important to competitions that Kaggle helps hosts whittle down data sets as much as possible so participants with few resources can run the problems on laptops or small systems.

“There’s a lot of low-hanging fruit that I suspect things like this could help to unleash,” Goldbloom says. “For example, you identify somebody as being a really high risk of hospitalization and you get them into an exercise program or you have a nurse call them up every day to make sure they take their prescription. Well, that’s going to have a significant effect on quality of life and it doesn’t involve a $3 trillion drug trial. It’s low-tech but it can have as dramatic an impact as a new blockbuster drug.”

To participate in the contest, visit the Heritage Health Prize website.


Morgon Mae Schultz is a copy editor for MSP TechMedia


Forum Inspiration

Ideas for trimming spaces and multiple field concatenation

By Jon Paris and Susan Gantner

Sometimes trying to decide what we’re going to write about is the hardest part of the job. One source of inspiration is the Internet forums we subscribe to. If a topic seems to have interest beyond the scope of the original question, it gets added to our list. Such is the case for today’s topics, the first of which could also be titled "the many ways to skin a cat."

Trimming Spaces Within a String

The original poster was faced with the task of editing a string to replace multiple spaces within that string with a single space. When we read the question, several possibilities sprang to mind, ranging from RPG III style techniques to the latest BIFs available in V7.1.

We decided to give the various options a try and see if there were any obvious differences in performance. In the end, the options displayed very little difference, and such differences were only perceptible when the operation was repeated some 50,000 times!

One thing that did quickly become apparent though was the relative comprehensibility of the different op-tions. The examples that follow utilize these basic data definitions. The field values supplies the test data from which the excessive embedded blanks are to be removed. The field data is the main one upon which the processing will operate, and the field outData will be used by our RPG III style routine as its output field.

d values          s             40a   varying                              
d                                     inz('ABC   DEF    HI JKL   MN     X') 
                                                                         
d data            s             40a   varying                              
d char            s              1a   dim(40) based(pchar)                 
d pchar           s               *   inz(%addr(data: *Data))              
                                                                           
d outData         s             40a   varying inz                          
d spaceSet        s               n   inz(*off)                            

Note that the array char is simply a redefinition of the field data in array form. Also we’ve used varying length fields in all cases; the second part of this article will help explain why.

Let’s begin with the RPG III style solution. The basic idea is to loop through the input field copying each character in turn to the output—unless the character represents a second or subsequent space within the field. This actual control is through use of the indicator spaceSet, which is set as soon as a space has been copied to the output string and will prevent further spaces from being added until after a non-space character is detected. The only real difference between this and what we could have actually done in RPG III is the use of a pointer and varying length fields and their characteristics.

  data = %TrimR(values);            
  outData = '';           // Set output to null (i.e. No data)         
                            
  for i = 1 to %len(data);         
    if (char(i) <> *blank); 
      outdata += char(i); // Add all non-blank characters to output  
      spaceSet = *Off;    //   and clear the space output flag  
    else;                   
      if not spaceSet;    // If no space has already been output ...  
        spaceSet = *On;        
        outdata += char(i); // Add the space to output 
      endIf;                
    endIf;                  
  endFor;                   

Our second approach involves a combination of the %Scan and %Replace BIFs. The idea is that %Scan will identify the first character position of a pair of spaces and %Replace replaces that pair with a single space. The logic keeps looping until all double space instances have been replaced. One of the things that’s immediately apparent in looking at this version is how much more obvious its operation is. In the previous version, it’s not exactly obvious what’s going on. Clearly you can see that something is stepping through a loop and that individual characters are being copied, but beyond that you must either study the code in detail or rely on the comments. With this %Scan and %Replace combination, the intent is much more obvious. Here’s the code:

  data = %TrimR(values);                      
  i = %scan('  ': data);              
  dow i <> 0;                         
    data = %replace(' ': data: i: 2); 
    i = %scan('  ': data);            
  enddo;                              

It’d be even more obvious if we used constants such as doubleSpace and singleSpace rather than literals.

For the third version, we decided to go one step further and investigate whether using the latest RPG BIF %ScanRpl could make the operation even faster and more obvious. "Faster" because it can perform multiple replacements within a single iteration. "Obvious" because the name clearly spells out exactly what’s going to happen.

It did, in fact, prove to be the fastest of the three options, but not by much. We think you’ll have to agree that the logic here is also a little more obvious in that the loop is directly conditioned on whether there are any double blanks left in the field. We also don’t need to know the exact position of the pair of spaces, as we did in the previous version, so we don’t need to store it. This alone probably accounts for some portion of the difference in speed between the two versions.

 data = %TrimR(values);
 dow %scan('  ': data) <> 0;         
   data = %ScanRpl('  ': ' ': data); 
 enddo;                                                       

You might be tempted to think that since the data is being put back in the same field, that %ScanRpl would actually be able to get rid of all of the double blanks in a single pass. But this isn’t the case as adding a simple display statement into the loop would demonstrate. The operation effectively takes place on a copy of the original data and not in-situ. It’s probably easiest to see what actually happens if we look at it step-by-step.

Note that in showing the test data below we have replaced spaces with a period "." to make the action a little more obvious. Here’s the original data:

ABC...DEF....HI.JKL...MN.....X

The first time through the loop results in a significant shortening of the field as many of the doubles will be replaced with single spaces.

ABC..DEF..HI.JKL..MN...X

The second time through further reduces the number of doubles.

ABC.DEF.HI.JKL.MN..X

And with the third iteration, we’re finally there.

ABC.DEF.HI.JKL.MN.X

So was which was the fastest version? If you said %ScanRpl, you’re correct. What might surprise you, however, is that the old-style RPG III version came in second place with the combination of %Scan and %Replace bringing up the rear. Of course, the speed difference is trivial and this is a classic example of where we’d go with the more obvious code (Scan/Replace) every time even if the performance difference were far greater. As it happens, in this instance, the fastest-running version is also the most obvious and self documenting—so we get the best of both worlds!

Multiple Field Concatenation

Our second example concerns the need to concatenate together a few fields, with or without a space or other character between them. How would you do it?

If your answer involves the use of the CAT operation code, where have you been for the last few years? There are far easier and more efficient ways to accomplish the task, but sometimes we go on autopilot and just do things the way we did decades ago.

Many of you are probably patting yourselves on the back now right because you wouldn’t have used CAT but would have used EVAL and + such as in the following example:

     D Result          S           1000a 

       Result = %TrimR(Field1) + ',' + %TrimR(Field2) + ',' +
                %TrimR(Field3) + ',' + %TrimR(Field4) + ',' +
                %TrimR(Field5);

But what if you couldn’t pull all of the fields together in a single statement—perhaps there’s a variable number of them or you need logic in between to determine which fields to use. In that case, you may consider something like this:

       Result = Field(1);
       i = 2;

       DoU i > %Elem(Field) or Field(i) = *Blanks;
          Result = %TrimR(Result) + ',' + Field(i);
          i += 1;
       EndDo;

Not bad, but you could do even better! With the preceding logic, on each iteration through the loop, the program must first trim off all the trailing spaces in the long field, concatenate the comma and the trimmed value and then pad the longer result field back with blanks—just so that it can turn around and trim off all those trailing blanks from the result field again on the next iteration!

If you make one small change to the definition of your result field, you can make the code dramatically more efficient. Simply define the result field as a variable length field. Then it will never need to pad to its maximum length; the result field simply gets longer with each iteration. It’d look something like this:

     D Result          S           1000    Varying 

       Result = %TrimR(Field(1));
       i = 2;

       DoU i > %Elem(Field) or Field(i) = *Blanks ;
          Result = Result + ',' + %TrimR(Field(i));
          i += 1;
       EndDo;

Now, the only trimming to be done on each iteration is the trim of the small number of blanks from the end of the field being added to the string. This results in far more efficient logic. In fact, in tests we’ve seen huge speed boosts from this simple change.

There are many more good ways to utilize variable-length fields. In fact, we’d go as far as saying that using varying-length fields should be your first choice. You can read more in “The Versatility of Variable-Length Fields.’


Jon Paris is a technical editor with IBM Systems Magazine and co-owner of Partner400.

Susan Gantner is a technical editor with
IBM Systems Magazine and co-owner of Partner400.


03/09/2011

Building Even More Dynamic Code

JavaScript eval lets us put RPG to use

By Aaron Bartell

There I was, minding my own business, when an idea hit me square between the eyes. I remembered that JavaScript had a special function named "eval" that allows you to dynamically invoke JavaScript statements at runtime. Why is this important and incredibly cool? Because it will help us move even more processing to the server and into RPG and out of the browser.

Let me explain. If we wanted to update an ExtJS text field, we’d usually do it with the following syntax:

Ext.getCmp('tfName').setValue('some new value')

In previous articles, we’ve taken this a step further by passing a JSON array with name-value-pairs declaring which components should have their values set (i.e., 'fldName': 'fldValue'). That was all fine, but I found I frequently needed to add new features and functionalities in both the client JavaScript and on the RPG server side of things. That’s when I realized we could eliminate changing the JavaScript side altogether by using the eval() function. Here’s how you’d accomplish the aforementioned setValue using eval:

eval("Ext.getCmp('tfName').setValue('some new value')");

Basically, all I’m doing is passing a string surrounded by double quotes into eval. Under the covers, eval will "compile" this code and immediately execute it. In theory, this means that ANYTHING we’re currently typing into our HTML document manually could be dynamically delivered from our RPG program to the client and executed.

Taking User Notifications Further

The idea came to me as I was looking for a friendly way to relay messages back to the user. My traditional approach was to use a small horizontal area at the top of the page to relay a message. Instead, I wanted something that had more eye appeal and features (i.e., a pop-up with rounded corners and would transition into and out of the page). After searching a bit in the Sencha.com forums I found an open-source ExtJS user extension named AlertBox. After playing around with the syntax of AlertBox, I was able to determine what would be necessary to make it work in conjunction with the JavaScript eval function so I could send a new AlertBox object from my RPG program to be dynamically displayed to the user. Because it used a lot of string concatenation, I created a separate service program named EXTJS with easy-to-call subprocedures to take care of all the dirty work, as shown in Figure 1. If you scroll down to the ExtJS_AlertBox subprocedure, you can see that I created parameters for the various configurable options the AlertBox allows. Note that a JSON pointer is passed in as the first parameter. This is necessary so we can subsequently add the JavaScript string to the global JSON response that will eventually be sent back to the client. You’ll notice that we aren’t actually invoking the json_* subprocedures here but instead are calling a more generic ExtJS_eval subprocedure to handle the process. ExtJS_eval was created to save on code duplication that other subprocedures in the same EXTJS service program, such as ExtJS_cmpShow, ExtJS_cmpHide and ExtJS_setValue, could also use.

Implementing the EXTJS Service Program

The next step is to implement those ExtJS_* RPG subprocedures into an actual program so we can see how they replace the traditional "uiactn" subprocedure approach I’ve taken in previous articles. For this purpose I’ve created RPG program EXTJSEVAL, as shown in Figure 2, that conveys both the use of ExtJS_* subprocedures and the previous approach that’s now commented out so you can use it for reference. For example, in subprocedure btnNxtPnl1 we see that extjs_cmpHide() has replaced the call to uiActn(). Also, in subprocedure btnNxtPnl2, you’ll see that extjs_cmpSetValue() replaced all of the various json_put* subprocedures. And lastly, you see btnStayPnl3 is still occupying gMsgTxt with an error message, and in subroutine endpgm we make a call to extjs_alertBox() instead of calling json_putString to send gMsgTxt back down to the user. That’s how the server side code changed with this new dynamic JavaScript eval approach. Let’s see how the client code changes.

Changing how we Process the Server Response

In Figure 3 we see the extjseval.html file, which contains all of the panel definitions we’re used to seeing. What’s different this time around can be found in the btnHandler JavaScript function toward the bottom of the source. The success config option of the Ext.Ajax.request object has our traditional call to JavaScript function uiActn() commented out and in its place is an Ext.iterate invocation that will loop through the JSON response and look for the evalList so it can process each subsequent eval name-value-pair. Figure 4 shows a screenshot of what the JSON response looks like when viewed in FireBug, along with the results of calling the window.console() API from within our JavaScript 'for' loop. I added the call to window.console() so you can see the exact command that’s being sent from the server and processed on the client. The key line of code in all of this is:

eval( uiCmpNam[uiActn] );

That will invoke the JavaScript statement as we saw earlier in this article where I had a hardcoded example.

That concludes the client-side coding. If you’re like me, your mind is swimming with other possibilities that could be accomplished with this newfound dynamic JavaScript statement processing. Let me share what I’m thinking. Imagine if we were to store the definition of an Ext.Panel in a DB2 table and instead of having any HTML files, we’d instead immediately invoke an RPG program. If that RPG program didn’t receive inbound parameters, it’d by default send back an Ext.Panel definition to be dynamically displayed in the browser. It’d be similar to doing something like this:

eval("new Ext.Panel({id:'pnlMain',..." );

Then when the user clicked a button in that panel, it’d communicate with the server again and we could send down another screen definition or some other actions to highlight a field that might have invalid data.

You Matter

Please continue to send me your ideas for future articles. I got an e-mail from an individual needing to create a dashboard with charts for mobile devices so they could prove to their C-level executives that RPG was still a major player in the modernization strategy. Stay tuned for an article on that as soon as SenchaTouch releases support for charts!


Aaron Bartell is an RPG and Java developer for www.krengeltech.com. Aaron can be reached at [email protected].


Figure 4


[back to article]

Are You Up to the Test?

Exploring best practices of testing

By Michael Ryan

We all do testing. We write (or update) new programs and test for the errors we anticipate. Then we compile the program, put it into production, and lean back and wait for the harried helpdesk person to knock on our cube wall with a user with a problem. Perhaps there’s a better way.

Testing is a broad topic. Too often IBM i programmers (and systems people who write code, especially CL) have too narrow of a focus when it comes to testing. Now, a narrow focus when applied to attention to detail is a good thing, but we need to broaden our horizons with testing. We tend to focus on the code that we write, the errors that we anticipate and the exceptions that we plan to handle. And I believe we do a very good job with that technique.

By the way, I make a distinction between errors and exceptions. An exception is a change to the normal flow of a process, but it’s something that we expect. Reaching end of file when reading a file would be an example of an exception. An error is also a change to the flow of a process, but it’s a change that’s unexpected or abnormal, and can cause problems when it occurs. A decimal data error or dividing by zero would be examples.

However, those of us who’ve been around the block for a while realize it’s not the errors that we anticipate that will cause problems; it’s the errors that we don’t anticipate. Doesn’t that sound counterintuitive? How can we handle something that we don’t anticipate? Is that like proving a negative or something? Rest assured that the solution is simple…it’s called a testing procedure.

The Testing Procedure

The testing procedure consists of three major steps: setup, process and assessment. We’ll look at each step, but here’s an overview of the steps and their components:

  1. Test Plan Setup
    • Design test
      • Test script
    • Validate test
      • Expected results
  2. Testing Process
    • Establish test data (ETL)
    • Conduct test
      • Unit tests
      • System tests
      • Repeatability
    • Regression testing
  3. Assess results
    • Compare actual to expected
    • Feedback to development/testing
    • Reset test data

Test Plan Setup

The first section, Test Plan Setup, is how we plan and design our testing. Rather than just concentrating on the errors and exceptions that we anticipate, we will create a test plan that will test the operation of our program (or application or system, depending on the scope of the testing). This will test the parts we expect to work as well as the parts where we expect a problem to happen.

The first step of the setup is to design the test. This is where we combine our knowledge of the program and our knowledge of the way it will be used. This enables us to create a listing of the step-by-step actions we need to take to fully test our program. The script would include instructions for the normal case (e.g., “Enter an order number,” “Press Enter to verify the order,” “Press F16 to submit the order for processing,” etc.). The script should also include instructions for error handling (e.g., “Press Enter with a blank order number,” “Attempt to submit an order with no vendor number,” etc.).

The second step of the test plan setup is to validate our test. Just as we create the actions to test our program, we also need to identify the expected results from those actions. For instance, if we process an order, we should expect that that order will appear in the list of open orders. If it doesn’t, we have a problem. We would need to provide feedback to the developer (or the lead tester) that a problem has been encountered.

Testing Process

A critical part of the testing process is the data with which we test. We need verifiable, accurate data for proper test results. In other words, if we don’t know the data to be accessed and manipulated, how will we know if our program is operating correctly? Establishing the test data is the foundation on which our testing is conducted. The technique of extract, transform and load (ETL) is how we establish the test data. We often use production data for testing, but we probably don’t need the entire production data set—just the appropriate data for our testing. This brings up an important point regarding test data—if you use an extract of production data for your testing, you need to use the same safeguards and security for that test data as you do for your production data. Confidential customer information must be protected even if it’s being used for testing.

The ETL process consists of extracting data from our production system, transforming the data to meet our testing needs (perhaps changing an identifier such as company number), and then loading the data into our test system. The test system may be a different LPAR, a physically separate system or a system composed of different libraries. Of course, the important consideration is to keep our production system and our test system separated. Nothing quite like the feeling you get when you realize you just set the status of all the open orders on a system to cancelled.

Conducting the test gets to the actual heart of the matter. Two types of tests are usually needed—unit tests and system tests. Unit tests are where we test the individual unit of code that we’ve changed. That unit of code could be a program or a procedure. I find that testing the smallest unit of code possible will yield the best results. It’s much more difficult to test a 25,000-line program for the change I made than it is to test a 50-line procedure. But while that has more to do with your program design philosophy, I think it points to the value of modular code. The system test is usually more involved, and may not be needed for all changes (though I think it should at least be considered for most testing). The system test is used to ensure correct operation and to identify any potential problems with other (usually downstream) processes. For instance, if I make a change to the order-entry program, I should also test the programs that print the list of open orders.

We want (and need) our testing to be repeatable. If we have a test script, and we have the same data, then every time we run the script against that data we should have the same results. This seems trivial, but it’s important. Results that aren’t repeatable show some type of inaccuracy; the data isn’t the same, the testing isn’t the same or the program hasn’t been changed correctly. You can easily determine if the testing is repeatable by simply running the same tests and getting the same results.

Regression testing is a type of unit and system testing. The idea behind regression testing is that fixing a problem, adding new functionality or making an enhancement to a program can introduce new problems. Sometimes a problem that was previously fixed will reoccur because the source code used to make the change was out-of-date. Sometimes fixing one problem can introduce other problems that weren’t even considered. Keeping test scripts around can be very helpful in regression testing. Re-running tests scripts can point out new problems or errors.

Assess Results

The object of the test procedure is to gather result data from testing. This result data must be compared to something to validate our test results. We need to compare the actual testing results to the expected testing results. This includes the normal case where we test to ensure our change is working as designed. It will also include any anomalies—inaccurate results, other issues observed and of course the dreaded program crash.

Once we’ve gathered the results and compared the actual to the expected, we need to provide feedback to the appropriate party. This could be the developer or the person in charge of testing. Remember to phrase the feedback in constructive terms: “Your code is abysmal and fails the simplest test” may be accurate, but doesn’t lead to good feelings at the next departmental birthday party. You may be the developer who receives the feedback. Look at the feedback from the standpoint of the tester. You may also be both the developer and the tester. I like to document the test results as a way of monitoring or gauging my progress.

Another task can be resetting the test data. This is usually an automated process where you can reset to the beginning test case data. This is important for testing and for test repeatability.

There Will be a Test

Testing should be an integral part of your development effort. While we’re all good at what do, we need to test to ensure our changes are effective and accurate. Testing is part of the overall system-development effort, and an important consideration.

It’s Your Turn. What is your testing strategy? Do you have testers who test developer’s changes? Do you have developers test their own changes?

Do you use any automated testing tools? I haven’t used them, but I can see where they could be very valuable. I’d appreciate information about tools such as these.

Do you have that “special” tester who can break anything? I can recall working with people who were great at finding problems. There’s probably a personality quirk in there somewhere, but the ability to find the bugs in someone else’s code is valuable.

Let’s Share

Like the last article about standards, let’s continue this discussion in a specially created Buzz blog you’ll find on the ibmsystemsmag.com website. Let’s continue our grassroots effort to share our knowledge and increase the professionalism of our community.

02/15/2011

Empathetic Circuits

A Cambridge team’s computers sense emotions

By Morgon Mae Schultz

As computers become more efficient and powerful, technology permeates into areas of life that may seem unlikely beneficiaries of small, fast processors—like human emotion. At the University of Cambridge computer laboratory, a team of researchers is addressing what it calls the necessity that computers become socially and emotionally intelligent, developing computers that can sense and react to user’s emotions. Possible applications range from improved automobile dashboards to aids for those unable to interpret emotional cues due to autism. The Cambridge lab’s graphics and interaction team, led by Professor Peter Robinson, has tested systems that can infer a user’s emotional state from facial expressions, gestures and voice as accurately as the top 6 percent of humans.

Reading Minds

The ability to discern what another person is feeling, known in psychology as mind reading, crosses cultural boundaries. Scientists agree on the facial expressions that reveal six basic human emotions (happy, sad, angry, afraid, disgusted and surprised) as well as hundreds of subtler mental states (such as tiredness, joy or uncertainty). Robinson’s team uses probabilistic machine learning to train computers that recognizing visual cues such as head tilt, mouth pucker and eyebrow raise. Such a system could inform a car when its driver is bothered, upset, bored or drowsy.

The team has applied the same mind-reading capabilities to an “emotional hearing aid,” a portable device designed to translate facial expressions into emotions and suggest appropriate reactions so people on the autism spectrum can relate to those around them. MIT is pursuing emotional-social prostheses, and Robinson says his team continues to research interventions for autism-spectrum conditions.

The inference system is as accurate as most people—70 percent. “There is potential for improvement. In some sense computers already are better than individual people, but there will always be difficulties establishing the ground truth in a subjective assessment,” Robinson says.

On a larger physical scale but more intimately customized, a gesture-reading system lets users control music through emotional body postures, creating an interactive, real-time soundtrack. Because emotional expression in gestures varies widely among individuals, it’s harder for machines to read whole-body cues than facial expressions. The system must tune itself to each new user and, just like humans, it reads large, dramatic movements more easily than subtle everyday gestures.

A Robot Named Charles

Not content with computers being able to recognize our mental states, Robinson’s team is working on machines that can synthesize emotion—express feelings in a way that triggers humans’ natural understanding. The complexities of human-human interaction present huge challenges to designing an appropriate human-robot interaction. One pioneer is Charles, an animated android head that Hanson Robotics built for the Cambridge team. Aiming for more satisfying robot experience, Charles has a plastic face (modeled after its mathematician namesake Charles Babbage) that can smile, grimace, raise its eyebrows and otherwise express a range of emotions.

Robinson says his team is always seeking commercial channels that could bring its technologies to consumers, including a major car manufacturer that may implement the emotional-inference system. “We are always talking to companies about the possibilities for commercial exploitation. I guess that something will appear when they see a good business case.”

You can see people interacting with Cambridge mind-reading machines here.

This video contains footage of Charles.


Morgon Mae Schultz is a copy editor for MSP TechMedia.

test

test