【问题标题】:Recognize different word classes识别不同的词类
【发布时间】:2016-03-06 10:20:40
【问题描述】:

我有很多来自网上商店的衣服。
每个条目都包含一个主词(例如衬衫、夹克)和一个或多个属性(例如尺寸、颜色)。

衣服可以有以下属性:

  • 尺码:XS、S、M、L、XL
  • 颜色:GREEN、RED、BLUE、...
  • 类别:SPORT、BUSINESS、CASUAL、...
  • 性别:MALE、FEMALE、UNISEX
  • ...

让我们看一个例子。

SPO SHIRT L 
CAS SHIRT M GRE
CAS SHIRT L RED
BUS SHIRT XS RED

CAS SHOES
SHOES BLACK

JACKET FEM M
JACKET FEM GRE
CAS JACKET MA RED

这些项目是由人类填充的,因此不一致。并非每个条目都有每个属性。他们也可能有不同的顺序。


我现在想自动识别主要单词和属性。我还想将属性分组到上面显示的组中。

示例输出只是单词组。

  • 主要词:衬衫、鞋子、夹克……
  • 属性:L、M、XS、GRE、RED、CAS、SPO、BUS、FEM、...

还有属性的类别:

  • L、M、XS、...
  • SPO、CAS、BUS、...
  • GRE、RED、...

当然,算法无法为类别提供合适的名称(例如尺寸、颜色)。


我已经知道的:

  • 相同类别(= 相同语义)的属性是互斥的。所以一件衬衫只能有 1 种尺寸、1 种颜色等。
  • 属性的数量远高于主要词的数量。
    • 因此,例如有 5 种不同的鞋子,但尺寸 L 会出现 20 次(与其他衣服一起)。

我可以使用哪些算法来识别这些单词?

一种可能的解决方案是过滤带有<=3 字母的单词。这些很可能是属性。但这是一种相当幼稚的方法。

我使用 JavaScript,但我也感谢伪代码。

这只是列表和可能类别的一小部分。

更新:

我确实事先知道这些属性。计算机应该无需我的帮助即可提取它们。

【问题讨论】:

  • 您能否举例说明您希望从上述项目列表中获得的输出?
  • @Fabius:请查看我的更新。
  • 如果您不能提供一组可能的主要词和一个可能的属性来测试完整的字符串,检查<=3似乎唯一的区别方法。您可能会使用一些(php?)代码以这种方式解析整个数据库,然后“手动”检查它以查找异常(并修复它们)。
  • 这实际上是一个很好的第一步。然后:阅读整个文件,制作一个计数单词列表,并使用最常用的单词only。注意(显然)每一行必须至少有一个“好”字。
  • ... 这将是理想的,但可能不存在这样的 t:在这种情况下,您可以选择最小的 t 使得每个产品在 wSBF[1 .. t] 中至少有一个词,或最大的 t,使得每个产品在 wSBF[1 .. t] 中最多有一个词。在任何情况下,后两个 t 值都为您提供了一个不错的(希望很小的)阈值范围供您手动考虑。

标签: javascript algorithm nlp pseudocode linguistics


【解决方案1】:

寻找主词是精确覆盖问题

让我们假设每个词要么是主词,要么是属性词——也就是说,没有词有时用作主词,有时用作属性。然后问题是将每个单词分类为 mainattribute - 或者等效地,确定所有单词的子集是主要词(因为其余的必须是属性词)。我们对属性词知之甚少,除了它们应该很常见。但是我们对作为主要词的词子集有更明确的了解:每个产品都必须恰好包含这个子集中的一个词

这个问题可以建模为找到一个exact cover,其中ground set(需要“覆盖”的项目的集合)是所有产品的集合,每个单词都给了我们一个我们可以潜在的集合用于覆盖其中一些基础元素:即使用该词的产品集。这个问题的一个解决方案是一个词的子集,其对应的产品集一起包含每个产品恰好一次——也就是说,它将是一个候选的主要词集。

不幸的是,找到一个精确的覆盖是一个 NP-hard 问题,所以没有已知的有效算法可以准确地解决这个问题。

整数线性规划的公式

