Go_形態素解析
date
Nov 24, 2022
slug
morphologicalAnalysis
status
Published
tags
Golang
type
Post
Place
summary
Golang形態素解析
Golangでも簡単で日本語の形態素解析ができます。(環境構築はGoogle先生にお願いします。)
たまたまネット上の話題に対して、Pythonでポジティブがネガティブが分析しています。いきなりGoで試したい。やりました。
コードの概要
パッケージと定数
package main import ( "fmt" "log" "os" "strings" "github.com/go-gota/gota/dataframe" "github.com/go-gota/gota/series" "github.com/shogo82148/go-mecab " "golang.org/x/text/encoding/japanese" "golang.org/x/text/transform" )
上記のコードは、
main パッケージを使用しています。また、以下のパッケージもインポートされています。fmt:標準出力のためのパッケージ
log:エラーログのためのパッケージ
os:ファイル操作のためのパッケージ
strings:文字列操作のためのパッケージ
github.com/go-gota/gota/dataframe:データフレーム操作のためのパッケージ
github.com/go-gota/gota/series:シリーズ操作のためのパッケージ
github.com/shogo82148/go-mecab:形態素解析のためのパッケージ
golang.org/x/text/encoding/japanese:日本語のエンコーディングのためのパッケージ
golang.org/x/text/transform:テキストの変換のためのパッケージ
const BOSEOS = "BOS/EOS"
BOSEOS は定数として定義されています。この定数は、形態素解析結果の特徴の先頭にある特別なタグを表しています。構造体
type NodeInfo struct { Surface string POS string POS1 string POS2 string BaseForm string PN float64 }
NodeInfo 構造体は、形態素解析結果のノード情報を格納するために使用されます。各フィールドは以下のような情報を保持します。Surface:表層形(文字列)
POS:品詞(文字列)
POS1:品詞細分類1(文字列)
POS2:品詞細分類2(文字列)
BaseForm:基本形(文字列)
PN:PN値(浮動小数点数)
type OutInfo struct { id string text string Pn float64 }
OutInfo 構造体は、解析結果を格納するために使用されます。各フィールドは以下のような情報を保持します。id:ID(文字列)
text:テキスト(文字列)
Pn:PN値(浮動小数点数)
main 関数
func main() { tagger, _ := mecab.New(map[string]string{"output-format-type": "wakati"}) defer tagger.Destroy() text := "見えない" dicList, err := parseToNode(tagger, text) if err != nil { log.Fatal(err) } fmt.Println(dicList) dfc := dataframe.LoadStructs(dicList ) meand := dfc.Col("PN").Mean() oinfs := []OutInfo{} oinfs = append(oinfs, OutInfo{ id: "1", text: text, Pn: meand, }) for _, v := range oinfs { fmt.Printf("%s\t%f\n", v.text, v.Pn) } }
main 関数はプログラムのエントリーポイントです。以下の処理を行います。mecab.New関数を使用して形態素解析器(tagger)を作成します。また、deferステートメントを使用して関数終了時にtagger.Destroy()を呼び出し、解放処理を行います。
- 解析対象のテキスト(
text)を定義します。
parseToNode関数を呼び出して形態素解析を行い、解析結果をdicListに格納します。
- 解析結果を表示します。
dataframe.LoadStructs関数を使用してデータフレーム(dfc)を作成します。
- データフレームの
PN列の平均値を計算し、meandに代入します。
- 解析結果を
OutInfoのスライス(oinfs)に追加します。
oinfsの要素をループして、テキストと PN 値を表示します。
形態素解析関数
func parseToNode(m mecab.MeCab, text string) ([]NodeInfo, error) { dicList := make([]NodeInfo, 0) node, err := m.ParseToNode(text) if err != nil { return nil, err } for ; !node.IsZero(); node = node.Next() { if !strings.HasPrefix(node.Feature(), BOSEOS) { fts := strings.Split(node.Feature(), ",") nodeInfo := NodeInfo{ Surface: node.Surface(), POS: fts[0], POS1: fts[1], POS2: fts[2], BaseForm: fts[6], PN: parsePN(node.Surface()), } dicList = append(dicList, nodeInfo) } } return dicList, nil }
parseToNode 関数は、形態素解析を行い、解析結果を NodeInfo のスライスとして返します。引数として形態素解析器(m)と解析対象のテキスト(text)を受け取ります。- 空の
dicListスライスを作成します。
m.ParseToNode関数を使用してテキストを解析し、解析結果の最初のノードを取得します。
- ノードが存在する限り、以下の処理を繰り返します。 -
ノードの特徴を取得し、
BOSEOS で始まっていないかを確認します。- ノードの特徴をカンマで分割し、各フィールドに割り当てます。
NodeInfo構造体を作成し、解析結果の情報をフィールドに格納します。
dicListにNodeInfoを追加します。
- 解析結果の
dicListを返します。
PN分析関数
func parsePN(v string) float64 { f, err := os.Open("pn_ja.csv") defer f.Close() if err != nil { log.Fatal(err) } r := transform.NewReader(f, japanese.ShiftJIS.NewDecoder()) df := dataframe.ReadCSV(r) dfl := df.Filter( dataframe.F{Colname: "A", Comparator: series.Eq, Comparando: v}, ) if dfl.Nrow() == 0 { return 0 } if i, ok := dfl.Col("D").Val(0).(float64); ok { return i } return 0 }
parsePN 関数は、PN値を分析するために使用されます。引数として解析対象の文字列(v)を受け取り、その文字列に対応するPN値を返します。"pn_ja.csv"ファイルを開きます。処理が終了したらdeferステートメントでファイルを閉じます。
- 日本語のシフトJISエンコーディングを使用して、ファイルをテキストとして読み込むための
transform.NewReaderを作成します。
dataframe.ReadCSV関数を使用して、CSVファイルをデータフレーム(df)として読み込みます。
- データフレームのフィルタリングを行い、列
"A"の値が解析対象の文字列と等しい行のみを取得します。
- 取得したデータフレーム(
dfl)の行数が0であれば、PN値は0として返します。
dfl.Col("D").Val(0)を使用して、列"D"の最初の値を取得します。
- 値が浮動小数点数であれば、その値をPN値として返します。そうでなければ、0を返します。
以上、です!