1

私はPHPベースのショッピングアプリケーションに取り組んでいます。同じ製品を表すことがわかっている文字列のリストがあります。これらの文字列には、完全な製品名またはその一部が含まれている可能性があります(完全な製品名は通常、ブランド+モデルです)。

この製品名の抽出を実行するための最良のアプローチは何でしょうか。

たとえば、同じ製品を表す文字列のリストは次のとおりです。

  • Tkg BOUILLOIRE TKG-JK 1008 RWD
  • Tkg Jk 1008 Rwd
  • Tkg Kalorik-JK1008RWD-BouilloireÉlectriquesansFil360°
  • TKGBouilloireélectriquesansfil1.7リットル2000ワットPoisTKGRouge et blanc
  • Tkg Kalorik-JK1008RWD-BouilloireÉlectriquesansFil360°
  • Tkg JK 1008 RWD BOUILLOIRES

商品名「TkgJK1008RWD」を抽出する予定です。文字列4には部分的な情報しか含まれていないことに注意してください。

すべての文字列で繰り返される単語を数えたときに、アプローチを試しました。しかし、そこから先に進むのは難しい。

手がかりはありますか?

乾杯ニコラス

4

4 に答える 4

2

文字列がどの程度重複しているかを分析し(そしてそれらのほとんどに現れる単語/部分文字列のリストを生成し)、最も関連性の高い単語を選択できます。

たとえば、単語が文字列の特定の割合で出現する場合、それらを製品名の最も可能性の高い候補として識別できます。(これまでに行ったことと同様ですが、しきい値を追加します。たとえば、文字列の 88% に 5 つの単語が表示され、他の単語ははるかに低いパーセンテージで表示されることがわかります。次に、製品名として上位 5 つを選択します。これは正確なものではありません。残念ながら手動で微調整する必要があります。) これで大部分の情報を収集できるはずですが、完璧にはなりません。

さらに、事前に定義されたブランドのリストを作成して、それらの単語を除外することもできます。また、手動でデータを入力した結果である可能性があり、常にタイプミスが発生する可能性があるため、単語の部分的な一致も考慮します. これがいかに重要かおわかりでしょう。単純にそれらを破棄するだけで十分な「シグナル」が得られれば、心配する必要はありません。

さらに進んで、別のフィルターを指定して手動キュレーションのアイテムをマークすることもできますが、これには非常に時間がかかる場合があります。

簡単な答えはないのではないかと心配しています。あなたがしていることは本質的にテキストマイニングです。始めるのに役立ついくつかのアイデアと出発点を紹介しました。

上記は、複数のソースからの日付をまとめようとする自動クローラーを構築していると仮定して機能します。訪問者がサイトを検索して、すべてのクエリに対して適切な製品ページを返せるようにしたい場合は、テキスト検索 (主なデータ分析はありますか?) に飛び込むことをお勧めします。または、既製のソリューションを使用するだけです。

于 2012-02-03T18:33:01.130 に答える
2

比較ショッピング エンジンで働いたことがあるので (特にこの問題についてではありませんが)、あなたが説明した問題は非常に難しいと思います。私の提案は、「その」製品名を合成または抽出しようとするのではなく、あきらめて「最高の」文字列を選択することです(とにかく漠然とした概念です)。製品名を抽出するために使用するほとんどのアイデアは、一貫性のないイライラする結果をもたらします. たとえば、あなたが示した例だけを見ると、素朴なアルゴリズムはおそらく「Jk 1008 Rwd」のような不可解な結果、または「Bouilloire Électrique」のような非常に曖昧なものを生成するでしょう。Tomas の巧妙で見栄えの良い結果でさえ、多くの製品では失敗するか、恥ずかしいほど非文法的な結果になります。