尽管如此,通常可以通过将问题表达为integer linear program 并使用 ILP 求解器(例如免费提供的 lp_solve 或昂贵(但速度更快)CPLEX,来解决问题。有两种方法:

  • 使用 integer LP 精确解决问题:这可能需要很长时间,但如果存在则保证找到精确的解决方案。
  • 使用普通的连续 LP 启发式地解决问题:这将花费相当短的时间,即使对于较大的输入大小,但通常不会找到可行的解决方案。大多数变量不会被分配 1 或 0,而是会被求解器分配在 [0, 1] 范围内的某个值,这通常可以解释为置信度分数,并简单地四舍五入为 0 或 1。这样做不会'不保证最佳的甚至可行解决方案,但通过执行此四舍五入然后“修复”任何违反可行性(特别是没有指定主词的任何产品)通常可以获得一个好的解决方案,或[EDIT 7/3/2016]任何包含两个或多个主要词的产品)与简单的本地hill-climbing search heuristics

方便地,从一个更改为另一个就像指定变量是否被约束为整数一样简单;目标函数和所有约束都不会改变。

假设有 n 个不同的词和 m 个产品。要将这个问题表述为 (I)LP,我们需要为每个不同的词 j 设置一个变量 x_j,如果第 j 个词应该被认为是主词,求解器将赋值为 1,如果应该是主词,则赋值为 0考虑一个属性词(或者如果我们只解决连续松弛,则介于两者之间)。如果产品 i 使用单词 j,则让 p_i_j 为 1(此信息存在于输入中,并且可以表示为矩阵)。那么对于每个产品 i,我们需要约束

p_i_1*x_1 + p_i_2*x_2 + ... + p_i_n*x_n = 1.

这会强制产品 i 只包含一个主词。 (大多数单词不会出现在给定的产品中,因此上述表达式中的对应项 p_i_j 的值为 0 并且可以省略;这样做会大大减少问题描述的大小。)

这些约束是我们真正需要的,但 ILP 还为我们提供了一个目标函数来最小化或最大化。因此,我们可以通过尝试最大化(或最小化)函数来找到最大(或最小)的主要词集

x_1 + x_2 + ... + x_n

这个公式非常灵活:我们可以轻松地对某些词赋予更高的权重,或者通过将它们的 x_j 值限制为 0 来防止将某些词(例如出现频率太高的词)视为主要词。

示例

让我们为提供的示例数据片段实际计算一个词集。

不同的词是:

 1    BLACK
 2    BUS
 3    CAS
 4    FEM
 5    GRE
 6    JACKET
 7    L
 8    M
 9    MA
10    RED
11    SHIRT
12    SHOES
13    SPO
14    XS

[EDIT 7/3/2016]:我们可以在 CPLEX LP format 中表达 ILP 问题,添加一个目标函数(有点随意)最小化被选为主词的总词数:

Minimize
  x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_10 + x_11 + x_12 + x_13 + x_14
Subject To
  x_13 + x_11 + x_7 = 1
  x_3 + x_11 + x_8 + x_10 = 1
  x_3 + x_11 + x_7 + x_10 = 1
  x_2 + x_11 + x_14 + x_10 = 1
  x_3 + x_12 = 1
  x_12 + x_1 = 1
  x_6 + x_4 + x_8 = 1
  x_6 + x_4 + x_5 = 1
  x_3 + x_6 + x_9 + x_10 = 1
Binary
  x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9 x_10 x_11 x_12 x_13 x_14

将包含上述代码块的文本文件提交给the online SCIP solver at NEOS,我们会返回(据报道在 0.00s 时间内!)将 3 个变量 x_6、x_11 和 x_12 分配为 1,其余分配为 0 的最佳解决方案:这相当于选择了JACKET、SHIRT和SHOES作为主词。

在这种情况下,选择最小化选择作为主词的词的数量得到了我们认为正确的答案,但通常可以有多组满足条件的主词,如何做到这一点并不明显选择最好的。例如,如果我们决定最大化主要词的数量(正如我最初尝试的那样,FWIW),我们可以得到解决方案 {BLACK, BUS, CAS, FEM, SPO}。但总的来说,提供的输入越多,令人满意的词集就越少,因此目标函数的选择就越不重要。

查找属性类别是图形着色问题

在确定哪些词是主要词之后,我们要将剩余的属性词分解为类别。这个问题更难:基本上我们只能说,只要两个词属于同一类别,比如 CAS 和 BUS,它们就不能同时出现在同一个产品中。但如果这是我们应用的 only 约束,那么一个简单的解决方案就是将每个单个属性词放入其自己的类别中。当然这并不能告诉我们任何有用的信息,所以为了避免这种可能性,我们可以要求类别的总数尽可能少。

然后我们遇到的是(Minimum) Graph Colouring 问题:对于每个属性词,创建一个顶点,并在任意两个顶点之间创建一条边,只要它们的词都出现在同一个产品中。图着色是将“颜色”(或等效地,简单的类别)分配给顶点(单词),它总是为边的两个端点分配不同的颜色。最低限度的此类着色使用尽可能少的颜色(类别)。

有几种不同的方法可以将图形着色问题表述为 ILP。你可以使用the one given here。请注意,变量将比 Exact Cover ILP 中的变量多得多,并且对于某些公式,将有多达 k!将特定细分编码为 k 个类别的不同方法(本质上,与排序 k 个项目的方法一样多的类别分配),因此将这个问题解决到最优可能需要更长的时间。

【讨论】:

  • 谢谢。有很多东西可以玩。你能把你上传到 NEOS 的整个文件贴出来吗?如果我只是上传您在上面提供的代码,我会得到很多输出,但它主要由 0 组成。
  • 很高兴它有帮助!我现在已将该代码块更新为完整的 LP 格式文件,我已在 NEOS 服务器上对其进行了测试。 NEOS 服务器似乎返回了很多输出,但是您可以查找“解决方案状态:找到最佳解决方案”,在其下方列出了分配为 1 的变量。 (我现在已经删除了我原来的评论回复,它只包含相同的信息。)
【解决方案2】:

更新

记住:在这种情况下,数据越多,算法就越准确。但是如果你只有几行有很多属性,那么几乎每个算法都会失败。此外,对于 BLACK,>=3 的事情会失败,并且产品名称是 TIE,所以我们必须寻找一个好的算法。

现在这是我对这个问题的看法

  1. 解析数据并为每个项目创建每个唯一单词与其他唯一单词的矩阵。这将给出在哪个顺序放置中使用哪个单词以及与该顺序中的哪些单词相关的统计信息。这还将提供有关单词在订单中使用频率的统计信息。

  2. 我建议创建或(从某处导入)人类可识别颜色名称的列表,因为颜色名称是全局的,如果它是蓝色的,那么人们会写成蓝色。这将有助于识别颜色。

  3. 一旦识别出颜色,我们就可以寻找性别。当然,如果一个是 FEMALE,写它的概率是 F 或 FEM 或 FEMALE。因此,我们必须通过任何string matching algorithm 找到与性别名称最接近的匹配项。

  4. 现在定位

  5. 之后从剩余的词中寻找出现频率最高的词,每个频率的出现频率都会相当高(因为类别有限),所以设置一个最小出现的阈值来将某事物识别为一个类别。

  6. 最后剩下的词就是物品名称(衬衫、鞋子等)

这里可能出现的唯一错误是数据非常少或频率阈值未正确优化。

MY_PREVIOUS_ANSWER:(当我认为你只需要解析输入时,但这仍然可以用来创建矩阵)。

我认为您可以通过创建地图并对其进行迭代来解决问题,例如

(function () {
  "use strict";
  const text = `SPO SHIRT L 
  CAS SHIRT M GRE
  CAS SHIRT L RED
  BUS SHIRT XS RED
  
  CAS SHOES
  SHOES BLACK
  
  JACKET FEM M
  JACKET FEM GRE
  CAS JACKET MA RED`;
  
  const tokens = {
    size_list: "XS, S, M, L, XL".split(', '),
    color_list: "GREEN, RED, BLUE, BLACK".split(', ').map((c) => c.slice(0, 3)),
    category_list: "SPORT, BUSINESS, CASUAL".split(', ').map((c) => c.slice(0, 3)),
    gender_list: ["MA", "FEM", "UNI"],
    item_list: "SHOES, SHIRT, JACKET".split(', ')
  };
  
  let items = text.split(/\n/).filter((line) => !!line.trim()).map((line) => {
    line = line.trim();
    let item = {};
    line.split(' ').forEach((w) => {
      Object.keys(tokens).forEach((t) => {
        tokens[t].includes(w) && (item[t.replace('_list', '')] = w);
      });
    });
    return item;
  })
  
  document.write(JSON.stringify(items, 0, 4));
}());

【讨论】:

  • 谢谢。但我事先并不知道所有属性。我只是提供一个列表,计算机应该完成工作(识别属性和主要单词)。
  • 我认为你可以实现一些接近的目标,但不完全是你想要的,我现在正在努力
  • 虽然我正在研究算法代码,但它花费了相当多的时间,所以我只会告诉你我的算法,请查看我的答案,我已经用算法 @user1170330 编辑了它
猜你喜欢
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 2015-09-08
相关资源
最近更新 更多