As I get deep in an actual web application, like the Nonprofit Planner and Grant Generator, it is easy to lose track of what my overall goal is with this blog and my book "The Shape of Knowledge".
My main message is, and has been, that there are basic knowledge patterns that capture important types of reasoning. The pattern I am elaborating on here is a Composer, which captures content once and then configures and reconfigures it into various documents to meet a particular need.
The value of identifying these patterns is that a talented developer, like my partner Steve, can write a powerful program that consumes predefined knowledge artifacts created by domain experts and then generates a web app automatically based on that knowledge. I call this type of program an application generator, or an 'apperator', for short.
At the same time, the identification of knowledge patterns empowers us, the knowledge authors who create the knowledge artifacts, because we can use these 'apperator' programs to build our own custom solutions without writing code.
In this particular case, I built a template using KnowtShare (our online collaboration tool), and made it available to charities for developing and documenting their business plans. The shape of that template, and therefore all plans created using it, is a hierarchical tree model. I call this shape a 'triangle' because it grows from a single root to the many 'leaves' of the tree. This tree/triangle is the knowledge artifact that stores the raw material for the Grant Composer. Each charity will create and maintain its own business plan.
There is a second artifact required, and it is built and maintained by me, as a community resource. That is a table -- a 'square' -- containing the information requirements for particular foundations.
The 'apperator' Steve has written is a Composer that knows how to consume these two types of artifacts: a hierarchical KnowtShare file filled with written information items and a .csv file that contains a matrix of communication targets (foundations) and their preferred order for those information items. Context questions are used to identify which branches of the tree and which rows of the table to use when creating a solution at run-time.
I, as the knowledge author, decided to use business plan information to populate a grant application for foundations, so the actual app that is created is a Grant Application Generator. But the same pattern could be used to collect an individual's CV and generate a customized resume for a particular company -- that would be a Resume Generator. Or a student's transcript and essay questions to generate a customized college application -- that would be a College Application Generator. This makes sense: these examples are very similar to the Grant Generator.
What about something further afield? There's a whole industry evolving around using legal boilerplate and context questions to generate legal documents. The Composer pattern could be used to achieve the same results, and with far less programming.
My last post was dedicated to describing how the very same business planning information used in grant applications can be used to generate other reports and marketing materials. All of these are examples of the Composer Pattern and can be created by the same aperator with only minor tweaks.
The Composer is just one pattern. I have written about the Recommender pattern and the Scoring pattern as well, and I will be describing others going forward.
The challenge, and the opportunity, come from thinking about problem solving at a higher level of abstraction than we normally do.
Most applications are built to solve a particular problem. The IT team interviews their customers to determine the functional specifications for an application they want built. Then the IT people go off and build it, checking back in periodically with the customers to make sure they're still on track.
Typically there is a deadline looming, and everyone is focused on the problem at hand. No one is interested in investing time (and money) in designing a meta solution that will make the next problem easier to solve. In fact, if programming is paid for on an hourly basis, there is a disincentive to look for the patterns that will make application development more efficient. But as knowledge authors, and as problem solvers in general, there are many benefits to identifying and harnessing new patterns.
Knowledge patterns only become visible when you are exposed to many different but similar problems, and when you look for them. It also helps to have a vocabulary and a mental framework that make it easier to discuss the patterns you sense are emerging. My goal is to contribute to the creation of those foundational tools, and to create real world examples that will stimulate discussion.
Lessons learned while exploring knowledge patterns that make it possible for domain experts to build web applications without writing computer code.
Showing posts with label data table. Show all posts
Showing posts with label data table. Show all posts
Tuesday, April 7, 2015
Tuesday, February 10, 2015
One More Input to the Nonprofit Planning System
I said in the prior post that two knowledge artifacts are required to run the Grant Generator: the Business Plan Tree, which provides the content, and the Foundation Sequencing Table, which provides the assembly instructions. There is one other input, a community asset that I build and maintain along with the Sequencing Table, which I call the Nonprofit Element Attribute table.
In the process of building the Nonprofit Planner and Grant Generator, there were certain design and formatting decisions that were left to me as the knowledge author. One was the rules for when to use the green 'completeness' highlighting in the business plan, and the other was how to format the output in the grant application.
First, I'll explain the completeness rules. Remember, in KnowtPlan, when an item is completed it is outlined in green in the note view and highlighted in green in the outline view.
The rule for when to apply the highlighting to the 'leaves' of the tree is simple: when both the short and long answer are filled in, add the green outline. So the completeness rule for 'Organization's Mission Statement' is 'self'; it is highlighted as soon as its 'self' is complete.
The rules for how to roll the highlighting up to higher levels in the tree are somewhat more complicated. That is because some of the higher level notes require their own answers and some are just headers added for organization purposes.
An example of a note that is just a header is 'SWOT Analysis'. It has no content; if you clicked on it, you would not get a popup window asking for a long and short answer. So its completeness rule is 'children'; it is highlighted as soon as all of its children are highlighted. In the screenshot above, SWOT is not highlighted because two of its attached notes have not been filled in yet.
On the other hand, 'Organization's Purpose' is a note that acts as a header but also requires its own content. The charity is expected to fill in the organization's purpose, which should be short and compelling - different from a mission statement, which can be rather wordy. So the completeness rule for 'Organization's Purpose' is 'both': it is considered complete when all of its children are completed AND its own content is filled in.
So one piece of information I have to provide is the completeness rule for every item in the plan. I do this by adding an attribute called 'completeness' and setting its value to 'self', 'children' or 'both'. A second attribute I need to provide for each item is how it should be formatted in the grant application that is generated. This is similar to assigning a paragraph style in Microsoft Word.
Even though we ask for a 'long' and 'short' answer for each question, it is clear from working with the actual content that some answers tend to be much longer than others. For example, contact info tends to be very short. Descriptions of the Board members, on the other hand, tend to be much longer.
So we created two different paragraph styles: 'inline' puts the question header on the same line as the response pulled from the business plan; 'paragraph' puts the header on a separate line. There are also headers, the ones that have no content of their own, that never show up in the generated grant application. Their style is set to 'none'. This became a second attribute.
I'm sure there will be other attributes that will surface as we continue to develop the Nonprofit system. To make it easy to expand and maintain this sort of information, we capture it in a table that is easy for me to change, and doesn't require changes in computer code. The current version of the Nonprofit Element Attribute Table looks like this:
In the process of building the Nonprofit Planner and Grant Generator, there were certain design and formatting decisions that were left to me as the knowledge author. One was the rules for when to use the green 'completeness' highlighting in the business plan, and the other was how to format the output in the grant application.
First, I'll explain the completeness rules. Remember, in KnowtPlan, when an item is completed it is outlined in green in the note view and highlighted in green in the outline view.
The rule for when to apply the highlighting to the 'leaves' of the tree is simple: when both the short and long answer are filled in, add the green outline. So the completeness rule for 'Organization's Mission Statement' is 'self'; it is highlighted as soon as its 'self' is complete.
The rules for how to roll the highlighting up to higher levels in the tree are somewhat more complicated. That is because some of the higher level notes require their own answers and some are just headers added for organization purposes.
An example of a note that is just a header is 'SWOT Analysis'. It has no content; if you clicked on it, you would not get a popup window asking for a long and short answer. So its completeness rule is 'children'; it is highlighted as soon as all of its children are highlighted. In the screenshot above, SWOT is not highlighted because two of its attached notes have not been filled in yet.
On the other hand, 'Organization's Purpose' is a note that acts as a header but also requires its own content. The charity is expected to fill in the organization's purpose, which should be short and compelling - different from a mission statement, which can be rather wordy. So the completeness rule for 'Organization's Purpose' is 'both': it is considered complete when all of its children are completed AND its own content is filled in.
So one piece of information I have to provide is the completeness rule for every item in the plan. I do this by adding an attribute called 'completeness' and setting its value to 'self', 'children' or 'both'. A second attribute I need to provide for each item is how it should be formatted in the grant application that is generated. This is similar to assigning a paragraph style in Microsoft Word.
Even though we ask for a 'long' and 'short' answer for each question, it is clear from working with the actual content that some answers tend to be much longer than others. For example, contact info tends to be very short. Descriptions of the Board members, on the other hand, tend to be much longer.
So we created two different paragraph styles: 'inline' puts the question header on the same line as the response pulled from the business plan; 'paragraph' puts the header on a separate line. There are also headers, the ones that have no content of their own, that never show up in the generated grant application. Their style is set to 'none'. This became a second attribute.
I'm sure there will be other attributes that will surface as we continue to develop the Nonprofit system. To make it easy to expand and maintain this sort of information, we capture it in a table that is easy for me to change, and doesn't require changes in computer code. The current version of the Nonprofit Element Attribute Table looks like this:
Tuesday, January 27, 2015
The Grant Application Generator
While the process of creating a 'composer' that generates grant applications highlighted the need for charities to do better planning, I have never lost sight of my original intention. Yes, the Nonprofit Planner has value on its own, but the magic of the tool is that it collects important content in a highly reusable form. The first composer we have built to utilize this content is the Grant Generator, and there will be other composers down the road that can use the planning content as well.
In my book, and in prior posts about the Recommender, I talked about knowledge patterns. I have defined a knowledge pattern as a consistent set of knowledge artifacts that can be used over and over again to solve a certain type of problem. The knowledge pattern for a Recommender looks like this:
I've written a series of posts about applying this pattern to build a Whiskey Recommender.
The pattern for a Composer is remarkably similar to that of a Recommender. The pattern for a generic Composer looks like this:
How this general pattern translates into specifics for the Grant Composer is shown here:
Two knowledge artifacts are required for a Composer: a document content tree, which contains the raw material for the document to be composed, and a table, which contains the assembly isntructions.
In earlier posts, I described the Foundation Sequencing Table, which holds the assembly information necessary to generate a grant application. This table will be a community asset that I will build and maintain. There will be only one version of this table because the information requirements for a particular foundation are the same for all charities that apply for grants.
The content to be assembled, however, is unique to each charity; each will have its own business plan, documented using our planning tool. This plan is an asset that will be built and maintained by the charity.
These two knowtifacts, then, are inputs to the composer application. Like all of our applications, the first step in using the tool is to collect the context for the current situation. In general, we run an application to solve a particular problem in the current moment, and the context is the way we describe our current needs.
The Grant Application Generator needs to collect two types of context information.
The first type is information that helps the application 'prune' down the input knowledge artifacts to the relevant columns, tree branches and fields. Questions like 'which foundation', 'which program' and 'long or short answers' fall into this category.
The second type is specific information that refers to this particular grant request only, and therefore cannot come from the business plan. Information in this category includes the request amount and date. This information must be collected at run-time so it can be filled in at the appropriate locations in the generated document.
Once the context is collected and 'OK' is clicked, the Grant Generator creates a document that meets the specifications: just the information the target foundation wants to see, and in the order they want to see it. (I've grayed out this charity's info, to protect their privacy.)
In my next post I'll discuss some of the details about how this report is formatted, and how charities can use it.
Tuesday, October 21, 2014
The Sequencing Table for the Grant Proposal Generator
The Content Table described in my last entry is the 'parts catalog' in the document configurator I want to build. The Sequencing Table will act as the assembly instructions.
The format of the Sequencing Table is similar to that of the content table, because they share a key field: the grant application questions.
Every row in the Content Table must have a corresponding row in the Sequencing Table for that content to be included in the grant proposal that is generated. There are a few headers added for organization purposes, like the "General Questions" text shown here, but they do not show up in the generated proposals.
A number in the column simply means that a given item is in that position in the proposal for that foundation. A blank means the information item is not required. In this way, the column of numbers shows both the subset of information required and the order it should be placed in to meet that foundation's needs.
This column of information needs to be filled out for each foundation that appears in the Grant Proposal Generator. My strategy for capturing this information is to prioritize foundations based on the needs of the charities that participate in our pilot program. I am working closely with the pilot program charities to help them find like-minded foundations that will have a higher probability of granting their requests. I will use the timelines generated from these prospecting lists to prioritize the foundations and schedule their addition to the system.
My goal is, eventually, to have foundations add themselves to the system by providing an intuitive, easy-to-use tool that helps them select the questions they want and arrange them in their preferred order. They will also be able to use the tool to modify their 'questionnaire' at any time. This will be the most efficient way to develop and maintain the Sequencing table, and will guarantee the Grant Proposal Generator is up-to-date with foundations' current requirements.
My next step is to work with my pilot charities to fill out the Content Table.
The format of the Sequencing Table is similar to that of the content table, because they share a key field: the grant application questions.
Every row in the Content Table must have a corresponding row in the Sequencing Table for that content to be included in the grant proposal that is generated. There are a few headers added for organization purposes, like the "General Questions" text shown here, but they do not show up in the generated proposals.
A number in the column simply means that a given item is in that position in the proposal for that foundation. A blank means the information item is not required. In this way, the column of numbers shows both the subset of information required and the order it should be placed in to meet that foundation's needs.
This column of information needs to be filled out for each foundation that appears in the Grant Proposal Generator. My strategy for capturing this information is to prioritize foundations based on the needs of the charities that participate in our pilot program. I am working closely with the pilot program charities to help them find like-minded foundations that will have a higher probability of granting their requests. I will use the timelines generated from these prospecting lists to prioritize the foundations and schedule their addition to the system.
My goal is, eventually, to have foundations add themselves to the system by providing an intuitive, easy-to-use tool that helps them select the questions they want and arrange them in their preferred order. They will also be able to use the tool to modify their 'questionnaire' at any time. This will be the most efficient way to develop and maintain the Sequencing table, and will guarantee the Grant Proposal Generator is up-to-date with foundations' current requirements.
My next step is to work with my pilot charities to fill out the Content Table.
Tuesday, September 9, 2014
Knowtifacts Required for a Composer Application
As I said in my last post, a Composer is basically a document configurator. Two required inputs for any configurator are a parts catalog and instructions for how to select and assemble the parts to meet the current need. To build a Grant Composer, I needed to design those two knowtifacts -- first, generic versions capable of generating any type of document and second, specific versions suitable for generating grant proposals.
My high level goal for The Shape of Knowledge -- the book, this blog and the Apprentice Systems website -- is to create an environment where people with knowledge can generate useful applications that embody that knowledge without writing computer code. To achieve this, people must be able to document their knowledge in easy-to-use tools like Microsoft Excel. A spreadsheet is perfect for capturing 'square' knowledge like tables. We created our own tool, KnowtShare, for documenting hierarchical triangle-shaped knowledge like decision trees. Between KnowtShare and Excel (Excel can also capture lines/lists and cubes/3D tables) we've been able to document many forms of important knowledge. The knowledge necessary to create a Composer is two tables, so only Excel will be required.
Then our job at Apprentice Systems is to create the Application Generators - - "apperators" - that can consume this documented knowledge and generate simple but useful applications. This method only works because underpinning the whole process is a highly reusable, generally applicable knowledge pattern that provides discipline and acts as a link between the documented knowledge and the app generator. Yes, two tables are all that's required, but the two tables must meet a consistent set of requirements for the Composer Apperator to work. My task is to design the two tables and identify those requirements.
The first table is the Content Table, and it will act as the 'parts catalog' for my configurator. It will be the comprehensive set of questions and answers that the Composer will draw from to generate a grant proposal. There will be multiple columns in this table, representing the various versions of the content.
The second table is the Sequencing Table, and it will act as the instructions for how to select and assemble items from the Content Table. There will also be multiple columns in this table, providing different sequencing instructions for different potential target audiences.
"To meet the current need" -- establishing the context for a particular document -- will determine which columns to use from each of the two tables. When running the Composer the user will select the version of the content and the target audience for that particular document, and the Composer will generate an HTML document that meets those specifications.
This is the general game plan. The next posts will show how this actually works for grant proposal generation.
My high level goal for The Shape of Knowledge -- the book, this blog and the Apprentice Systems website -- is to create an environment where people with knowledge can generate useful applications that embody that knowledge without writing computer code. To achieve this, people must be able to document their knowledge in easy-to-use tools like Microsoft Excel. A spreadsheet is perfect for capturing 'square' knowledge like tables. We created our own tool, KnowtShare, for documenting hierarchical triangle-shaped knowledge like decision trees. Between KnowtShare and Excel (Excel can also capture lines/lists and cubes/3D tables) we've been able to document many forms of important knowledge. The knowledge necessary to create a Composer is two tables, so only Excel will be required.
Then our job at Apprentice Systems is to create the Application Generators - - "apperators" - that can consume this documented knowledge and generate simple but useful applications. This method only works because underpinning the whole process is a highly reusable, generally applicable knowledge pattern that provides discipline and acts as a link between the documented knowledge and the app generator. Yes, two tables are all that's required, but the two tables must meet a consistent set of requirements for the Composer Apperator to work. My task is to design the two tables and identify those requirements.
The first table is the Content Table, and it will act as the 'parts catalog' for my configurator. It will be the comprehensive set of questions and answers that the Composer will draw from to generate a grant proposal. There will be multiple columns in this table, representing the various versions of the content.
The second table is the Sequencing Table, and it will act as the instructions for how to select and assemble items from the Content Table. There will also be multiple columns in this table, providing different sequencing instructions for different potential target audiences.
"To meet the current need" -- establishing the context for a particular document -- will determine which columns to use from each of the two tables. When running the Composer the user will select the version of the content and the target audience for that particular document, and the Composer will generate an HTML document that meets those specifications.
This is the general game plan. The next posts will show how this actually works for grant proposal generation.
Monday, August 18, 2014
Deb's Whiskey Recommender
Earlier posts have described the processes, both mental and physical, that I went through to create the knowtifacts necessary for generating a Whiskey Recommender. I used basic Excel skills to create the Options table. I used KnowtShare to generate the Context Decision Tree. I used Google and Bing's image search tools to find suitable images and placed them in a folder. I uploaded these three components into the Recommender Apperator, and it generated "Deb's Whiskey Recommender" for me.
For each of these steps I needed some basic computer skills, but I never needed to write computer code. What was most essential for me to provide was the knowledge of whiskey and an opinion about which type of whiskey was the best choice in different contexts.
Since I wasn't an actual whiskey expert, I had to use the internet to educate myself. I also realized, too late, that I had taken on a really, really complicated subject for what was supposed to be a simple tutorial! This forced me to make several compromises between completeness and manageability. I had to cut corners. Each time I did, I noted that if I were building a real application I might have made different choices, and suggested how a more complete approach might be pursued.
So what did my efforts get me? Here are some screenshots of Deb's Whiskey Recommender, the app generated by the Recommender Apperator:
The logic I embedded in the Context Decision Tree is transformed into a simple wizard.
As the user makes choices, those choices are placed into the 'breadcrumbs' at the top of the page. This navigation device not only makes it clear which path has been taken through the tree, it makes it simple to backtrack to any one of the decisions and change it. When a user clicks on a prior choice, he or she will be taken to that spot in the wizard.
From a 'Shape of Knowledge' perspective, it is worth noting that the Context Decision knowledge is captured in a triangle shape, a tree, but the user interface serves that knowledge up in a linear fashion. This is an example of one of the best practices I talk about in my book: use the best knowledge shape for capturing the knowledge, but use the simplest shape possible when presenting it to a user. In this case, the triangular knowledge is flattened to a line by the wizard-like UI.
Based on this particular set of decisions, a long list of whiskeys is recommended. This path takes the user to the bourbons, both Tennessee Whiskey and Kentucky Straight Bourbon. Here is a sample of the recommended list:
The baseball card format lays out information from the Options Table. Shown are three of the many Kentucky Straight Bourbons in the Whiskey Table. At this point, the implications of the compromises I made become clear: everything on these three cards is identical, except for the brand name. Because all three whiskeys are from the same manufacturer, they have the same image. Because they are all the same type of whiskey, they have the same taste profile. Even though the price levels were calculated individually, they all happen to fall into the same price group. It would have been nicer if I had documented this information down to the individual brand level, but with 450 brands in the data table that wasn't feasible.
The options for knowledge authors building future Recommenders are these: pick a simpler topic, with fewer options; crowd-source the information in the Options Table; or be prepared to do a whole lot of work yourself, which is worth it if you are creating a Recommender to sell, establish your expertise, or to create competitive advantage.
Meanwhile, it is important to remember that the amount of effort required to create a complete data table is minor compared to the effort required to build this sort of application from scratch! The data has to be there, in any case -- there's no avoiding that work. But the ease of building the decision logic in KnowtShare is unparalleled, and the user interface and the computer logic that knits the pieces together comes for free.
This demo application achieved my goals: to document the process of building a Recommender, and to demonstrate that a potentially sophisticated application can be created based solely on domain expertise, no computer code required.
Wednesday, July 23, 2014
Adding Images to the Whiskey Recommender
While images aren't required for a Recommender app, there is a place for a picture in the 'baseball card' template, just as you would expect for any baseball card. Here is an example of the template, as it is used in the Beach Town Recommender:
I want to add images to the Whiskey Recommender, but this is more difficult than it was for beach towns. The challenge arises, once again, because I am working with a much larger set of possible options -- 450 different whiskey brands!
The Beach Town Recommender has about 30 towns in it, so it was relatively easy to search the internet for good medium-sized images of my beach towns and save them to a folder on my computer. I won't be able to do that for 450 whiskeys; it's just too much work. I'll have to find different images for different types of whiskeys, and stop there.
The basic process I used was to (1) locate images using a search engine, and then (2) save those images to a folder using a simple, consistent naming convention. Then I added a "Picture" column to my data table and (3) entered the file name of the image I wanted to display for that particular whiskey.
I started out with a nice, generic picture of whiskey that I could use for my default image. This is the one I selected:
I named this 'whiskey.jpg' and I copied that name into the entire "Picture" column in my data table. I would copy and paste over this name if I found a better/more specific picture.
Now I moved on to my top level classes in my classification tree: American, Scotch, Canadian and Irish. What sort of images could act as generic images for these high level classes?
I learned after doing a bit of image research, which I did in the image section of both Google and Bing, that there were pictures available that showed groups of whiskey bottles, selected to represent different types of whiskeys. Here's an example:
This is the image I decided to use for 'American'. Someone else had already created this for me -- I could see that different bottles had been cut and pasted into the image -- but that's okay, it saved me some time. What I liked about this picture is that it had a selection of Tennessee Whiskey, Kentucky Straight Bourbon and Rye Whiskeys, making it a snapshot of a variety of American types and brands. I found similar images for Canadian, Irish and Scotch. At this point, rather than copying and pasting image names into my data table, I decided to hold off and see what other pictures I could find.
I was able to find similar multi-bottle pictures for several sub-classes: American rye, Kentucky bourbon, Tennessee whiskey, single malt scotch, and blended scotch. I would have liked to have pictures for the other sub-classes as well, like 'American blended' or 'American corn', but I couldn't find anything appropriate. So I used the generic 'American' image for those types, just as I had to settle for only one image for all of the Canadian whiskeys. At this point, I copied the names of the most specific image I had available into the appropriate cells in my "Picture" column.
Now I assessed the situation. I realized that when someone used the Whiskey Recommender, if they were directed to a particular type of whiskey, like single malt scotch, they would see 20+ 'baseball cards' -- all with different information on them but with the same picture, this one:
That's a little too boring, even for a demo! So I knew I needed to push one more level down in the data, if I could.
There were a couple of different options I could pursue. In single malt scotch I had another column in my data table: "Region". I could look for images that went with Speyside, Highlands, Islay, etc. But the other possibility was to look for images that went with the "Company" dimension, images for Diageo, Suntory/Beam, Sazerac, and the like. I decided to look for company-specific images, because that could add visual diversity to all of the whiskey types, not just single malt scotch.
I was able to find images for Beam Irish, Beam American, Forty Creek Canadian, Sazerac Canadian, Diageo Scotch and Pernod Ricard Scotch. Here is the image for Pernod Ricard Scotch:
After adding these images to my image folder, I copied and pasted the image names into the appropriate cells of my data table. I would love to have a picture of every specific whiskey brand, but for this particular demo, I decided to stop at this point. The Whiskey Data Table -- one of the two knowledge artifacts required to create a Recommender app -- was complete.
When I build the Whiskey Recommender using the Recommender Apperator, I will need to upload my folder of images along with my Whiskey Data Table and Context Decision Tree so that the pictures can appear in my web app.
One final comment about finding appropriate images: I always use my search engine's tools to limit the images I am shown to medium-sized files. That is big enough to provide good resolution in my web app, while saving data storage and reducing load times during execution.
Now I need to move on to creating the final 'knowtifact' that is required to generate a Recommender: the Context Decision Tree.
I want to add images to the Whiskey Recommender, but this is more difficult than it was for beach towns. The challenge arises, once again, because I am working with a much larger set of possible options -- 450 different whiskey brands!
The Beach Town Recommender has about 30 towns in it, so it was relatively easy to search the internet for good medium-sized images of my beach towns and save them to a folder on my computer. I won't be able to do that for 450 whiskeys; it's just too much work. I'll have to find different images for different types of whiskeys, and stop there.
The basic process I used was to (1) locate images using a search engine, and then (2) save those images to a folder using a simple, consistent naming convention. Then I added a "Picture" column to my data table and (3) entered the file name of the image I wanted to display for that particular whiskey.
I started out with a nice, generic picture of whiskey that I could use for my default image. This is the one I selected:
I named this 'whiskey.jpg' and I copied that name into the entire "Picture" column in my data table. I would copy and paste over this name if I found a better/more specific picture.
Now I moved on to my top level classes in my classification tree: American, Scotch, Canadian and Irish. What sort of images could act as generic images for these high level classes?
I learned after doing a bit of image research, which I did in the image section of both Google and Bing, that there were pictures available that showed groups of whiskey bottles, selected to represent different types of whiskeys. Here's an example:
This is the image I decided to use for 'American'. Someone else had already created this for me -- I could see that different bottles had been cut and pasted into the image -- but that's okay, it saved me some time. What I liked about this picture is that it had a selection of Tennessee Whiskey, Kentucky Straight Bourbon and Rye Whiskeys, making it a snapshot of a variety of American types and brands. I found similar images for Canadian, Irish and Scotch. At this point, rather than copying and pasting image names into my data table, I decided to hold off and see what other pictures I could find.
I was able to find similar multi-bottle pictures for several sub-classes: American rye, Kentucky bourbon, Tennessee whiskey, single malt scotch, and blended scotch. I would have liked to have pictures for the other sub-classes as well, like 'American blended' or 'American corn', but I couldn't find anything appropriate. So I used the generic 'American' image for those types, just as I had to settle for only one image for all of the Canadian whiskeys. At this point, I copied the names of the most specific image I had available into the appropriate cells in my "Picture" column.
Now I assessed the situation. I realized that when someone used the Whiskey Recommender, if they were directed to a particular type of whiskey, like single malt scotch, they would see 20+ 'baseball cards' -- all with different information on them but with the same picture, this one:
That's a little too boring, even for a demo! So I knew I needed to push one more level down in the data, if I could.
There were a couple of different options I could pursue. In single malt scotch I had another column in my data table: "Region". I could look for images that went with Speyside, Highlands, Islay, etc. But the other possibility was to look for images that went with the "Company" dimension, images for Diageo, Suntory/Beam, Sazerac, and the like. I decided to look for company-specific images, because that could add visual diversity to all of the whiskey types, not just single malt scotch.
I was able to find images for Beam Irish, Beam American, Forty Creek Canadian, Sazerac Canadian, Diageo Scotch and Pernod Ricard Scotch. Here is the image for Pernod Ricard Scotch:
After adding these images to my image folder, I copied and pasted the image names into the appropriate cells of my data table. I would love to have a picture of every specific whiskey brand, but for this particular demo, I decided to stop at this point. The Whiskey Data Table -- one of the two knowledge artifacts required to create a Recommender app -- was complete.
When I build the Whiskey Recommender using the Recommender Apperator, I will need to upload my folder of images along with my Whiskey Data Table and Context Decision Tree so that the pictures can appear in my web app.
One final comment about finding appropriate images: I always use my search engine's tools to limit the images I am shown to medium-sized files. That is big enough to provide good resolution in my web app, while saving data storage and reducing load times during execution.
Now I need to move on to creating the final 'knowtifact' that is required to generate a Recommender: the Context Decision Tree.
Thursday, July 17, 2014
Adding Taste Attributes to the Whiskey Data Table
Now that I had a price level attribute in the table (see my last post) I wanted to add something about taste. I wasn't sure what information would be available about taste. There are plenty of qualitative descriptions on the web, describing particular types of whiskeys, but I wanted a single source that covered most of the whiskeys in my database. I found this very helpful graphic:
This picture reminds me a lot of the poster I used as my original knowledge source. It calls out the same four high level classes: Canadian, American, Irish and Scottish. It also has many of the sub-classes but not all of them. For example, it has some of the Scottish single malt regions, but not Campbeltown and Island. And there is no single malt listed under American whiskey, though there are several in my database.
This chart uses what is called a 'radar chart' to depict its information.
The number of flavors ranges from a high of seven for Highland single malt scotch to a low of one for several types of American whiskey. I'm okay with this; I think this reflects the differing complexities of different types of whiskey. People aren't buying American corn whiskey -- "moonshine" -- for its sophistication. My only real problem is the fact that I have several whiskey types with no taste information at all, because they are not listed in my taste knowledge source.
To fill in the blanks, I did further research. I found several sources that had taste profiles for both Island and Campbeltown single malts, so I filled those in, using the terminology I had already established.
The real challenge was American single malts. I found a New York Times article that talked about how this is an up-and-coming category, so it is important to have good data, but it also said this is such a diverse group it defies being summarized with a single taste profile. So I did what I have been resisting so far in this project: I created individual taste profiles for each whiskey.
I was able to find reviews for each American single malt in my database, and I used these reviews to create a taste profile containing my established terminology. Once again, if we were crowd-sourcing the data, or if this project were being funded by a customer, this individualized approach could be used for all of the whiskeys in the database, but this is a demo application that I am building to illustrate the process of building a Recommender, so I am going to keep things as simple as possible. There is a similar dynamic tension between effort and completeness in the final step of data preparation: adding images. That will be the topic of my next post.
This picture reminds me a lot of the poster I used as my original knowledge source. It calls out the same four high level classes: Canadian, American, Irish and Scottish. It also has many of the sub-classes but not all of them. For example, it has some of the Scottish single malt regions, but not Campbeltown and Island. And there is no single malt listed under American whiskey, though there are several in my database.
This chart uses what is called a 'radar chart' to depict its information.
There are eighteen axes coming out of the center that show the whiskey's rating on 18 different taste dimensions: sweet, smoky, grainy, vanilla, honey, spicy, briny, malty, cocoa, buttery, toffee, fruit, bacon fat, oaky, caramel, corny, biscuity, and peaty. A given whiskey can have one of three scores on each of these dimensions: 0, 1 or 2. I decided to change these numbers into written descriptions. If a whiskey scored a zero, that flavor is not mentioned at all. If it scores a '1', the flavor is mentioned, and if it scores a '2' I added the word "very". So single malt scotch from Speyside could be described as "very sweet, very honey, very fuity, very oaky, grainy, cocoa, buttery and caramel."
Once again, judgment now plays an important part. While I love this graphic, I think most people's taste buds are not refined enough to taste the subtleties conveyed here. Most of us would be lucky to perceive the "very" strong flavors, let alone the secondary mentions. So I made the decision to simplify even further and only mention the flavors that were strongly associated with the whiskey, the "very" flavors.
I had to decide how to record this information for my data table, because that will have an impact on how it is displayed in the 'baseball card' shown in the final recommendation. I could make a column for each of the 18 flavors and record the score -- 0, 1 or 2 -- but that doesn't seem very user friendly. There would be eighteen attributes listed for each whiskey, many of which will not be applicable. Instead I decided to create a group of columns and label them 'taste1', 'taste2' and so on, and fill in the strong flavors associated with that whiskey. My data table now looks like this:
To fill in the blanks, I did further research. I found several sources that had taste profiles for both Island and Campbeltown single malts, so I filled those in, using the terminology I had already established.
The real challenge was American single malts. I found a New York Times article that talked about how this is an up-and-coming category, so it is important to have good data, but it also said this is such a diverse group it defies being summarized with a single taste profile. So I did what I have been resisting so far in this project: I created individual taste profiles for each whiskey.
I was able to find reviews for each American single malt in my database, and I used these reviews to create a taste profile containing my established terminology. Once again, if we were crowd-sourcing the data, or if this project were being funded by a customer, this individualized approach could be used for all of the whiskeys in the database, but this is a demo application that I am building to illustrate the process of building a Recommender, so I am going to keep things as simple as possible. There is a similar dynamic tension between effort and completeness in the final step of data preparation: adding images. That will be the topic of my next post.
Tuesday, July 15, 2014
Adding the Price Attribute to the Whiskey Table
My next challenge in building the Whiskey Recommender is to add attributes to the data table that will become the core of the information shown on the 'baseball card' for the recommended whiskies.
I'm going to start with 'price'. I already know I won't be adding actual prices to the table because I've decided to stop my decomposition process at the 'brand' level. Since all the variants of a brand, including bottle size, will have a significant impact on the actual price I need to aggregate that pricing into something more conceptual, like 'price level'.
I start by searching the internet for a downloadable source of whiskey prices. I found one pretty close to home: I live in Northern Virginia, and the liquor stores are state run, or at least state controlled. I found a downloadable file with all the current liquor prices. It looks like this:
This type of file is called a "csv" file, which stands for 'comma separated values'. The first row in a csv file usually contains a description of the data that follows. In this case, I learned that each row in the table contains seven items of information: the description of the item, an identifying code of some sort, the brand, the bottle size, the age of the liquor, its proof, and price.
It's pretty simple to import this kind of file into Excel, which will create a table using the first row for column headings and placing the data in the correct cells beneath.
The next thing I did is eliminate all the rows that did not contain whiskey information. The VA liquor stores sell many different alcoholic products and I needed to pull the irrelevant ones out of the analysis. I also eliminated columns that weren't relevant to my analysis: code, age and proof. If I were decomposing my whiskey brands to a lower level, like different ages, I would need this information, but since I have made the decision to aggregate all the variants into a single price level I can eliminate these columns. Now I was down to description, brand, bottle size and price.
One variant I can't ignore is the impact of bottle size.To make sure I am aggregating 'apples to apples' prices, I need to average prices for one bottle size only; this is called 'controlling' for bottle size. I notice by looking at the data that 750 ml is the most common bottle size, so I used the Excel data functions to filter the data and keep only the rows for 750 ml bottles. This is now the data set I will use for my analysis.
I then used Excel's average function to calculate averages for each description. For example, the data shown above would be included in the 'scotch' average. It's clear from inspection that there are some outliers -- some bottles are very expensive! But our hope, as data analysts, is that the existence of outliers is spread out across different categories, and if there are clusters of them (like in scotch) that is a fair representation of the relative price for that category. Remember, we are trying to calculate a price rating of some sort, not an actual price. Scotch, and in particular, single malt scotch, is relatively expensive.
Once I had calculated an average for each description, I created a 5 point scale and a price range for each, with "5" being the most expensive. I used the description to map as closely as possible into the classification structure I had created in my data table and entered the price rating. To keep with our scotch example, I set the price level for every scotch in the table to "4". Now is where judgment comes in.
If I were building this application for a client, I would take the time to breakout sub-classes like 'single malt' in the Virginia price list so I could actually calculate the average price for that group. But since I am building this app as a demonstration piece, I was comfortable with sampling the single malts (I mean statistically sample, not literally - though I have done some of that in the course of my research) and giving single malt scotch a '5' on price level.
As a final pass of the data, I looked for brands that were priced significantly lower than other brands in their cohort. Different companies will have portfolios of brands in which one is used as their entry price point and is priced lower than the rest. If I can call those out without too much additional effort, I will. So I gave Dewar's a '3' and a scotch called Passport a '2'. I'm not sure that I caught all of these special cases, because the Virginia liquor stores don't sell every whiskey that's in my database, but I did the best I could with the data that is readily available.
Here's a sample of the whiskey data table with the price attribute added:
Notice Speyburn is a single malt scotch that I gave a '3' price rating, based on the actual price being significantly lower than other single malt scotches in the Virginia price list.
I'm going to start with 'price'. I already know I won't be adding actual prices to the table because I've decided to stop my decomposition process at the 'brand' level. Since all the variants of a brand, including bottle size, will have a significant impact on the actual price I need to aggregate that pricing into something more conceptual, like 'price level'.
I start by searching the internet for a downloadable source of whiskey prices. I found one pretty close to home: I live in Northern Virginia, and the liquor stores are state run, or at least state controlled. I found a downloadable file with all the current liquor prices. It looks like this:
This type of file is called a "csv" file, which stands for 'comma separated values'. The first row in a csv file usually contains a description of the data that follows. In this case, I learned that each row in the table contains seven items of information: the description of the item, an identifying code of some sort, the brand, the bottle size, the age of the liquor, its proof, and price.
It's pretty simple to import this kind of file into Excel, which will create a table using the first row for column headings and placing the data in the correct cells beneath.
The next thing I did is eliminate all the rows that did not contain whiskey information. The VA liquor stores sell many different alcoholic products and I needed to pull the irrelevant ones out of the analysis. I also eliminated columns that weren't relevant to my analysis: code, age and proof. If I were decomposing my whiskey brands to a lower level, like different ages, I would need this information, but since I have made the decision to aggregate all the variants into a single price level I can eliminate these columns. Now I was down to description, brand, bottle size and price.
One variant I can't ignore is the impact of bottle size.To make sure I am aggregating 'apples to apples' prices, I need to average prices for one bottle size only; this is called 'controlling' for bottle size. I notice by looking at the data that 750 ml is the most common bottle size, so I used the Excel data functions to filter the data and keep only the rows for 750 ml bottles. This is now the data set I will use for my analysis.
I then used Excel's average function to calculate averages for each description. For example, the data shown above would be included in the 'scotch' average. It's clear from inspection that there are some outliers -- some bottles are very expensive! But our hope, as data analysts, is that the existence of outliers is spread out across different categories, and if there are clusters of them (like in scotch) that is a fair representation of the relative price for that category. Remember, we are trying to calculate a price rating of some sort, not an actual price. Scotch, and in particular, single malt scotch, is relatively expensive.
Once I had calculated an average for each description, I created a 5 point scale and a price range for each, with "5" being the most expensive. I used the description to map as closely as possible into the classification structure I had created in my data table and entered the price rating. To keep with our scotch example, I set the price level for every scotch in the table to "4". Now is where judgment comes in.
If I were building this application for a client, I would take the time to breakout sub-classes like 'single malt' in the Virginia price list so I could actually calculate the average price for that group. But since I am building this app as a demonstration piece, I was comfortable with sampling the single malts (I mean statistically sample, not literally - though I have done some of that in the course of my research) and giving single malt scotch a '5' on price level.
As a final pass of the data, I looked for brands that were priced significantly lower than other brands in their cohort. Different companies will have portfolios of brands in which one is used as their entry price point and is priced lower than the rest. If I can call those out without too much additional effort, I will. So I gave Dewar's a '3' and a scotch called Passport a '2'. I'm not sure that I caught all of these special cases, because the Virginia liquor stores don't sell every whiskey that's in my database, but I did the best I could with the data that is readily available.
Here's a sample of the whiskey data table with the price attribute added:
Notice Speyburn is a single malt scotch that I gave a '3' price rating, based on the actual price being significantly lower than other single malt scotches in the Virginia price list.
Tuesday, July 8, 2014
Creating the Whiskey Data Table
As I mentioned in the last post, the whiskey poster I am using as my initial knowledge source has almost 450 different whiskey brands listed. These brands represent the many options a whiskey drinker has from which to choose. In a Recommender with a smaller number of options, like the Beach Town Recommender, these possible choices can be added as notes to the KnowtShare file and dropped directly into the classification tree, becoming the 'leaves' of that tree. However, 450 notes would be difficult to work with in a visual environment. Data tables are better at that.
So I switched from KnowtShare to Excel and began creating my data table.
I began by creating columns that aligned with the classes and sub-classes I had established in my classification tree.
So I switched from KnowtShare to Excel and began creating my data table.
I began by creating columns that aligned with the classes and sub-classes I had established in my classification tree.
Each row in the table is an option that can be recommended. The first column should always hold the option name; in this particular example it is a particular brand of whiskey.
I should point out that 'brand' is not the lowest possible level I could go in whiskey database. A particular brand can have many variants. For example, Macallan, a very fine scotch, comes in Macallan 12, 18 and 21, the number in the name referring to the number of years the whiskey has been aged. There is a basic Macallan, which is aged exclusively in sherry seasoned casks, and a Macallan Fine Oak, which is aged in a combination of sherry and bourbon seasoned oak for a lighter flavor.
In fact, the variants of whiskey seem to be endless, so to make the Recommender manageable I decided to stop at the brand level. This has its own challenges, because my next step will be to add some attributes to the table, attributes like 'taste' and 'price'. Any attributes I add will need to be generalizations, in a sense, because they will be referring to a group of whiskeys that vary in age, process and bottle size. If the data in this table could be crowd-sourced in some way it would be possible to account for this complexity, but as a demonstration app (which is what I am building) I will need to make some simplifying assumptions.
My next task is to expand the table by adding attributes to the whiskey brands.
Subscribe to:
Posts (Atom)



























