Chapter 3 Preprocessing
3.1 前処理
データセットから10%だけ抽出して使用することにします。ここで一部の前処理もやってしまいます。
レビューのテキストについては、あらかじめ形態素解析をすませてから、スペース区切りのテキストとしてデータセットのなかに差し戻しておきます。tidymodelsの枠組みのなかでやってもよいのですが、形態素解析は文字列を分割する処理としてはわりと重いので、個人的には、学習とセットではやらないほうがよいかなと思います。
<- dt |>
corp ::lazy_dt(immutable = TRUE) |>
dtplyr::slice_sample(prop = .1) |>
dplyr::select(
dplyr
review_id, product_category,
verified_purchase,
star_rating, helpful_votes, total_votes,
review_headline, review_body,
review_date|>
) ::mutate(
dplyrproduct_category = forcats::fct_lump(factor(product_category), n = 2),
verified_purchase = factor(verified_purchase),
star_rating = forcats::fct_lump(factor(star_rating), n = 2),
review_len = nchar(review_body),
review_month = factor(lubridate::month(review_date)),
review_wday = factor(lubridate::wday(review_date, label = TRUE))
|>
) ::select(!review_date) |>
dplyr::filter(review_len > 50, review_len < 2000) |>
dplyr::as_tibble() dplyr
ここではMeCab+IPA辞書で解析し、品詞が「助詞・助動詞・記号」である語と、品詞細分類1が「非自立」である語を取り除きます。
<- corp |>
corp ::select(review_id, review_headline, review_body) |>
dplyr::mutate(chunk_id = dplyr::ntile(dplyr::row_number(), 10)) |>
dplyr::group_by(chunk_id) |>
dplyr::group_map(\(df, grp) {
dplyr|>
df ::mutate(
dplyrreview_body = stringi::stri_c(review_headline, review_body, sep = "\n\n") |>
::stri_replace_all_regex("(<br />)", "\n\n") |>
stringi::strj_normalize() |>
audubon::stri_trim_both() |>
stringi::stri_replace_all_regex("[\\d]+", "0")
stringi|>
) ::select(review_id, review_body) |>
dplyr::tokenize(review_body, review_id) |>
gibasa::filter(!gibasa::is_blank(token)) |>
dplyr::prettify(col_select = c("POS1", "POS2", "Original")) |>
gibasa::mutate(token = dplyr::if_else(is.na(Original), token, Original)) |>
dplyr::add_count(doc_id, token) |>
dplyr::mute_tokens(POS1 %in% c("助詞", "助動詞", "記号")) |>
gibasa::mute_tokens(POS2 == "非自立") |>
gibasa::pack()
gibasa|>
}) ::list_rbind() |>
purrr::left_join(
dplyr|>
corp ::select(
dplyr
review_id, product_category,
verified_purchase,
star_rating, helpful_votes, total_votes,
review_len, review_month, review_wday
),by = c("doc_id" = "review_id")
|>
) ::as_tibble() dplyr
3.2 形態素解析の結果の確認
後でtextrecipes::step_tokenfilter
を使って語彙を減らすので、この段階で大体の語彙数を確認します。rsample::initial_split
はとくに何も指定しないと75%を訓練データにするので、コーパス全体の75%くらいについて、語彙数を確認しておきます。
|>
corp ::corpus() %>%
quanteda::corpus_sample(x = ., size = floor(quanteda::ndoc(.) * .75)) |>
quanteda::tokens(what = "fastestword") |>
quanteda::dfm() |>
quanteda::dfm_trim(min_termfreq = 100) |>
quanteda::nfeat() quanteda
## [1] 1901
|>
corp ::corpus() %>%
quanteda::corpus_sample(x = ., size = floor(quanteda::ndoc(.) * .75)) |>
quanteda::tokens(what = "fastestword") |>
quanteda::dfm() |>
quanteda::dfm_trim(min_termfreq = 100) |>
quanteda::textstat_frequency(
quanteda.textstatsn = 20L,
groups = product_category,
force = TRUE
|>
) ::ggdotchart(
ggpubrx = "feature",
y = "frequency",
group = "group",
color = "group",
palette = viridisLite::turbo(3),
add = "segment",
rotate = TRUE
+
) ::theme_bw() ggplot2