-
Notifications
You must be signed in to change notification settings - Fork 0
Trieを用いた絵文字判定の実装案 #1
Comments
ありがとうございます。動作することを確認しました。データセットの余分な EmojiData()
{
trieTree = { { false,{} } }; // trieTreeの初期化
const std::vector<std::vector<std::uint32_t>> lines =
{
# include "EmojiCodePoints.txt"
};
for (const auto& line : lines)
{
int currentNode = rootNode; /* 現在のノード番号 */
/* 根からノードの遷移を行い、たどり着いた先のノードに絵文字であるというフラグを立てます。 */
for (const auto& codePoint : line)
{
if (trieTree[currentNode].nxt.find(codePoint) == trieTree[currentNode].nxt.end())
{
/* ノードがない場合には新しくノードを生成する */
trieTree[currentNode].nxt[codePoint] = trieTree.size();
const Node addNode = { false,{} };
trieTree.push_back(addNode);
}
currentNode = trieTree[currentNode].nxt[codePoint];
}
trieTree[currentNode].isEmoji = true;
}
return;
} 実装について、判定速度と拡張性は申し分ないと思いますが、メモリに関しては、Node の std::map 用の内部データの構築のために、単純な sizeof(std::vector) や sizeof(std::map) は通常 16~32 バイトあり、 現状 |
早速、見ていただき、ありがとうございます。 メモリ消費に関しては、指摘されたとおり確かにまだ非効率な点が多いです。 Trieの木構造のメモリ管理にmapを使う代わりに、木構造の簡潔データ構造であるLOUDSを用いればメモリ使用量を減らすことが可能です[1]。
[1] 高速文字列解析の世界―データ圧縮・全文検索・テキストマイニング 岡野原 大輔 (著) |
詳細な方針の検討をありがとうございます。 メモリを一度に連続して確保できるのであれば、多少メモリ消費量が増えても、アクセス効率の観点から 値を辞書順でソートした codePoint データセットは簡単に用意できるため、元データとして |
以前に述べたTrieの簡潔データ構造を実装してみました。
完備辞書(FID)も1ファイルにまとめると、長くなるのでクラス化してファイルを分けました。 コンストラクタを走らせた後 のEmojiData クラスのメモリ使用量を比較しました。
実行中のプロセスを cat /proc/*/status として、 データセグメントにあたる VmData の容量で計測
この実装では、「EmojiCodePoints_SortedByValue.txt」を差し替えるだけでコードの変更をする必要はないです。 EmojiData クラスのコンストラクタで、「"EmojiCodePoints_SortedByValue.txt"」を読み込んでいるのでメモリ使用量のピークは大きいです。 |
実装と検証をありがとうございます。追ってこちらでも検証させていただきます。 |
FIDのリポジトリにMITライセンスを記載しました。 |
ありがとうございます。 |
絵文字判定の実装案として、Trie ( https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4%E6%9C%A8 )を用いるのはどうでしょうか?
Trieは文字列の集合を管理するのに適しているデータ構造です。
具体的には、各ノードが文字列の接頭辞を表しており、ノードの関係が木構造となっています。
時間面
Trieの生成の実行時間は 全絵文字のcodePointの合計に比例します。
絵文字判定の最悪実行時間は、絵文字を構成するcodePointの最大個数(現在では7)で抑えられます。
メモリ面
Trieのノードの個数は最悪で全絵文字のcodePointの合計個数です。
しかし、{0x1F469} と {0x1F469, 0x1F3FF, 0x200D 0x1F692} が絵文字である場合は、
CodePoint の 接頭辞が共通している部分だけノードの個数を減らせるため、 1 つの絵文字につき 1 つの std::vector を用いるよりかはメモリ消費を減らすことが可能だと考えています。
拡張面
木構造で管理しているため、codePoint を構成する個数が変更されてもコードの変更をする必要がないと考えられます。
以下のソースコードは、Trieを用いた絵文字判定の実装例です。
ここでは、木構造の子供の管理にmapを用いています。
注意の欄から絵文字と判断される場合には、最長のcodePointで構成される絵文字にマッチングすると仮定しています。
このソースコードを参考にする場合、「EmojiCodePoints.txt」からcodePointを抽出する部分の実装が甘いので、書き換える必要があると思います。
The text was updated successfully, but these errors were encountered: