10

我正在构建一个红宝石配方管理应用程序,作为其中的一部分,我希望能够将成分数量解析为我可以比较和扩展的形式。我想知道最好的工具是什么。

我最初计划使用一个复杂的正则表达式,然后是一些其他将人类可读的数字(如twofive)转换为整数的代码,最后是将 say1 cup3 teaspoons转换为一些基本度量的代码。我控制输入,所以我将实际成分分开。但是,我注意到用户输入了抽象度量,例如to taste1 package。至少对于抽象测量,我想我可以忽略它们并缩放并刮掉它们之前的任何数字。

这里还有一些例子

1 tall can
1/4 cup
2 Leaves
1 packet
To Taste
One
Two slices
3-4 fillets
Half-bunch
2 to 3 pinches (optional)

这有什么技巧吗?我注意到用户似乎对数量的构成有些困惑。我可以尝试执行更严格的规则,并将诸如tall can和之类的东西推leaves入成分部分。但是,为了强制执行,我需要能够传达无效的内容。

我也不确定我应该将数量转换为什么“基础”测量。

这些是我的目标。

  1. 能够扩展食谱。 任意度量单位,例如 packages不必缩放,但精确的度量单位喜欢cupsounces需要缩放。

  2. 找出“主要”成分。 在这个问题的背景下,这将主要通过弄清楚配方中最大的成分是什么来完成。在生产中,必须有某种基于成分类型的修饰符,因为很明显,flour几乎从未将其视为“主要”成分。不过,chocolate可以少用,还是可以说是一个chocolate cake

  3. 规范化输入。 为了保持网站的一致性,我想保持一致的缩写。例如,pounds应该是,而不是lbs

4

4 回答 4

23

您提出了两个问题,识别/提取数量表达式(语法)并弄清楚它们的含义(语义)。

在确定正则表达式是否足以识别数量之前,您应该让自己对它们的外观有一个很好的模式(语法)。您的示例如下所示:

<amount> <unit> [of <ingredient>]

where<amount>可以采取多种形式:

whole or decimal number, in digits (250, 0.75)
common fraction (3/4)
numeral in words (half, one, ten, twenty-five, three quarters)
determiner instead of a numeral ("an onion")
subjective (some, a few, several)

金额也可以表示为两个简单<amount>s 的范围:

two to three
2 to 3
2-3
five to 10

然后你有单位本身:

general-purpose measurements (lb, oz, kg, g; pounds, ounces, etc.)
cooking units (Tb, tsp)
informal units (a pinch, a dash)
container sizes (package, bunch, large can)
no unit at all, for countable ingredients (as in "three lemons")

最后,有一种特殊情况的表达式永远不能与数量或单位组合,因此它们可以有效地作为两者的组合:

a little
to taste

我建议将其作为一个小型解析器来处理,您可以根据需要对其进行详细或粗略的处理。如果这是您选择的工具,那么为所有这些编写正则表达式应该不会太难,但正如您所见,这不仅仅是文本替换的问题。将零件拉出并将每种成分表示为三元组(amount, unit, ingredient)。(对于可数,使用特殊单位“件”或其他;对于“一点”等,我会将它们视为特殊单位)。

这就留下了转换或比较数量的问题。很多地方都进行了单位换算,因此至少对于官方单位来说,您应该可以轻松获得换算表。例如,如果您输入“将 4 盎司转换为克”,Google 就会执行此操作。请注意,一汤匙是三汤匙或四汤匙,具体取决于国家/地区。

您可以很容易地将定义明确的单位标准化为您最喜欢的单位,但非正式单位有点棘手。对于“a pinch”、“a dash”等,我建议找出近似重量,以便您可以正确缩放(10 pinches = 2 g,或其他)。罐头之类的东西是没有希望的,除非你能查到特定产品的尺寸。

另一方面,主观量是最简单的:如果你将“品尝”放大十倍,它仍然是“品尝”!

最后一个想法:识别主要成分还需要某种成分数据库,因为大小很重要:“一个鸡蛋”可能不是主要成分,但“一只小山羊,四等分”可能是主要成分。我会考虑将其用于第 2 版。

于 2012-09-18T18:09:44.073 回答
10

正则表达式很难用于自然语言解析。就像您提到的那样,NLTK 可能是一个不错的选择,否则您会发现自己绕着圈子试图使表达式正确。

