見出し画像

〚関心〛のスコア化方法|22年ライフログ研究(論文解説①)【第4話】

2004年1月10日から22年間、
私は日記やチャットのログを記録し続けてきました。
総文字数は約1550万文字。

第3話では、「関心の変化」の可視化に関する研究を学術論文としてまとめ、
公開したことを書きました


今回は、その裏側
この膨大なテキストデータを、どのように「関心スコア」に変換しているのかを整理します。


■ なぜ「スコア化」が必要なのか

22年分のログは、読み返せばエピソードは見つかります。
しかし、全体傾向は見えません。

20代友人の話が多かった気がする」
 (なんとなくだけど)
30代子どもの話題が増えた気がする」
 (なんとなくだけど)

こうした感覚を
可視化・スコア化しデータ分析しました。

22年分の記憶を、たった1行のコードで検索し、偏差値で可視化する快感が得られます。


(図)ライフログから関心をスコア化する著者

■分析に使用した生ログ

私自身が18~40歳(2004~2025年)の22年間に記録した個人ライフログ(チャットログ,日記等,総量約1550万文字)を使用しました。

10万字小説換算で小説155冊分に相当します
このライフログは日付単位で整理されています。

 対象:2004/1/10~2025/8/20(7863日分)
 平均:1,966字/日
 最大:77,308字/日
 欠損:16.56%
 ※欠測日のスコアについては,前7日間の加重移動平均により補正。

なお、ログ量は日ごとに大きなばらつきがあります。


■生ログの統合作業(下処理)

私のライフログは約4000ファイルに渡り、保存形式もバラバラでした。
このため、生ログデータを、Python3系で21種のコードを用いて、
約3000万セル分(35.5万行×80列)の1ファイルに統合しました。
非常に大変
さらに、「形態素解析(Janome)」により、生ログを単語ごとに区切りました(こちらは難しいので詳細は省略)。

生ログ統合(下処理)イメージ
保存していたログ(一部)
# 実際に使用したコードの一部を掲載します(簡略化)。
# chat_log_parser.py
import re # ★この行をファイルの先頭に追加します★
file_path = "20050112.txt"
try:
    with open(file_path, 'r', encoding='cp932') as f:
        first_line = f.readline()
        log_date = first_line[8:18] # 例: '2005/01/12'
        print(f"抽出した日付: {log_date}\n")
        print("----- ここから各メッセージの抽出結果 -----")
        all_chat_messages = []
        chat_line_pattern = re.compile(r'^(\d{2}:\d{2})\s+\((.*?)\)\s*(.*)$')
        for line in f:
            stripped_line = line.strip() # 行頭・行末の空白や改行を削除
            if not stripped_line: # 空白行はスキップ
                continue
            match = chat_line_pattern.match(stripped_line)
            if match:
                time = match.group(1)      # グループ1: 時刻
                speaker = match.group(2)   # グループ2: 話者
                message = match.group(3)   # グループ3: メッセージ本文
                all_chat_messages.append({
                    'Date': log_date,
                    'Time': time,
                    'Speaker': speaker,
                    'Message': message
                })
                print(f"日付: {log_date}, 時刻: {time}, 話者: {speaker}, メッセージ: {message}")
            else:
                print(f"警告: パターンにマッチしない行をスキップしました -> {stripped_line}")
        print(f"\n全{len(all_chat_messages)}件のメッセージをリストに格納しました。")
except FileNotFoundError:
    print(f"エラー: ファイル '{file_path}' が見つかりません。")
except Exception as e:
    print(f"ファイルの読み込み中にエラーが発生しました: {e}")

■関心スコア化

関心項目に関するキーワード辞書として、
 ・分類語彙表(国立国語研究所,2018)
 ・日本語WordNet(情報通信研究機構,2010)
 ・科学技術用語形態素解析辞書(科学技術振興機構,2015)

による関心キーワード辞書を作成しました。

