Site Search

[Trying out AI persona marketing with NVIDIA DGX Spark]
Episode 1: Overview of the Demo
Episode 2: Selection of the Subjects to be Investigated
Episode 3: Question Generation
Episode 4: Generating and Collecting Responses
Episode 5: Visualizing the Survey Results
Episode 6 Summary

Contents of this story

Finally, we will analyze the results. The analysis will not delve too deeply, but will be limited to visualizing the results.

Retrieving the response results

The following data is read from the JSON file containing the answer results saved in Episode 4.

import os import glob import json from ipywidgets import Dropdown from IPython.display import display from collections import Counter, OrderedDict import matplotlib.pyplot as plt from survey import SurveyResponseList, Survey # 日本語フォントを設定 import matplotlib matplotlib.rc('font', family='Noto Sans CJK JP')
# 調査結果を保存しているJSONファイルをリストアップして、ドロップダウンメニューに表示する # ファイル名にタイムスタンプが入っているため、最近編集されたファイルが上に来るようにソートする sheet_list = sorted(glob.glob(os.path.join(".", "response*.json")), reverse=True) sheet_dict = {os.path.splitext(os.path.basename(f))[0]: f for f in sheet_list} dropdown_widget = Dropdown( options=sheet_dict, description="Survey File:" ) display(dropdown_widget)
This demo is implemented as a Jupyter notebook, so you can use Jupyter Widgets to select the file to load.
# ドロップダウンで選択されたファイルを読み込む file_path = dropdown_widget.value with open(file_path, encoding="utf-8") as f: json_str = json.dumps(json.load(f), ensure_ascii=False) survey_data = SurveyResponseList.model_validate_json(json_str) print(f"Loaded {len(survey_data.survey_responses)} survey responses from {file_path}")
Loaded 1000 survey responses from ./response20260326124854.json

totalling

We will tally which option was selected for each question.

# 各設問の選択肢ごとの選択数をリストで取得する options_res_list = [] for opts in survey_data.survey_responses: options_res_list.append([opt.option for opt in opts.responses])
# 選択肢のリストの整合性をチェックする関数 def check_options(options, num_items=5, num_options=4): if not options: return False if not isinstance(options, list): return False if len(options) != num_items: return False for option in options: if not isinstance(option, int): return False if option < 1 or option > num_options: return False return True
# 整合性の取れていない選択肢のリストを除外する options_res_list = [option for option in options_res_list if check_options(option)] len(options_res_list)
1000
# 設問毎に選択肢の選択数をカウントする selections = list(zip(*options_res_list)) selection_counts = [Counter(selection) for selection in selections] selection_counts
[Counter({2: 523, 1: 360, 3: 94, 4: 23}),
 Counter({1: 761, 2: 154, 3: 49, 4: 36}),
 Counter({1: 629, 4: 162, 3: 147, 2: 62}),
 Counter({3: 652, 2: 346, 1: 2}),
 Counter({3: 874, 4: 117, 2: 5, 1: 4})]

Pie chart display

We will obtain the survey data in order to overlay the question and answer information onto the graph.

# 調査票データの取得 with open("survey.json", encoding="utf-8") as f: json_str = json.dumps(json.load(f), ensure_ascii=False) survey_data = Survey.model_validate_json(json_str)

We will display the graph using the Matploltlib module.

# selection_countsを円グラフで表示する i = 0 for counts, qs in zip(selection_counts, survey_data.questions): print(f"設問 {i + 1}: {qs.question_text}") for opt_num, opt in enumerate(qs.choices): print(f"{opt_num+1}: {opt.text}: {counts.get(opt_num + 1, 0)}") counts = OrderedDict(counts) counts = OrderedDict( sorted(counts.items(), key=lambda x: x[1], reverse=True) ) labels = [f"{rank}位: {opt_num}." + qs.choices[opt_num - 1].text for rank, opt_num in zip(range(1, len(counts) + 1), counts.keys())] values = counts.values() def func(pct, values): pcts = [v / sum(values) * 100 for v in values] indent = "" if (abs(pct - min(pcts)) < 1e-6 and pct < 3.0): indent = "

" return f"{indent}{pct:.1f}%" fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(aspect="equal")) wedges, texts, autotexts = ax.pie( values, autopct=lambda pct: func(pct, values), pctdistance=0.7, textprops=dict(color="w"), startangle=90, counterclock=False ) ax.legend(wedges, labels, title="回答", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1)) plt.setp(autotexts, size=12, weight="bold") ax.set_title(f"設問 {i + 1}: {qs.question_text}") plt.show() i += 1

Example of aggregated results

The results will vary slightly each time you complete the LLM questionnaire as explained in Episode 4.

設問 1: 朝の目覚めに、あなたが思い浮かべる“さわやかさ”はどのシーンですか? 1: 海辺の朝日が水平線から顔を出す瞬間: 360 2: 高原の風が葉を揺らす音と共に吹く瞬間: 523 3: 都会のカフェで、窓の外に映るネオンが光る瞬間: 94 4: 秋の森の中で、落ち葉がカサカサと音を立てる瞬間: 23
設問 2: コンビニで新しいスナックを選ぶとき、どのパッケージが最初に手に取られそうですか? 1: 淡いパステルカラーでシンプルなロゴが配置されたデザイン: 761 2: 鮮やかなネオンカラーとダイナミックなパターンが走るデザイン: 154 3: レトロなイラストと温かみのあるトーンでまとめられたデザイン: 49 4: 黒を基調にメタリックなアクセントが入ったモダンなデザイン: 36
設問 3: 友達と週末に新しいお菓子をシェアするとしたら、どんなシチュエーションが一番楽しいですか? 1: 自然の中でハイキングやピクニックをしながら: 629 2: 屋外フェスやライブで音楽に合わせて: 62 3: カフェでゆっくりおしゃべりしながら: 147 4: 自宅でゲームや映画鑑賞をしながら: 162
設問 4: テレビやSNSで有名人が商品を紹介しているとき、あなたが「信頼できる」と感じるのはどんな雰囲気ですか? 1: 自然体で笑いを交えたユーモラスな雰囲気: 2 2: 自分の経験や感情を率直に語る誠実さ: 346 3: 専門的な知識やスキルを活かした説得力: 652 4: 最新トレンドを先取りするクールさ: 0
設問 5: 新しいスナックを食べるとき、どのような音楽が流れていると最もリラックスできますか? 1: 軽快なポップス: 4 2: リズミカルなヒップホップ: 5 3: 落ち着いたインディー・アコースティック: 874 4: エレガントなジャズやクラシック: 117

Summary of this episode

We've shown you how to visualize the results of LLM's responses using graphs. I imagine it would be possible to go further and investigate the correlation between the person's attributes and their responses, but I'll leave that to the readers.

In the next episode, we will provide an overall summary and an introduction to NVIDIA NeMo Data Designer.

Contact Us