ファジィテクスト(文章/タイトルマッチングクライアントまで、フルのC#
-
09-06-2019 - |
質問
こんにちはが、私が使っている Levenshteins アルゴリズムを取得し距離はソースおよびターゲット文字列になります。
もっ方法を返す値は0から1:
/// <summary>
/// Gets the similarity between two strings.
/// All relation scores are in the [0, 1] range,
/// which means that if the score gets a maximum value (equal to 1)
/// then the two string are absolutely similar
/// </summary>
/// <param name="string1">The string1.</param>
/// <param name="string2">The string2.</param>
/// <returns></returns>
public static float CalculateSimilarity(String s1, String s2)
{
if ((s1 == null) || (s2 == null)) return 0.0f;
float dis = LevenshteinDistance.Compute(s1, s2);
float maxLen = s1.Length;
if (maxLen < s2.Length)
maxLen = s2.Length;
if (maxLen == 0.0F)
return 1.0F;
else return 1.0F - dis / maxLen;
}
この私にとっては不十分です。が必要な複雑なマッチさせる方法を見つける二つの文が書かれています。
例えば私自動的にタグも楽しいオリジナル曲名、歌ゴミのように、 スーパー、品質、 年のように 2007, 2008, etc..etc..また一部のファイルで http://trash..thash..song_name_mp3.mp3, その他は正常である。をしたいと思っているアルゴリズムまでより完全なよ。うものですか?
ここには現在のアルゴ:
/// <summary>
/// if we need to ignore this target.
/// </summary>
/// <param name="targetString">The target string.</param>
/// <returns></returns>
private bool doIgnore(String targetString)
{
if ((targetString != null) && (targetString != String.Empty))
{
for (int i = 0; i < ignoreWordsList.Length; ++i)
{
//* if we found ignore word or target string matching some some special cases like years (Regex).
if (targetString == ignoreWordsList[i] || (isMatchInSpecialCases(targetString))) return true;
}
}
return false;
}
/// <summary>
/// Removes the duplicates.
/// </summary>
/// <param name="list">The list.</param>
private void removeDuplicates(List<String> list)
{
if ((list != null) && (list.Count > 0))
{
for (int i = 0; i < list.Count - 1; ++i)
{
if (list[i] == list[i + 1])
{
list.RemoveAt(i);
--i;
}
}
}
}
/// <summary>
/// Does the fuzzy match.
/// </summary>
/// <param name="targetTitle">The target title.</param>
/// <returns></returns>
private TitleMatchResult doFuzzyMatch(String targetTitle)
{
TitleMatchResult matchResult = null;
if (targetTitle != null && targetTitle != String.Empty)
{
try
{
//* change target title (string) to lower case.
targetTitle = targetTitle.ToLower();
//* scores, we will select higher score at the end.
Dictionary<Title, float> scores = new Dictionary<Title, float>();
//* do split special chars: '-', ' ', '.', ',', '?', '/', ':', ';', '%', '(', ')', '#', '\"', '\'', '!', '|', '^', '*', '[', ']', '{', '}', '=', '!', '+', '_'
List<String> targetKeywords = new List<string>(targetTitle.Split(ignoreCharsList, StringSplitOptions.RemoveEmptyEntries));
//* remove all trash from keywords, like super, quality, etc..
targetKeywords.RemoveAll(delegate(String x) { return doIgnore(x); });
//* sort keywords.
targetKeywords.Sort();
//* remove some duplicates.
removeDuplicates(targetKeywords);
//* go through all original titles.
foreach (Title sourceTitle in titles)
{
float tempScore = 0f;
//* split orig. title to keywords list.
List<String> sourceKeywords = new List<string>(sourceTitle.Name.Split(ignoreCharsList, StringSplitOptions.RemoveEmptyEntries));
sourceKeywords.Sort();
removeDuplicates(sourceKeywords);
//* go through all source ttl keywords.
foreach (String keyw1 in sourceKeywords)
{
float max = float.MinValue;
foreach (String keyw2 in targetKeywords)
{
float currentScore = StringMatching.StringMatching.CalculateSimilarity(keyw1.ToLower(), keyw2);
if (currentScore > max)
{
max = currentScore;
}
}
tempScore += max;
}
//* calculate average score.
float averageScore = (tempScore / Math.Max(targetKeywords.Count, sourceKeywords.Count));
//* if average score is bigger than minimal score and target title is not in this source title ignore list.
if (averageScore >= minimalScore && !sourceTitle.doIgnore(targetTitle))
{
//* add score.
scores.Add(sourceTitle, averageScore);
}
}
//* choose biggest score.
float maxi = float.MinValue;
foreach (KeyValuePair<Title, float> kvp in scores)
{
if (kvp.Value > maxi)
{
maxi = kvp.Value;
matchResult = new TitleMatchResult(maxi, kvp.Key, MatchTechnique.FuzzyLogic);
}
}
}
catch { }
}
//* return result.
return matchResult;
}
この作品は通常のものがある場合、多くのタイトルを一致させる必要があい致---かも必要式ゲートなどが思いつかないの..
アイデア、浮かぶのでしょうか。う方に。Algos?
ようにしているこの状態のセキュリティーソフトで同僚にて掲載しておりましでもできませんので、適切な解決のためにこの問題です。):近似文字列照合アルゴリズム
解決
問題はここがれの区別をすること騒音の言葉を有データ
- Rolling_Stones.Best_of_2003.Wild_Horses.mp3
- スーパー.ます。Wild_Horses.mp3
- Tori_Amos.Wild_Horses.mp3
することですが、辞書のノイズ単語を無視した。るらしい無骨なくなったあのアルゴリズムを識別することができるとバンド/アルバム名およびノイズが得られます。
他のヒント
のようなもってこいのスポットですために有効と考えられる未来。いてのLevenshteinアルゴリズムとして安心してご利用いただける、ほんの少しでもいくつかの非常に効果的なヒューリスティクスの次回のプレゼンテーション:
キーいままでの3または4(または 以上 方法の把握に類似語(Levenshtein距離は一つの方法)、そしてその実例を文字列にしたい試合と同様、調整の価格下落を過大に評価の組み合わせによりそのヒューリスティクスまでも伸ばし最大限に発揮させるための正。それを使用するすべての今後の試合でやるべきく伸びていくことが予想されます。
ユーザーの関与の過程でもベストを提供する場合は、インターフェイスユーザーで追加的に一致することの優先順位が高い結果とな類似する場合には同意できないと最初の選択です。
こちらの抜粋からのリンク先の答えです。場合のために使いたいという任意のコードとしては、会員の方はログインしてくだ前を変換するVBAにC#.
簡単、迅速、非常に有用な指標においてこれを用いた作成した二つの別々の指標を評価する類似性の二つの文字列です。一呼びかけ"valuePhrase"と呼ん"valueWords".valuePhraseのLevenshtein距離の二つのフレーズ、valueWords分割文字列の個々の言葉に基づき、区切り文字などの空間にダッシュ、その他何でもないので、比較し、各単語が他の単語総括として取りまとめました短Levenshtein距離を結ぶせます。基本的に対応できるかどうかの情報を一フレーズは私に含まれるものだと言う..私は数日としてプロジェクトではなく最も効率的な方法での分割文字列に基づく区切り文字.
valueWords,valuePhrase、分割機能:
Public Function valuePhrase#(ByRef S1$, ByRef S2$)
valuePhrase = LevenshteinDistance(S1, S2)
End Function
Public Function valueWords#(ByRef S1$, ByRef S2$)
Dim wordsS1$(), wordsS2$()
wordsS1 = SplitMultiDelims(S1, " _-")
wordsS2 = SplitMultiDelims(S2, " _-")
Dim word1%, word2%, thisD#, wordbest#
Dim wordsTotal#
For word1 = LBound(wordsS1) To UBound(wordsS1)
wordbest = Len(S2)
For word2 = LBound(wordsS2) To UBound(wordsS2)
thisD = LevenshteinDistance(wordsS1(word1), wordsS2(word2))
If thisD < wordbest Then wordbest = thisD
If thisD = 0 Then GoTo foundbest
Next word2
foundbest:
wordsTotal = wordsTotal + wordbest
Next word1
valueWords = wordsTotal
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' SplitMultiDelims
' This function splits Text into an array of substrings, each substring
' delimited by any character in DelimChars. Only a single character
' may be a delimiter between two substrings, but DelimChars may
' contain any number of delimiter characters. It returns a single element
' array containing all of text if DelimChars is empty, or a 1 or greater
' element array if the Text is successfully split into substrings.
' If IgnoreConsecutiveDelimiters is true, empty array elements will not occur.
' If Limit greater than 0, the function will only split Text into 'Limit'
' array elements or less. The last element will contain the rest of Text.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function SplitMultiDelims(ByRef Text As String, ByRef DelimChars As String, _
Optional ByVal IgnoreConsecutiveDelimiters As Boolean = False, _
Optional ByVal Limit As Long = -1) As String()
Dim ElemStart As Long, N As Long, M As Long, Elements As Long
Dim lDelims As Long, lText As Long
Dim Arr() As String
lText = Len(Text)
lDelims = Len(DelimChars)
If lDelims = 0 Or lText = 0 Or Limit = 1 Then
ReDim Arr(0 To 0)
Arr(0) = Text
SplitMultiDelims = Arr
Exit Function
End If
ReDim Arr(0 To IIf(Limit = -1, lText - 1, Limit))
Elements = 0: ElemStart = 1
For N = 1 To lText
If InStr(DelimChars, Mid(Text, N, 1)) Then
Arr(Elements) = Mid(Text, ElemStart, N - ElemStart)
If IgnoreConsecutiveDelimiters Then
If Len(Arr(Elements)) > 0 Then Elements = Elements + 1
Else
Elements = Elements + 1
End If
ElemStart = N + 1
If Elements + 1 = Limit Then Exit For
End If
Next N
'Get the last token terminated by the end of the string into the array
If ElemStart <= lText Then Arr(Elements) = Mid(Text, ElemStart)
'Since the end of string counts as the terminating delimiter, if the last character
'was also a delimiter, we treat the two as consecutive, and so ignore the last elemnent
If IgnoreConsecutiveDelimiters Then If Len(Arr(Elements)) = 0 Then Elements = Elements - 1
ReDim Preserve Arr(0 To Elements) 'Chop off unused array elements
SplitMultiDelims = Arr
End Function
措置の類似性
これら二つのメトリクス、第三るだけで計算の距離は二つの文字列、シリーズの変数で走行可能最適化アルゴリズムを実現するための数。ファジィ文字列マッチングは、ファジィ科学などを直線的に独立したメトリクスの測定文字列の類似性を、既知のセットの文字列のい合わせてのパラメータは、特定のスタイルの文字列をファジィ合。
当初の目標の指標にしたの低い検索の値致を向上の検索値がますますpermuted。に実行不可能な場合、それはかなり簡単に定義を使用し設定の定義の組み、工学の最後の式のようになるとした増加を検索値を結果として望ましい。
ご覧の通り、最後の二つの指標であるファジィ文字列マッチングメトリクス、既に自然な傾向にスコアが低い文字列うに合わせ下の斜め).これ良いですよ。
の応用 の最適化ファジィマッチング、重量の各指標においてなお、アプリケーション毎のファジィ文字列に一致で重量をパラメータとは異なります。式を定義する最終的な点数は単純に組み合わせのメトリクスとそのウェイト:
value = Min(phraseWeight*phraseValue, wordsWeight*wordsValue)*minWeight +
Max(phraseWeight*phraseValue, wordsWeight*wordsValue)*maxWeight + lengthWeight*lengthValue
を最適化アルゴリズム(神経ネットワークはこちらではの離散多次元問題の目標は最大数。作成した機能を検出するの正しい試合毎に設定され、この最終スクリーンショット.カラムまたは連続得点が最も低いスコアを割り当てを文字列にすることを意味したマッチングさせ、部分的に付与されるポイントがある場合は提携のための最も低いスコアの正しい試合の結合文字列です。そして最適です。できるが緑の細胞はカラムでのコミュニケーションをとったの現在行には、ブルースクエア周辺の細胞を行でのコミュニケーションをとった現在のカラムです。のスコアのコーナーでの成功に合う伝えていま最適化問題の最大化.
るように聞こえるようにしたい場合最長の部分文字列。では、例では,二つのファイルのように
ゴミ箱..thash..song_name_mp3.mp3 や ゴミ..spotch..song_name_mp3.mp3
うみも同じです。
ま必要なヒューリスティクスがあります。ひとつのかみの文字列をsoundexに変換します。Soundexの"コーデック"を見るために使用場からの"音"と同じ(しょうえ、電話オペレーター).少しでも目安の音声とmispronunciation半証タスセリの益々の飛躍が期待され.では比較編集距離がられたのがきっかけとなっていない。(公式に使用する名前だけを使います。理由はありませんがが、利用のマッピングの各文字が文字列になります。見 wikipedia 詳しく)
その後、私の提案するsoundexお弦chopれにいくつかの長さのトランシェ(言のように5、10、20)、その後もクラスター内クラスターを使うものように編集距離は最大部分文字列.
あのコミュニケーションも楽しみの仕事をやや関連する問題のDNA配列アライメント検索のための"地sequence alignment)-クラシックアルゴリズム"Needleman-Wunsch"複雑な現代のものもあるので簡単に見つけられます。の考え方は似てGregの答えを行うのではなく、特定との比較をキーワードを探してみて最長の緩やかにマッチングの部分文字列が長い文字列です。
この悲しい場合にのみ目標は、分別の音楽は、正規表現をカバー可能なネーミングスキームでしょう仕事より汎用アルゴリズムです。
があり GitHubレポ 実施されますので、ご了承ください。