英単語間以外の空白を削除したい(正規表現)
英単語間以外の空白を削除したい(正規表現)
最近、スクレイピングで取得していたニュースをもとに文書生成のディープラーニングをできないか検討していてたのですが、テキストデータにある英単語間以外の空白が気になりました。
文書生成する際には、連続する○文字をもとに次の文字を予測するような動きになるので、この日本語間の空白がノイズになっているのではないかと。。
単純に半角と全角の空白文字をReplceで除去してしまえばよいかと思いましたが、こうすると英単語間の空白まで削除してしまいます。なので、あくまで下記のパターンのみ削除したいです。
- 全角文字 + 空白 + 全角文字
- 全角文字 + 空白 + 半角英字
- 半角英字 + 空白 + 全角文字
正規表現の準備
今回はC#でコーディングしていきますが、大半の言語は同じように記載できると思いますので参考にしてみてください。
まずは、先程のパータンを処理するためには、「半角英字」と「それ以外の文字」で分類する必要があります。
逆に言うとそれだけでよいのです!
- 半角英字
- 上記以外の文字
対象となる文字は「a」から「z」と「A」から「Z」です。
これは容易で、「[a-zA-Z]」のように記載することでマッチさせることができます。
「全角文字」というと複雑な書き方を思い浮かべてしまうかもしれないですが、「それ以外の文字」と記載すれば何となく分かるのではないでしょうか。
正規表現の場合「^」をパータンの先頭に記載するだけで十分です。
なので、「[^a-zA-Z]」と記載するだけで完了になります。
上記で「半角英字」と「それ以外の文字」を検知することができるようになりました。
次は、その間にある空白文字を除去する仕組みです。なお、今回は事前にすべて全角空白を半角空白に置換している前提でコーディングをします。
わかりやすくするために例を上げると下記のような文字列を使います。
・私は C# のプログラムを書きます。
まずは、「は」と「C」の間にある空白の取り除きます。なので先程あげた正規表現を使用して、「は C」の文字列をマッチさせます。
なおこのとき、グループ化を使用して「空白文字の1文字前の文字」と「空白文字の1文字後ろの文字」を抽出させておきます。
グループ化を使用した正規表現は下記のようになります。
・(?<endChar>[^A-Za-z]) (?<startChar>[A-Za-z])
これで「空白文字の1文字前の文字」を「endChar」で、「空白文字の1文字後ろの文字」を「startChar」で抽出することが可能になります。 文字を抽出するための正規表現については整理できたので、いよいよコーディングをします。
コーディング
正規表現も整理できたので、コーディングをします。
まずは整理した正規表現をキーとするため、Regexをインスタンス化します。
Regex reg = new Regex("(?<endChar>[^A-Za-z]) (?<startChar>[A-Za-z])");次に正規表現にマッチした部分を抽出しますが、今回は対象文字列から全て除去させたいので繰り返しの実装をします。
繰り返しの実装部分は下記になります。なお対象文字列は変数textとします。
for (Match m = reg.Match(text); m.Success; m = m.NextMatch()) { }最後にマッチした文字列から空白文字を除去します。
やり方は、グループ化しておいた前後の文字を空白なしで結合し、マッチした部分をReplace関数で置換させます。
text = text.Replace(m.Value, m.Groups["endChar"] + "" + m.Groups["startChar"]);これで、不要な空白文字を除去することができました。
一応最後に全体を記載してきます。なお、これは「全角文字 + 空白 + 半角英字」のパターンしか対応できていないので、「[^a-zA-Z]」と「[a-zA-Z]」部分を入れ替えて網羅できるようにします。
Regex reg = new Regex("(?<endChar>[^A-Za-z]) (?<startChar>[A-Za-z])"); for (Match m = reg.Match(text); m.Success; m = m.NextMatch()) { text = text.Replace(m.Value, m.Groups["endChar"] + "" + m.Groups["startChar"]); }
稼働確認
作成した部分を組み込みテストをしてみます。
プログラムの全量は下記になります。Gitにもコード載せておきますので参考にしてみてください。
RemoveWhitespace
using static System.Net.Mime.MediaTypeNames; using System.Text.RegularExpressions; Console.WriteLine("Please input text."); var inputText = Console.ReadLine(); Console.WriteLine("inputText: " + inputText); Regex reg1 = new Regex("(?<endChar>[^A-Za-z]) (?<startChar>[A-Za-z])"); for (Match m = reg1.Match(inputText); m.Success; m = m.NextMatch()) { inputText = inputText.Replace(m.Value, m.Groups["endChar"] + "" + m.Groups["startChar"]); } Regex reg2 = new Regex("(?<endChar>[A-Za-z]) (?<startChar>[^A-Za-z])"); for (Match m = reg2.Match(inputText); m.Success; m = m.NextMatch()) { inputText = inputText.Replace(m.Value, m.Groups["endChar"] + "" + m.Groups["startChar"]); } Regex reg3 = new Regex("(?<endChar>[^A-Za-z]) (?<startChar>[^A-Za-z])"); for (Match m = reg3.Match(inputText); m.Success; m = m.NextMatch()) { inputText = inputText.Replace(m.Value, m.Groups["endChar"] + "" + m.Groups["startChar"]); } Console.WriteLine("outputText: " + inputText);
アプリを起動したらコンソールに書き文字を入力します。
・私は C# のプログラムを書きます。I write a program in C#.
アプリの実行結果は下記です。
これでノイズを除去できるようになりまた。
さいごに
今回はディープラーニングのためのデータからノイズを除去するために、英単語間以外の空白文字を削除するプログラムを作成してみました。
もしかしたらもっと簡単に実装できるのかもしれないですが、自分でコードを書く場合にはこんな感じかなと思います。
ぜひ参考にしてみてください。
今回はこの辺で、ではまた!
コメント
コメントを投稿