これを用い、形態素解析済のログの各項目キーワードの日別出現頻度を算出し、「関心スコア」としました。
 (語数:28,593語。スコア:71,219点

# 実際に使用したコードの一部を掲載します(簡略化)。
import pandas as pd
import re
main_data_path = "C:/Users/●●/chatlog_lifelog/Python/integrated_lifelog_data.csv"
dictionary_path = "C:/Users/●●/99_detail_emotion_word.csv"
try:
    df_integrated = pd.read_csv(main_data_path, encoding='utf-8-sig')
    df_dictionary = pd.read_csv(dictionary_path, encoding='utf-8-sig')
    print("統合データと辞書ファイルを読み込みました。")
    print(f"統合データの行数: {len(df_integrated)}行")
    print(f"辞書データの行数: {len(df_dictionary)}行")
    df_integrated['日付'] = pd.to_datetime(df_integrated['日付'], errors='coerce')
    df_dictionary['キーワード'] = df_dictionary['キーワード'].astype(str).fillna('')
except FileNotFoundError as e:
    print(f"エラー: 必要なファイルが見つかりません。パスを確認してください: {e.filename}")
    exit()
except Exception as e:
    print(f"データの読み込み中にエラーが発生しました: {e}")
    exit()
print("\n--- ワード辞書をPythonの辞書形式に変換します ---")
keyword_dict = df_dictionary.groupby('特定ジャンル')['キーワード'].apply(list).to_dict()
text_columns = ['総合テキスト']
print("\n--- 特定キーワード特化スコアの作成を開始します ---")
for genre, keywords in keyword_dict.items():
    pattern = '|'.join(keywords)
        for text_col in text_columns:
        score_col_name = f"{text_col}_{genre}_スコア"
        text_series = df_integrated[text_col].fillna('')
        df_integrated[score_col_name] = text_series.str.count(pattern, flags=re.IGNORECASE)
        print(f"'{genre}'関連スコアの作成が完了しました。")
print("\n--- 新しく作成されたスコア列の最初の5行(例) ---")
score_cols_to_show = [
    '日付', '総合テキスト_ごみ・廃棄物・一廃・産廃_スコア', '総合テキスト_インフレ・値上・物価高騰・物価上昇_スコア'
]
existing_cols_to_show = [col for col in score_cols_to_show if col in df_integrated.columns]
print(df_integrated[existing_cols_to_show].head())
output_path_with_keywords = main_data_path.replace('.csv', '_with_detail_emotion_scores.csv')
df_integrated.to_csv(output_path_with_keywords, index=False, encoding='utf-8-sig')
print(f"\n新しく追加されたスコアを含むデータを '{output_path_with_keywords}' に保存しました。")
print("このデータを今後の分析にご利用ください。")

■ 関心カテゴリの設計

単語をそのまま集計しても意味はありません。
そこで、あらかじめ関心カテゴリ(項目)を設計しました。
関心カテゴリ(項目)は、某市の市民アンケートと同じ項目にしました。
(そうすれば、市民アンケートとの比較が可能になるため

<関心項目(例)>
子ども、家族 友人、知人 住宅、土地、お金・財産、
健康、仕事、家事、勉強、老後、生活、趣味・娯楽、
スポーツ・レジャー 、信仰・宗教、政治、ボランティア、地域活動

各単語をこれらのカテゴリに紐づけます。


■ 標準化と偏差値化

ログの量は日によってバラバラです。
普通にやると、たくさん書いた日はスコアが高くなって当然。
そこで「Constant-Sum Scaling」という手法を用い、
その日の全単語に対する各カテゴリの構成比を算出しました。
(統計学では「標準化」と呼ばれます)

さらにこれを22年間の自分と比較して「偏差値」に変換します。
これにより、「22年間の自分史上、今日がどれだけ特別だったか
などのハイライトが浮き彫りになります。

例えば、私は2008年8月21日の「友人」の関心の偏差値は71でした。
その日のログを見返すと、
どうやら、公務員試験に最終合格した日で、友人とその会話をしていました。
(ちなみに、この日の「家族」偏差値は38)

「友人」の関心偏差値71の日のログ抜粋(当時23歳)

--------2008/08/21 00:00:00 ログを開始
2008/8/21 木 19:51 私  ○○市に受かったぞ!
2008/8/21 木 19:52 私  来年から川崎に住みます
2008/8/21 木 19:52 友人 おお
2008/8/21 木 19:52 友人 やったな
2008/8/21 木 19:52 友人 川崎ってどこだ?
2008/8/21 木 19:52 友人 横浜の辺り?
2008/8/21 木 19:52 私  横浜と東京の間。
2008/8/21 木 19:52 私  ギリギリ神奈川県
2008/8/21 木 19:52 友人 なるほど
--------2008/08/22 00:00:00 ログを終了

※匿名加工済
(図)友人偏差値71の日のログを発見した瞬間


■ 限界について

当然ながら、この方法には限界があります。

  • 単語辞書設計の恣意性

  • 文脈の無視

  • 皮肉や比喩の扱い

  • データの欠損期間   など

 そのため、これは「厳密な心理測定」ではなく、探索的な可視化手法と位置づけています。


■生ログ逆参照(トレーサビリティ)の可能性

スコア妥当性検証として、関心偏差値が高い特定期間の生ログを逆参照し、日時ID、生ログID、感情スコアID、各関心スコアIDをキーに、対象日前後7日の生ログを確認しました。

第1話でも触れましたが、例えば、2009年8月4日の週は「友人」偏差値91異常値であり、22年間で偏差値80以上の週は11回のみでした。

これは統計学上は単なる異常値(外れ値)ですが、
ライフログにおいては、決して単なる数値ではなく
忘れていた親友との熱い会話を、20年越しに発掘してくれた瞬間
です。

「友人」偏差値の22年分スコア(週平均)


偏差値の高い日は、いずれも非常に濃い会話(会話例「鳥肌立つ展開」など)が繰り広げられてました。
つまり、生ログ逆参照(トレーサビリティ手法)を活用することで、文脈要因追跡の手がかりを得ることが可能です。

なお、高関心+高感情(ポジティブ発言)を抽出すれば「負の異常値」を回避することも可能です。

従来の統計分析(マクロ分析)では、異常値は「外れ値」として除去され、また、生ログの逆参照も不可能でした。

ですが、個人ログ(N=1)においては、異常値は関心が跳ねる瞬間であり、行動変容やパーソナライズの起点として価値が高く、こうした異常値こそ探索の起点や要因理解となり得ることが示唆されました。


■ 未来への展望

これはまだ仮説段階ですが、
RAG(Retrieval-Augmented Generation)やAIエージェントの進展は、ライフログを個人の検索可能な資源として扱う流れ(Gurrin et al.,2014)とも親和性が高く、本稿で示したN=1研究の再現性と蓄積可能性を高める基盤技術として期待されます。

また、本研究で試みた日別生ログの逆参照によるトレーサビリティを発展させることで、N=1データの長期保存と高精度な文脈抽出を組み合わせた介入設計の枠組みが構想し得ると考えています。

例えば今後、「ログは財産」という考え方の下で、N=1ログ中の「関心の源泉」をキーワード分析にとどまらずRAG等で文脈的に掘り起こし、個人の内発的動機付けを促す介入も考えられます。

こうしたAIによる介入モデルと本稿のモデルを組み合わせ、人々の関心の維持・拡張に対する効果を実証的に検討することは、社会情報学における今後の重要な課題の一つとなり得ると考えています。

AIとRAGが進化した将来、あらゆる「ログは財産」になり得る?


■次回【第5話】

次回は、「関心」とは別の、もう一つの軸である「感情スコア」の算出方法です。
関心と感情は、似ているようで、
実はまったく異なる動きをします。

▼第5話「感情」のスコア化方法


▼本シリーズの起点【第1話】

 https://note.com/lifelog_lab/n/n2f55c09c19bb


もしよろしければ「フォロー」と「スキ」をいただけると、
とても励みになります。


▼日本ライフログ研究所 │ 公式サイト

・公式サイトURL:
 https://wide-spirit-498.notion.site/346b4484a04880e8b4b7dbd94f9e602a


いいなと思ったら応援しよう!