File size: 6,612 Bytes
945c653
 
 
 
5e17d42
dfa90ba
45939fa
 
dfa90ba
5e17d42
 
45939fa
 
 
 
 
 
 
5e17d42
 
45939fa
 
 
 
 
 
 
5e17d42
 
45939fa
 
 
5e17d42
dfa90ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt


# ========== Mock 词频函数(避免 HuggingFace 下载大语料) ==========
def get_freq(expr):
    expr = expr.lower().replace(" ", "_")
    return (abs(hash(expr)) % 5000) + 50


# ========== E 曲线:固着(Entrenchment) ==========
def entrenchment_real(freq_val):
    x = np.linspace(0, 10, 200)
    strength = min(2.0, 0.5 + np.log(freq_val + 1) / 4)
    shift = 5
    y = 1 / (1 + np.exp(-strength * (x - shift)))
    return x, y


# ========== C 曲线:常规化(Conventionalization) ==========
def conventionalization_real(freq_val):
    x = np.linspace(0, 10, 200)
    spread = min(2.0, 0.4 + np.log(freq_val + 1) / 5)
    shift = 4
    y = 1 / (1 + np.exp(-spread * (x - shift)))
    return x, y


# ===================== 单表达分析 =====================
def analyze_ec(expr):
    f = get_freq(expr)

    entrenchment_text = (
        "### Entrenchment(固着)\n"
        f"表达 **'{expr}'** 的模拟语料频次为:**{f} 次**。\n\n"
        "词频越高,固着曲线越陡峭,越容易在个体大脑中形成自动化加工。\n"
    )

    conventionalization_text = (
        "### Conventionalization(常规化)\n"
        "高频表达更容易在社群中传播与扩散,因此常规化曲线会更早上升、扩散更快。\n"
    )

    summary = (
        "### 综合解释\n"
        f"表达 **'{expr}'** 的频率为 **{f}**。高频使用会带来:\n\n"
        "- 更快的固着(E)→ 心理加工速度更快;\n"
        "- 更快的常规化(C)→ 社群接受与扩散更快;\n\n"
        "这反映了 Schmid E&C 模型的核心:语言使用频率驱动固着与常规化共同形成语言系统的稳定性。"
    )

    # --- E 曲线 ---
    x1, y1 = entrenchment_real(f)
    fig_e = plt.figure(figsize=(4.5, 3.2))
    plt.plot(x1, y1, linewidth=2)
    plt.title("Entrenchment Curve")
    plt.xlabel("Usage Frequency")
    plt.ylabel("Cognitive Strength")
    plt.tight_layout()

    # --- C 曲线 ---
    x2, y2 = conventionalization_real(f)
    fig_c = plt.figure(figsize=(4.5, 3.2))
    plt.plot(x2, y2, linewidth=2, color="#ff8c42")
    plt.title("Conventionalization Curve")
    plt.xlabel("Time / Spread")
    plt.ylabel("Community Adoption")
    plt.tight_layout()

    return entrenchment_text + "\n" + conventionalization_text, fig_e, fig_c, summary


# ===================== 双表达对比 =====================
def compare_two(expr1, expr2):
    f1 = get_freq(expr1)
    f2 = get_freq(expr2)

    # --- E 对比 ---
    xA, yA = entrenchment_real(f1)
    xB, yB = entrenchment_real(f2)

    fig_e = plt.figure(figsize=(5, 3.5))
    plt.plot(xA, yA, linewidth=2, label=f"{expr1} (freq={f1})")
    plt.plot(xB, yB, linewidth=2, label=f"{expr2} (freq={f2})")
    plt.title("Entrenchment Comparison")
    plt.legend()
    plt.tight_layout()

    # --- C 对比 ---
    xC1, yC1 = conventionalization_real(f1)
    xC2, yC2 = conventionalization_real(f2)

    fig_c = plt.figure(figsize=(5, 3.5))
    plt.plot(xC1, yC1, linewidth=2, label=f"{expr1} (freq={f1})")
    plt.plot(xC2, yC2, linewidth=2, label=f"{expr2} (freq={f2})")
    plt.title("Conventionalization Comparison")
    plt.legend()
    plt.tight_layout()

    # --- E 差异热力图 ---
    diff = np.abs(yA - yB)[:50].reshape(10, 5)
    fig_h = plt.figure(figsize=(4, 3))
    plt.imshow(diff, cmap="Reds", aspect="auto")
    plt.colorbar(label="Difference")
    plt.title("E Difference Heatmap")
    plt.tight_layout()

    explanation = (
        "### 双表达对比解释\n\n"
        f"两个表达的模拟词频:\n"
        f"- {expr1}: **{f1} 次**\n"
        f"- {expr2}: **{f2} 次**\n\n"
        "#### 1. 固着(E)差异\n"
        "- 高频表达曲线更陡峭 → 更快固着。\n"
        f"- 若 {expr1} 曲线整体高于 {expr2},说明它在认知加工上更自动化。\n\n"
        "#### 2. 常规化(C)差异\n"
        "- 高频表达扩散更快,曲线更左移。\n"
        f"- 若 {expr1} 的扩散曲线高于 {expr2},说明它更容易成为社群惯例。\n\n"
        "#### 3. 热力图解释\n"
        "- 深红表示两表达的固着差异显著。\n"
        "- 浅色表示两表达的固着趋势接近。\n\n"
        "#### 4. 综合结论\n"
        "词频显著影响固着与常规化,体现了 E&C 模型中‘个体认知 × 社群传播’的动态互动机制。"
    )

    return "", fig_e, fig_c, fig_h, explanation


# ===================== UI =====================
with gr.Blocks(
    css="""
    .card {
        background:white;
        padding:15px;
        border-radius:10px;
        box-shadow:0 3px 10px rgba(0,0,0,0.08);
        margin-bottom:12px;
    }
    body {
        background: linear-gradient(135deg,#eef2ff,#e0f2fe);
    }
    """
) as demo:

    gr.Markdown("# 🧠 E&C 模型互动平台(最终稳定版)")

    # ========== 单表达 Tab ==========

    with gr.Tab("单表达分析"):
        expr = gr.Textbox(label="输入表达")
        btn1 = gr.Button("分析")
        out_text = gr.Markdown()
        out_e = gr.Plot()
        out_c = gr.Plot()
        out_sum = gr.Markdown()

        btn1.click(
            analyze_ec,
            inputs=[expr],
            outputs=[out_text, out_e, out_c, out_sum]
        )

    # ========== 双表达 Tab ==========

    with gr.Tab("双表达对比分析"):

        with gr.Row():
            with gr.Column(scale=1):
                gr.HTML("<div class='card'>")
                expr1 = gr.Textbox(label="表达 A")
                expr2 = gr.Textbox(label="表达 B")
                btn2 = gr.Button("开始对比")
                gr.HTML("</div>")

            with gr.Column(scale=2):

                with gr.Row():
                    with gr.Column():
                        gr.HTML("<div class='card'>")
                        cmp_e = gr.Plot()
                        gr.HTML("</div>")

                    with gr.Column():
                        gr.HTML("<div class='card'>")
                        cmp_c = gr.Plot()
                        gr.HTML("</div>")

                gr.HTML("<div class='card'>")
                heatmap = gr.Plot()
                gr.HTML("</div>")

                gr.HTML("<div class='card'>")
                cmp_text = gr.Markdown()
                gr.HTML("</div>")

        _dummy = gr.Textbox(visible=False)

        btn2.click(
            compare_two,
            inputs=[expr1, expr2],
            outputs=[_dummy, cmp_e, cmp_c, heatmap, cmp_text]
        )

demo.launch()