2

私は最近、n-gram と、テキスト本文内のフレーズの頻度を n-gram と比較する素晴らしい可能性について知りました。現在、テキスト本文を取得し、最も頻繁に使用されるフレーズのリストを返す vb.net アプリを作成しようとしています (n >= 2)。

テキスト本文から n-gram を生成する方法の C# の例を見つけたので、コードを VB に変換することから始めました。問題は、このコードでは単語ごとに 1 グラムではなく、文字ごとに 1 グラムが作成されることです。単語に使用したい区切り文字は、VbCrLf (改行)、vbTab (タブ)、および次の文字です: !@#$%^&*()_+-={}|\:\"'?¿ /.,<>'¡º×÷';«»[]

この目的のために次の関数を書き直す方法を知っている人はいますか?

   Friend Shared Function GenerateNGrams(ByVal text As String, ByVal gramLength As Integer) As String()
    If text Is Nothing OrElse text.Length = 0 Then
        Return Nothing
    End If

    Dim grams As New ArrayList()
    Dim length As Integer = text.Length
    If length < gramLength Then
        Dim gram As String
        For i As Integer = 1 To length
            gram = text.Substring(0, (i) - (0))
            If grams.IndexOf(gram) = -1 Then
                grams.Add(gram)
            End If
        Next

        gram = text.Substring(length - 1, (length) - (length - 1))
        If grams.IndexOf(gram) = -1 Then
            grams.Add(gram)

        End If
    Else
        For i As Integer = 1 To gramLength - 1
            Dim gram As String = text.Substring(0, (i) - (0))
            If grams.IndexOf(gram) = -1 Then
                grams.Add(gram)

            End If
        Next

        For i As Integer = 0 To (length - gramLength)
            Dim gram As String = text.Substring(i, (i + gramLength) - (i))
            If grams.IndexOf(gram) = -1 Then
                grams.Add(gram)
            End If
        Next

        For i As Integer = (length - gramLength) + 1 To length - 1
            Dim gram As String = text.Substring(i, (length) - (i))
            If grams.IndexOf(gram) = -1 Then
                grams.Add(gram)
            End If
        Next
    End If
    Return Tokeniser.ArrayListToArray(grams)
End Function
4

2 に答える 2

2

単語のnグラムは、これらの単語を格納する長さnの単なるリストです。nグラムのリストは、単に単語のリストのリストになります。頻度を保存したい場合は、これらのnグラムで索引付けされた辞書が必要です。2グラムの特殊なケースでは、次のようなものを想像できます。

Dim frequencies As New Dictionary(Of String(), Integer)(New ArrayComparer(Of String)())
Const separators as String = "!@#$%^&*()_+-={}|\:""'?¿/.,<>’¡º×÷‘;«»[] " & _
                             ControlChars.CrLf & ControlChars.Tab
Dim words = text.Split(separators.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)

For i As Integer = 0 To words.Length - 2
    Dim ngram = New String() { words(i), words(i + 1) }
    Dim oldValue As Integer = 0
    frequencies.TryGetValue(ngram, oldValue)
    frequencies(ngram) = oldValue + 1
Next

frequenciesこれで、テキストに含まれる2つの連続する単語のペアすべてと、それらが(連続するペアとして)表示される頻度を含む辞書が含まれるはずです。

このコードには次のArrayComparerクラスが必要です。

Public Class ArrayComparer(Of T)
    Implements IEqualityComparer(Of T())

    Private ReadOnly comparer As IEqualityComparer(Of T)

    Public Sub New()
        Me.New(EqualityComparer(Of T).Default)
    End Sub

    Public Sub New(ByVal comparer As IEqualityComparer(Of T))
        Me.comparer = comparer
    End Sub

    Public Overloads Function Equals(ByVal a As T(), ByVal b As T()) As Boolean _
            Implements IEqualityComparer(Of T()).Equals
        System.Diagnostics.Debug.Assert(a.Length = b.Length)
        For i As Integer = 0 to a.Length - 1
            If Not comparer.Equals(a(i), b(i)) Then Return False
        Next

        Return True
    End Function

    Public Overloads Function GetHashCode(ByVal arr As T()) As Integer _
            Implements IEqualityComparer(Of T()).GetHashCode
        Dim hashCode As Integer = 17
        For Each obj As T In arr
            hashCode = ((hashCode << 5) - 1) Xor comparer.GetHashCode(obj)
        Next

        Return hashCode
    End Function
End Class

EqualityComparer残念ながら、VBコンパイラにはジェネリッククラスの検索に問題があるため、このコードはMonoでコンパイルされません。したがって、implementationwが期待どおりに機能するかどうかをテストすることはできませんGetHashCodeが、問題はないはずです。

于 2010-03-10T16:36:54.163 に答える