如果你想要一些 Ruby 类型的东西而不是 NLTK,请看一下 Treat:

https://github.com/louismullie/treat

此外,语言学框架也可能是一个不错的选择:

http://deveiate.org/projects/Linguistics

编辑:

我认为那里必须已经有一个 Ruby 配方解析器,这是您可能想要研究的另一个选项:

https://github.com/iancanderson/ingreedy

于 2012-09-14T13:56:05.103 回答
6

如果你知道如何编写一个好的网络爬虫和解析工具,那里有很多免费的培训数据。

http://allrecipes.com/Recipe/Darias-Slow-Cooker-Beef-Stroganoff - 这个网站似乎可以让您根据公制/英制和用餐人数转换食谱数量。

http://www.epicurious.com/tools/conversions/common - 这个网站似乎有很多转换常数。

对现有配方站点的一些系统抓取,这些站点以某种结构化格式(您可以通过阅读底层 html 发现)呈现成分、程序,这将帮助您建立一个非常大的训练数据集,这将使处理此类问题变得更加容易。

当您拥有大量数据时,即使是简单的学习技术也会非常有用。一旦你有大量数据,你就可以使用标准的 nlp 技巧(ngrams、tf-idf、naive bayes 等)来快速做一些很棒的事情。

例如:
主要成分
具有较高 idf(逆文档频率)的菜肴中的成分更有可能是主要成分。每道菜都提到盐,所以它的 idf 应该很低。很少有菜提到油,所以它应该有更高的 idf。大多数菜肴可能只有一种主要蛋白质,因此“鸡肉”、“豆腐”等短语应该比盐、洋葱、油等更罕见,也更有可能成为主要成分。当然也可能有“香菜”之类的项目' 这可能比 'chicken' 更罕见,但如果你在每道菜中都刮掉了一些相关的元数据,你也会得到可以帮助你解决这个问题的信号。大多数厨师可能不会在他们的食谱中使用香菜,但那些确实使用香菜的人可能很多。因此,对于任何成分名称,您都可以找出名称'

缩放食谱
大多数食谱网站都会提到特定菜肴的服务人数,并有一个单独的成分列表,其中包含适合该人数的数量。
对于任何特定的成分,您可以收集所有提及它的食谱,并查看为多少人规定的成分数量。这应该告诉您使用哪些短语来描述该成分的数量,以及数字如何缩放。您现在还可以收集使用特定短语描述数量的所有成分(例如,“切片”->(面包、奶酪、豆腐……)、“杯子”->(大米、面粉、坚果、.. .)) 并查看这些短语中最常见的短语并手动写下它们的扩展方式。

规范化输入
这似乎根本不是一个难题。手动整理常见缩写及其完整形式的列表(例如,'lbs' -> 'pounds'、'kgs' -> 'kilograms'、'oz' -> 'ounces' 等)应该可以解决 90% 的问题。每当您看到它们时,将新的缩略词添加到此列表中应该会使此列表在一段时间后变得非常全面。

总之,我要求您大幅增加数据的大小,并收集大量相关的元数据以及您抓取的每个食谱(作者信息、食物类型等),并使用所有这些结构化数据以及简单的 NLP/ML 技巧解决您在尝试构建智能食谱站点时将面临的大多数问题。

于 2012-09-22T22:59:05.097 回答
0

就这些而言:

  1. 我会对这些进行硬编码,这样如果你得到的盎司多,就用杯子,如果你得到的杯子比那么多,就用品脱、垃圾、加仑等。我不知道你怎么能避免除非有人已经编写了代码来处理这个问题。

  2. 如果标题中有一种成分,它可能是主要成分。不过,您会遇到“燕麦葡萄干饼干”的问题。正如你所说,面粉、牛奶等不是主要成分。您还需要将培根、猪排、烤猪肉全部映射到猪肉,并将牛排、汉堡包等映射到牛肉。

  3. 同样,这只是查看某物的数量,你知道人们会有磅、盎司等,所以尽量抢占他们并尽可能地写这个。您可能会错过一些,但随着您网站的发展,您将能够引入新的过滤器。

如果您完成所有这些工作,请考虑发布它,这样其他人就不必这样做了:)

于 2012-09-14T13:35:11.560 回答