私があなたの立場なら、おそらく次のようにソリューションをモデル化するでしょう: タイトルの単語ごとに IDF 重みを計算します (すべての製品またはこのカテゴリのすべての製品をドキュメントのスペースとして表示します)。次に、各製品文字列をその idf 重みベクトルに変換し、製品のすべての重みベクトルの重心を計算します。その重心に最も近い文字列を見つけて、それを「最高」と呼びます。その文字列を製品名として使用します。完璧ではありませんが、ほとんどの場合うまくいく可能性があります。Lucene (または使用している検索データベース) にプラグインまたはクエリがあり、これらの多くを実行できる場合があります。

あなたが与えた弦のリストでは、この方法は4番目の不完全な弦から離れる傾向があります。これは、重みの高いモデル番号1008が含まれていないためです(おそらく電気ケトルでは一般的ではありません)。情報が少なく不完全な製品名がたくさんある場合、これは問題になる可能性があります。その場合、重心はモデル番号を含む名前に特に近いとは限りません。おっしゃる通り、難しい問題です。

その他のアイデア:

  1. 最初の n 個の最も一般的な単語を選択するという Thomas のヒューリスティックは、私が推測しているよりもうまく機能する可能性があります。あるいは、うまく機能しない場合を検出するための別のヒューリスティックがあるかもしれません
  2. ほとんどの文字列に共通する長い部分文字列を探し、IDF の重みの合計が最も高いものを選択します。

参考文献:

TF-IDF

重心

ベクトル空間モデル

于 2012-02-04T02:33:38.030 に答える
1

ほんの少しの考え

<?php
// to lower case
$string = strtolower(
'Tkg BOUILLOIRE TKG - JK 10o8 RWD
Tkg Jk 10o8 Rwd
Tkg Kalorik - JK 10o8 RWD - Bouilloire Électrique sans Fil 360°
TKG Bouilloire électrique sans fil 1,7 litre 2000 watts Pois TKG Rouge et blanc
Tkg Kalorik - JK 10o8 RWD - Bouilloire Électrique sans Fil 360°
Tkg JK 10o8 RWD BOUILLOIRES'
);

// remove new lines and explode by spaces
$data = explode(' ', str_replace(array("\r\n", "\n", "\r"), ' ', $string));
// count most popular words
$count = array_count_values($data);
// sort 
arsort($count);
// get first 6 most popular words
$product = array_slice($count, 0, 6);
// print product
var_dump(implode(' ', array_keys($product)));
?>

出力は次のとおりです。

tkg rwd 1008 jk - bouilloire
于 2012-02-03T19:25:14.777 に答える
0

皆さんが持ってきたいくつかのアイデアを実装するための最初の試み。

class ProductNameExtraction {

    private $brandName = NULL;
    private $categoryName = NULL;

    private $modelName = NULL;

    /**
      * @param $A Array of string discribing the same product
      */
    public function __construct($A, $brandName, $categoryName) {
        $this->brandName = $brandName;
        $this->categoryName = $categoryName;

        $res = array();     
        foreach ($A as $k => $title) {
            $res[] = $this->cleanTitle($title);
        }

        $this->modelName = $this->computeProductName($res);
    }

    public function getModelName() {
        return $this->modelName;
    }

    private function computeProductName($A) {
        $s = NULL;

        foreach ($A as $k => $title) {
            $s .= $title . ' ';
        }
        $s = trim($s);

        $data = explode(' ', $s);

        // count most popular words
        $count = array_count_values($data);

        // Remove brand & category names
        unset($count[$this->cleanTitle($this->brandName)]);
        unset($count[$this->cleanTitle($this->categoryName)]);

        $s = '';
        $totalnb = sizeof($A);          
        foreach ($count as $k => $val) {
            if ($val / $totalnb > 0.5) {
                $s .= $k . ' ';
            }
        }

        return $s;
    }

    private function cleanTitle($title) {
        // Remove extra spaces
        $title = trim($title);
        $title = preg_replace('/\s\s+/', ' ', $title);

        // Remove noise
        $title = str_replace(' - ', ' ', $title);
        $title = str_replace(array("\r\n", "\n", "\r"), ' ', $title);

        return strtoupper($title);
    }

}
于 2012-02-04T09:42:09.787 に答える