Sunday, June 5, 2011

The Balancing Act

In http://sightsplanner.blogspot.com/2011/05/rating-tours.html we discussed the method of rating the output of heuristic search so that the tours with individually highest-ranked items would be preferred. Having a reliable rating method is the basis of guiding the search and selecting the best from the candidate solutions.

One method of differentiating the tourist attractions in Sightsplanner database is their popularity property - a number that describes the relative activity of tourist visits to the attraction. The most active site currently has 2500 daily visits, while some obscure sites may go as low as 1. A typical museum might have 100 visits. The popularity property is aggregated into the final item score, so that with two otherwise identical items, the one with a higher popularity property will receive a higher score.

Although the ability to differentiate between similar-looking (to the machine) churches or museums is highly useful for enhancing the user experience, it also introduces side effects. In a historically attractive town like Tallinn, historic sites like medieval architecture are far more popular among tourists than sports and outdoor activities - in other words, items in some categories will tend have a higher score on the average than other categories.

From the statistics taken from Sightsplanner database of 835 tourist attractions, dated 01.03.2011, the average values of popularity property were the following (click on the image to see the graph in it's full glory):



The categories represent the seven sliders from Sightsplanner homepage. Even though these averages don't provide us with the exact statistical distribution, it would not be unusual if a large number of architecture-related items had higher popularity than the best sports-related item in the database.

So imagine we pushed both the "Architecture & City" and "Sports & Outdoor" sliders to the maximum, leaving the remaining ones at the minimum value, then ask Sightsplanner to give us a recommendation. Both categories of items should match to our preferences with similar level of confidence, but after adjusting for popularity, the top-ranked items would be mainly, or even exclusively, architecture-related. Applying the methods described in the "Rating the tours" article, the recommender would then accordingly attempt to produce tours that consist of architecture objects. Did this meet with the user's expectations?

To answer that question, we will take a step back and have a look at the input of the preferences from the recommender homepage.

1. Interpretation of sliders

Events: 0
Architecture & City: 1.0
Museums & Arts: 0.5
Eating out: 0

In this sample of sliders, 0 marks the leftmost position, indicating that there is no interest in that category. The rightmost position translates to the value 1 and the positions in between to fractional values.

In order for the recommender software to produce output that matches the user's preferences, we must, as the first step, unambiguously define what this configuration of sliders means. There are two plausible interpretations:

Interpretation 1: I would like to spend 66% of my time seeing architecture and 33% of my time visiting museums
Interpretation 2: I like architecture twice as much as museums (and hate the rest). Thus architecture sites on the average have a match score of S, museums have S/2 and the rest have 0.

If we could pick one of these as the optimization criteria and ignore the other we would have a straightforward way of searching for the maximal solution. As we saw, introducing the generally useful notion of popularity as an item score component produced the effect where one category could occupy all of the top spots in the item rankings - so using the first interpretation would help to ensure that the categories receive fair representation. The choice of time as the method of determining shares is arbitrary, but seems better suited than counting the items. On the other hand, the second interpretation remains one of the main design concepts of Sightsplanner and cannot be discarded either - in other words, we need to accommodate both interpretations.

The goals of the recommendation have then become:
- I would like each attraction in my tour to be as high-rated as possible
- I would like each category that I've expressed interest in, receive a fair share in the tour

2. Tackling the categories

The individual item ratings as an optimization criteria is already addressed by our tour ranking method. The redefinition of goals has upgraded our problem classification into the field of multiple-criteria optimization - we should now also observe whether all the categories present in the user profile are present in the candidate solutions and favor those where the proportions of categories by time are similar to what was indicated in the profile. We shall call this new criteria the balance criteria, as it represent the balance between categories.

There are two general methods of doing multiple-criteria recommendation - one is aggregating all the criteria into a single value and optimizing for that. The other is to treat the criteria separately, using a specially-designed search algorithm that produces a set of Pareto-optimal solutions. This set is then presented to the user.

In the current concept of Sightsplanner the recommender is expected to return a single optimal solution. For that purpose, computing the Pareto set does not appear to add much value, as automatically picking a single solution from the set would still require computing a single aggregate score for each of the set members.

Now that we know we need to arrive at a single rating value that would describe both the average individual item score, as well as the balance of categories. The formula we start with is:

m = sum(m_i) / (n + t_u / t_min)

(m_i is the individual item score, n is the number of items and t_u is the unused time. Also the notation of t_avg has been dropped in favor of t_min, the minimal visit time of a recommended item).

Observe that the score formula already contains the notion of "unused" time. This is a construct we can exploit further. Consider our target time shares of 33% museums and 66% architecture from the sliders example - if the items in the candidate solution indeed make up these proportions, we can call the time spent on this tour "well-utilized". If, on the other hand, the items would constitute of 80% architecture and 20% museums, we have an extra 14% of architecture that was not needed. In this case 86% of the time was well utilized.

This fits rather well into our score formula. Instead of looking at the average score of all the items, we only consider those items that contribute to filling the expected category time shares. The rest of the items are discarded, so that the search is no longer rewarded for piling items from a single top-ranking category. The time that was left over from filling the category shares is added to the otherwise unused time.

The new, Utilized Time Model formula:

m = sum(m*_i) / (n* + (t - t*) / t_min)

Where m*_i denotes the individual item score of all the contributing items, n* is the number of contributing items and t* is the the "well utilized" time. When there are more items in a category than required to fill it, the items are prioritized by their individual score - the higher-scoring ones are included first. The items are treated as discrete, so in case there is an item without which a category would remain unfilled, but adding it "overflows" the category, we allow the item to contribute to the score if more than half of it's visit time is useful.

3. Avoiding overdoing it

Sightsplanner computes the expected time shares of categories in minutes, so that a 100% share would be equal to the duration of the entire tour. This approach was chosen, because it makes the GRASP search inside the planner easier to guide - until the entire tour is filled with items, some categories will remain unfilled and the heuristic can prioritize the items appropriately while inserting them one by one.

If, on the other hand, we looked at the proportions items currently in the half-finished solutions, we might think that after inserting a single museum into the solution, we have 100% museums, meaning that we have grossly overfilled our 33% expectation. This can confuse the heuristic and produce anomalies(an item that is actually needed may get a weak heuristic score because it incorrectly appears to be overfilling a category).

When using time quotas, meeting the balance criteria exactly is likely to be too demanding. Even if the planner gets the item proportions right, travel time between different attractions makes it impossible to fill the quotas given in minutes. This can be compensated for by reducing the quotas by some predetermined amount - in other words, relaxing the balance criteria.

More importantly, though, it is likely that the recommended items won't fit neatly, leaving categories under- and overfilled. Let's look at a different configuration of sliders:

Events: 0.2
Architecture & City: 1.0
Museums & Arts: 0.2
Eating out: 0.2

Value of 0.2 would be a slider that is moved 1/5th from it's leftmost, "uninterested" position. Let's assume that the duration of the tour is long enough so that our Utilized Time Model formula properly rewards the planner for including items from "small" categories. The shares are so small however that they consistently get overfilled even by a single item. Together, these extra minutes assigned to events, museums and eating out take a large portion of time away from the architecture category. It again comes down to interpreting user expectations, but it is not unreasonable to assume that for a tour of short duration, items of low priority would be excluded, instead of including them at the expense of a high priority category.

To address this, we take a slightly different approach to relaxing the balance criteria. The quotas will be lowered more if the sliders are towards the "uninterested" position and less if they are towards the "interested" position. This creates some buffer time to travel between recommended attractions, as mentioned earlier, but mostly at the expense of categories that the user is less interested in.

We will omit the actual time quota table from Sightsplanner for brevity and just look at how our sliders example would be affected. A slider position of 0.2 is assigned a ratio of 0.5 and the slider with a position of 1.0 has a ratio of 1.0. Assuming that the tour length is 3 hours, we get the following time quotas:

Events: 180 minutes * (0.2/1.6) * 0.5 = 11 minutes
Architecture & City: 180 minutes * (1.0/1.6) * 1.0 = 113 minutes
Museums & Arts: 11 minutes
Eating out: 11 minutes

So everything except the architecture will be fairly insignificant and the planner won't be rewarded for recommending items in these categories, unless they have very short visit times (following the rule that at least half of the item's time should contribute to something for it's score to count, it needs to be under 22 minutes in this case).

4. Other considerations

Our scoring model allows one more simple method of refining the calculation - so far we've exploited the utilized and unused time constructs, the other major component is the individual item scores that contribute towards the average. These could be modified to encourage or discourage specific behavior of the planner. Let's look at an application for modifying the individual item scores.

Links are the part of the tour that fall between two waypoints (recommended items). Sometimes there is a remotely located, but very interesting attraction that would contribute a significant amount to the overall score. It is possible that the high score outweighs the disadvantage of having to expend a large amount of time to get there, as it's possible that all the alternative attractions are simply so much worse. In such case, a recommendation where the user has to, for example, walk 60 minutes from one attraction to another, is possible.

However, this would not be the case if the remote attraction's score would be lowered exactly due to it's remoteness. This is fairly simple to implement: if the link leading to an item is longer than some specified amount of time, the item score is lowered. The planner is no longer rewarded for including it and might have to look closer. Note that the penalty is specific to that particular link, so the item might still be a healthy choice if we later end up somewhere closer to it.

Specifically, the operator of the recommender can set soft and hard tolerance limits (such as 30 min, 60 min) for the link length - we'll start lowering the item score once the link reaches the soft limit, it should reach the minimum at the hard limit. The item score is then:

m*_i = \epsilon + (t_hard - l_i) (m_i - \epsilon) / (t_hard - t_soft)

\epsilon is some small score greater than 0 that makes this item more useful than not visiting anything at all; l_i denotes link length and m_i is the unmodified score.

Monday, May 9, 2011

Rating the tours

Sightsplanner is built around the premise that we have an idea what the user is interested in and are able to rank individual items - more specifically, tourist attractions - from our database according to that. Once we obtain such rankings, we have learned what the best-matching attractions are and putting the tour together should be a cakewalk.

Let's give it a try. Say we have 3 hours and our interest-matching calculation has provided these items from Tallinn city center:
(1) Oleviste church steeple (1.0), visit time 30 min
(2) Niguliste church (0.8), visit time 60 min
(3) Olde Hansa restaurant (0.7), visit time 100 min
(4) Viru shopping center (0.3), visit time 60 min

The numbers (like 1.0) are match scores, meaning that the Oleviste steeple appears to be best matched to the user's interests and besides churches, the user also has interest in dining and shopping.

It is evident that not all of these items may be visited, as the total time would exceed 4 hours, while we only have 3 at our disposal. So we need to take some items and discard the others, making sure we get the most out of our available time - a combinatorial optimization problem.

There are many techniques to solve this class of problems but there is usually one thing in common - we need to compare one candidate solution to another to find out which one is the best (at least, of those we have examined so far), so a numerical value is assigned to each - a metric or criteria.

1. The obvious approach

So what happens if we just add the individual item ratings together? Indeed this looks like a natural way of giving an overall rating to the tour. If we visit better attractions, the sum of ratings must increase and also, this should favor the solutions where the items are packed into the available time as efficiently as possible.

m = sum(m_i)

Where m_i is an item included in the candidate solution.

Looking at our example, the combination of (1), (2) and (4) appears to have the highest m = 1.0 + 0.8 + 0.3 = 2.1 - every time we try to include (3), only one other item fits which gives us a maximum m = 0.7 + 1.0 = 1.7 for solutions including Olde Hansa.

Incidentally, if we use this scoring method, we have modeled our tour-building task as equivalent to what is called the "0-1 knapsack" problem in the literature. The knapsack in the name refers to the anecdotal description of the problem where a thief has a limited size knapsack and tries to fill it with most valuable items possible, while each item also has an amount of space it takes up. The "0-1" part comes from the more formal mathematical description and means that each item may either be taken or not taken (but you're not allowed to cut them up).

At this point we may congratulate ourselves on a job well done and start programming our elegant little scoring model into our recommender. The user, on the other hand, may be left wondering why the program sent him/her shopping while dining had a higher priority. Turns out that this approach has a natural bias for items that have short visit time, as it is possible to fit more of those into the available time - and this bias isn't quite intuitive and acceptable to the user, leading to unsatisfactory user experience.

In our first example, the situation was somewhat ambiguous, as we had two possible categories of items to choose from and given the limited time, we picked the less time-consuming alternative, while the discarded item wasn't even the highest-scoring one. However, this bias can degrade the quality of recommended tours much more severely. Let's look at three museums:

(A) 100min score 1.0
(B) 30min score 0.6
(C) 30 min score 0.6

If we have 100 minutes to use, including (A) would limit us to a maximum score of 1.0. Picking (B) and (C) instead, we increase the minimum score to 1.2 and have 40 minutes to fill with more items! So, we have a high-scoring item (A) that the user will never see in recommended tours. In reality, people are visiting that attraction however, furthermore it is so interesting that they are spending a lot more time on the average there - so our recommender must have failed somehow.

Here one might argue that it's possible to differentiate scores more, so that weaker items are discarded anyway. However this approach is somewhat artificial and does not remove bias for shorter visit time among "equal" items. Also, we would like the tour-building phase of the recommendation to work somewhat independently of the calculation of individual item rankings.

2. Compensating for time creates a different kind of bias

Another intuitive approach to rating the tours might be saying, "I would like to spend each minute of the tour at as high-scoring attractions as possible". From the user experience point of view, this statement looks promising. So, let's see how we can achieve this. If we spend 30 minutes at an item with a score of 1.0 and 60 minutes at an item with a score of 0.4, we could say that on the average, we spent each minute at a 0.6-rated item. So, calculating the overall rating for the candidate solution is again quite simple:

m = sum(m_i * t_i) / t

Where t_i is the visit time of the attraction and t is the total time. Within the calculation of one recommendation, t can actually be dropped, as we always have the same amount of time available for the tour.

Revisiting our museum example, after compensating for the visit times like this, we get:

(A) 1.0* 100min = 100
(B,C) 0.6* 30min = 18

So, we have remedied the earlier flaw and one good item is now superior to 3..4 mediocre ones when calculating the total score. When using this new formula to rate the solutions to our first example, we get that our earlier winner (1),(2) and (4) scores m = 1.0*30 + 0.8*60 + 0.3*60 = 96. Instead, picking (2) and (3) gives m = 0.8*60 + 0.7*100 = 118 - a new best solution. This suggests that there is no more bias against the long visit time; while we have lost the individually highest scoring item, considering the very limited combinations available in the example this does not necessarily indicate a flaw of the scoring model - if there was twin item (1a) with the same properties as (1), those two could be inserted to replace (2) and the overall score would increase.

Yet there is a problem with this calculation method also and to understand why, we need to include the search algorithm that actually builds the candidate solutions. In a real-world application, having just 4 matching items is unlikely and would even defeat the purpose of automated recommendation - more likely we would get 40 or 400 matches to the particular user's profile. When that happens, we no longer have computing resources to try out all the possible combinations and need to rely on approximations of what might be the best solution.

Enter the heuristic search. If we look at a state-of-the-art meta-heuristic like GRASP (Sightsplanner also uses a derivative version of it), it has some characteristics of a simple greedy search in that it tends to pick higher-scoring items first - the idea, of course, being that this guides us to a best solution faster.

In the above museum example this would be quite fine, as (A) is likely to be picked first and as long as the search runs, we could try combinations that include (A) and something else. However, the scores may be distributed the other way:

(D) 0.5 * 100min = 50
(E,F) 1.0 * 30min = 30

Now, the 100 min item (D) looks like a more attractive first choice for the search algorithm. Of course, given enough time, the search could eventually find a different combination that includes (E) and (F) yielding a higher total score, but only exhaustive search could guarantee this. In practice we have to aim for a search technique that converges towards a "good-ish" solution fast.

3. Average score looks nice

So, getting rid of the dependence on item visit time has become desirable. Let's revisit the statement of the goal of the search for the best solution - perhaps if we reword it as "I would like each attraction in my tour to be as high-rated as possible", we are not distorting the meaning from the user's perspective. Mathematically, we get quite a difference:

m = avg(m_i)

Our first and second formula could also be expressed as average score, however this one is explicitly the average item score. Again applying that to our candidate solutions, we find that the winner by first formula, the solution consisting of items (1), (2) and (4) gets m = (1.0 + 0.8 + 0.3) / 3 = 0.7 and the winner by second formula scores m = (0.7 + 0.8) / 2 = 0.75. Checking our museum examples, obviously item (A) always yields higher average than (B) and (C), while from the search aspect (E) and (F), when using their individual item rankings, remain preferable to item (D).

The above looks very nice, but there is a catch - so far our model has been too perfect and we have ignored the real-world aspect of having to walk (or drive) from one attraction to other, attractions having opening and closing times and even the time available to perform the search expiring before something sensible has been produced. So, in a real-world application it is possible that tours containing a lot of "waste" time, such as picking inefficient routes between attractions, are produced. Should a candidate solution containing just item (1) appear somehow, it would win by virtue of it's unbeatable m = 1.0, even though 2.5 hours of the tour would be completely wasted.

Search algorithms can be guided to always use the available time, but from the aspect of just being able to compare all the conceivable candidate solutions, the problem does not go away. On the other hand, we can attack the issue from the scoring point of view in a fairly straightforward manner.

Let's introduce variable t_u that denotes the total time not spent at an attraction. We might now calculate some sort of a penalty to the overall score that increases when t_u increases and is 0 when the t_u is 0 (or low enough). This would put us on a slippery ground of having two criteria - "spend as much time at attractions as possible" and "have the highest possible average". The implications of this are beyond the scope of this article, but considering we get two sometimes diverging scores for each candidate solution, combining them together may require some sort of weights (of emphasis, relative importance), which leaves us with an administrative task of tuning these weights to best match our database of items and expectations for recommender output.

Instead, let's pretend that we did spend the unused time at some attractions - since they were completely useless, they contribute 0 individual item score each. Our formula then becomes:

m = sum(m_i) / (n + t_u / t_avg)

Where n is the number of items in the candidate solution and t_avg is some amount of time we have assigned to visiting these imaginary items which could also be derived from the available item data. We consider the imaginary attractions as discrete items, so the remainder of t_u/t_avg is ignored.

Note that we haven't quite avoided using a parameter to aggregate the evaluations of two potentially conflicting criteria as stated earlier. The difference now is that we can predict the behavior of the recommender somewhat - if there is something, anything with a score higher than 0 to insert into that unused time, the recommender will try to do so. The extreme cases where one high-scoring item alone beats a number of very low-scoring ones remain - without collecting statistics on recommendations it is too early to state whether this is an issue that still needs addressing.

For the sake of completeness, here are the scores for candidate solutions we have found so far, using t_avg = 45 min: items (1), (2) and (4) m = (1.0 + 0.8 + 0.3) / (3 + 30/45) = 0.7; items (2) and (3) m = (0.7 + 0.8) / (2 + 20/45) = 0.75; a solution consisting of just item (1) m = 1.0 / (1 + 150/45) = 0.25.

Thursday, March 24, 2011

About sightsplanner

Sightsplanner is a personal recommender for your trip to a foreign city. It was launched for Tallinn in spring 2011.

Based on your time of the visit and your preferences about different types of sights and events, the system will suggest which places to visit and will build a realistic itinerary just for your visit.

Why use sightsplanner?

Obviously, most people planning a trip start investigations by looking for materials on the web. It is easy to find a large amount of information about the city and its most popular tourism objects, but it takes very long time to select and organize all the interesting objects. Places and events which are really interesting for you, but not for the general public, are easily missed.

Once you find the sights you'd like to see, you need to build a rough itinerary. This is - obviously - pretty hard. We need to find out opening times and schedule the visits accordingly. It may turn out that some of the objects do not fit into the time schedule, in which we will have need to select different objects. All this takes a lot of effort.

Sightsplanner takes care of finding the objects based on you personal preferences, preferences, visit time, method of travel and the corresponding information about sights: their types, opening times, location, typical visit time and popularity of the sight. It will also build an itinerary for your visit. Last not least, sightsplanner knows more objects and more about the objects than any other site.

Using sightsplanner

Your plan and suggestions are composed using your preferences, visit time, method of travel and the corresponding information about sights: their types, opening times, location, typical visit time and popularity of the sight.
Set your preferences by moving sliders left or right. Moving the slider left will give fewer suggestions in that category, moving right will give you more. You can set more detailed preferences by opening the subcategory list: just click on the category name and the detailed list will open.

After setting your preferences, click the "Look" button: this will build your personalized visit itinerary. If you just want to see the most popular objects of the selected category mix, click the link "Popular objects" below the button. At the bottom of the page there are several options for defining your visit - start time and date, duration and means of transport. The question marks after the sliders give a few hints about what might be included in that category. The four pre-set options at the top of the page simply move several sliders at once to a predefined position. 

How does it work?

The suggestion engine finds interesting objects for the given user, based on the user preferences, using sophisticated probabilistic matching algorithms and a wealth of knowledge about the objects. For example, sightsplanner knows the rough popularity of the object, it knows the different categories (along with fuzzy degrees) the object is in, it knows the average visit time and opening times. Each knowledge item is associated with a degree of confidence.

In order to find the interesting objects, each query recalculates the score of "interestingness" for absolutely all the objects in the database, for exactly the user-given set of preferences and limitations of the given query. Simply put, the objects that the user probably likes have a higher score and vice versa.

The objects and events with their calculates "interestingness" are then organized into a timetable based on their location and time using several optimal trip search algorithms in parallel.

Conceptually, we use extended semantic web techonology plus probabilistic rules with a confidence measure. Data is kept as extended RDF sextuplets - object, property, value, confidence, source, timestamp - in both an ordinary relational database and an extremely fast main memory database for match calculation and planning. We derive additional information for objects using a rule system including full predicate logic augmented with a confidence measure.

The system database is built by merging, scraping and converting information from a wide number of different sources: several structured databases, several semistructured thematic websites plus human research and data augmentation/correction.

Contacts and links

Sightsplanner was built by a team of developers and researchers from three companies Mindstone, Apprise, ELIKO and the Tallinn University of Technology.

For further information, contact Tanel Tammet: tanel.tammet@gmail.com

Some links you may want to check: