Update app.py
Browse files
app.py
CHANGED
|
@@ -3,17 +3,15 @@ import numpy as np
|
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
| 5 |
|
| 6 |
-
# ========== Mock
|
| 7 |
-
# 你之后可以换成真实语料版本
|
| 8 |
def get_freq(expr):
|
| 9 |
expr = expr.lower().replace(" ", "_")
|
| 10 |
-
return (abs(hash(expr)) % 5000) + 50
|
| 11 |
|
| 12 |
|
| 13 |
# ========== E 曲线:固着(Entrenchment) ==========
|
| 14 |
def entrenchment_real(freq_val):
|
| 15 |
x = np.linspace(0, 10, 200)
|
| 16 |
-
# 高频 → 更陡
|
| 17 |
strength = min(2.0, 0.5 + np.log(freq_val + 1) / 4)
|
| 18 |
shift = 5
|
| 19 |
y = 1 / (1 + np.exp(-strength * (x - shift)))
|
|
@@ -23,7 +21,6 @@ def entrenchment_real(freq_val):
|
|
| 23 |
# ========== C 曲线:常规化(Conventionalization) ==========
|
| 24 |
def conventionalization_real(freq_val):
|
| 25 |
x = np.linspace(0, 10, 200)
|
| 26 |
-
# 高频 → 扩散更快
|
| 27 |
spread = min(2.0, 0.4 + np.log(freq_val + 1) / 5)
|
| 28 |
shift = 4
|
| 29 |
y = 1 / (1 + np.exp(-spread * (x - shift)))
|
|
@@ -34,20 +31,175 @@ def conventionalization_real(freq_val):
|
|
| 34 |
def analyze_ec(expr):
|
| 35 |
f = get_freq(expr)
|
| 36 |
|
| 37 |
-
entrenchment_text =
|
| 38 |
-
### Entrenchment
|
| 39 |
-
表达
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
conventionalization_text =
|
| 44 |
-
### Conventionalization
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
summary =
|
| 49 |
-
###
|
| 50 |
-
|
| 51 |
-
-
|
| 52 |
-
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
| 5 |
|
| 6 |
+
# ========== Mock 词频函数(避免 HuggingFace 下载大语料) ==========
|
|
|
|
| 7 |
def get_freq(expr):
|
| 8 |
expr = expr.lower().replace(" ", "_")
|
| 9 |
+
return (abs(hash(expr)) % 5000) + 50
|
| 10 |
|
| 11 |
|
| 12 |
# ========== E 曲线:固着(Entrenchment) ==========
|
| 13 |
def entrenchment_real(freq_val):
|
| 14 |
x = np.linspace(0, 10, 200)
|
|
|
|
| 15 |
strength = min(2.0, 0.5 + np.log(freq_val + 1) / 4)
|
| 16 |
shift = 5
|
| 17 |
y = 1 / (1 + np.exp(-strength * (x - shift)))
|
|
|
|
| 21 |
# ========== C 曲线:常规化(Conventionalization) ==========
|
| 22 |
def conventionalization_real(freq_val):
|
| 23 |
x = np.linspace(0, 10, 200)
|
|
|
|
| 24 |
spread = min(2.0, 0.4 + np.log(freq_val + 1) / 5)
|
| 25 |
shift = 4
|
| 26 |
y = 1 / (1 + np.exp(-spread * (x - shift)))
|
|
|
|
| 31 |
def analyze_ec(expr):
|
| 32 |
f = get_freq(expr)
|
| 33 |
|
| 34 |
+
entrenchment_text = (
|
| 35 |
+
"### Entrenchment(固着)\n"
|
| 36 |
+
f"表达 **'{expr}'** 的模拟语料频次为:**{f} 次**。\n\n"
|
| 37 |
+
"词频越高,固着曲线越陡峭,越容易在个体大脑中形成自动化加工。\n"
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
conventionalization_text = (
|
| 41 |
+
"### Conventionalization(常规化)\n"
|
| 42 |
+
"高频表达更容易在社群中传播与扩散,因此常规化曲线会更早上升、扩散更快。\n"
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
summary = (
|
| 46 |
+
"### 综合解释\n"
|
| 47 |
+
f"表达 **'{expr}'** 的频率为 **{f}**。高频使用会带来:\n\n"
|
| 48 |
+
"- 更快的固着(E)→ 心理加工速度更快;\n"
|
| 49 |
+
"- 更快的常规化(C)→ 社群接受与扩散更快;\n\n"
|
| 50 |
+
"这反映了 Schmid E&C 模型的核心:语言使用频率驱动固着与常规化共同形成语言系统的稳定性。"
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
# --- E 曲线 ---
|
| 54 |
+
x1, y1 = entrenchment_real(f)
|
| 55 |
+
fig_e = plt.figure(figsize=(4.5, 3.2))
|
| 56 |
+
plt.plot(x1, y1, linewidth=2)
|
| 57 |
+
plt.title("Entrenchment Curve")
|
| 58 |
+
plt.xlabel("Usage Frequency")
|
| 59 |
+
plt.ylabel("Cognitive Strength")
|
| 60 |
+
plt.tight_layout()
|
| 61 |
+
|
| 62 |
+
# --- C 曲线 ---
|
| 63 |
+
x2, y2 = conventionalization_real(f)
|
| 64 |
+
fig_c = plt.figure(figsize=(4.5, 3.2))
|
| 65 |
+
plt.plot(x2, y2, linewidth=2, color="#ff8c42")
|
| 66 |
+
plt.title("Conventionalization Curve")
|
| 67 |
+
plt.xlabel("Time / Spread")
|
| 68 |
+
plt.ylabel("Community Adoption")
|
| 69 |
+
plt.tight_layout()
|
| 70 |
+
|
| 71 |
+
return entrenchment_text + "\n" + conventionalization_text, fig_e, fig_c, summary
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# ===================== 双表达对比 =====================
|
| 75 |
+
def compare_two(expr1, expr2):
|
| 76 |
+
f1 = get_freq(expr1)
|
| 77 |
+
f2 = get_freq(expr2)
|
| 78 |
+
|
| 79 |
+
# --- E 对比 ---
|
| 80 |
+
xA, yA = entrenchment_real(f1)
|
| 81 |
+
xB, yB = entrenchment_real(f2)
|
| 82 |
+
|
| 83 |
+
fig_e = plt.figure(figsize=(5, 3.5))
|
| 84 |
+
plt.plot(xA, yA, linewidth=2, label=f"{expr1} (freq={f1})")
|
| 85 |
+
plt.plot(xB, yB, linewidth=2, label=f"{expr2} (freq={f2})")
|
| 86 |
+
plt.title("Entrenchment Comparison")
|
| 87 |
+
plt.legend()
|
| 88 |
+
plt.tight_layout()
|
| 89 |
+
|
| 90 |
+
# --- C 对比 ---
|
| 91 |
+
xC1, yC1 = conventionalization_real(f1)
|
| 92 |
+
xC2, yC2 = conventionalization_real(f2)
|
| 93 |
+
|
| 94 |
+
fig_c = plt.figure(figsize=(5, 3.5))
|
| 95 |
+
plt.plot(xC1, yC1, linewidth=2, label=f"{expr1} (freq={f1})")
|
| 96 |
+
plt.plot(xC2, yC2, linewidth=2, label=f"{expr2} (freq={f2})")
|
| 97 |
+
plt.title("Conventionalization Comparison")
|
| 98 |
+
plt.legend()
|
| 99 |
+
plt.tight_layout()
|
| 100 |
+
|
| 101 |
+
# --- E 差异热力图 ---
|
| 102 |
+
diff = np.abs(yA - yB)[:50].reshape(10, 5)
|
| 103 |
+
fig_h = plt.figure(figsize=(4, 3))
|
| 104 |
+
plt.imshow(diff, cmap="Reds", aspect="auto")
|
| 105 |
+
plt.colorbar(label="Difference")
|
| 106 |
+
plt.title("E Difference Heatmap")
|
| 107 |
+
plt.tight_layout()
|
| 108 |
+
|
| 109 |
+
explanation = (
|
| 110 |
+
"### 双表达对比解释\n\n"
|
| 111 |
+
f"两个表达的模拟词频:\n"
|
| 112 |
+
f"- {expr1}: **{f1} 次**\n"
|
| 113 |
+
f"- {expr2}: **{f2} 次**\n\n"
|
| 114 |
+
"#### 1. 固着(E)差异\n"
|
| 115 |
+
"- 高频表达曲线更陡峭 → 更快固着。\n"
|
| 116 |
+
f"- 若 {expr1} 曲线整体高于 {expr2},说明它在认知加工上更自动化。\n\n"
|
| 117 |
+
"#### 2. 常规化(C)差异\n"
|
| 118 |
+
"- 高频表达扩散更快,曲线更左移。\n"
|
| 119 |
+
f"- 若 {expr1} 的扩散曲线高于 {expr2},说明它更容易成为社群惯例。\n\n"
|
| 120 |
+
"#### 3. 热��图解释\n"
|
| 121 |
+
"- 深红表示两表达的固着差异显著。\n"
|
| 122 |
+
"- 浅色表示两表达的固着趋势接近。\n\n"
|
| 123 |
+
"#### 4. 综合结论\n"
|
| 124 |
+
"词频显著影响固着与常规化,体现了 E&C 模型中‘个体认知 × 社群传播’的动态互动机制。"
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
return "", fig_e, fig_c, fig_h, explanation
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
# ===================== UI =====================
|
| 131 |
+
with gr.Blocks(
|
| 132 |
+
css="""
|
| 133 |
+
.card {
|
| 134 |
+
background:white;
|
| 135 |
+
padding:15px;
|
| 136 |
+
border-radius:10px;
|
| 137 |
+
box-shadow:0 3px 10px rgba(0,0,0,0.08);
|
| 138 |
+
margin-bottom:12px;
|
| 139 |
+
}
|
| 140 |
+
body {
|
| 141 |
+
background: linear-gradient(135deg,#eef2ff,#e0f2fe);
|
| 142 |
+
}
|
| 143 |
+
"""
|
| 144 |
+
) as demo:
|
| 145 |
+
|
| 146 |
+
gr.Markdown("# 🧠 E&C 模型互动平台(最终稳定版)")
|
| 147 |
+
|
| 148 |
+
# ========== 单表达 Tab ==========
|
| 149 |
+
|
| 150 |
+
with gr.Tab("单表达分析"):
|
| 151 |
+
expr = gr.Textbox(label="输入表达")
|
| 152 |
+
btn1 = gr.Button("分析")
|
| 153 |
+
out_text = gr.Markdown()
|
| 154 |
+
out_e = gr.Plot()
|
| 155 |
+
out_c = gr.Plot()
|
| 156 |
+
out_sum = gr.Markdown()
|
| 157 |
+
|
| 158 |
+
btn1.click(
|
| 159 |
+
analyze_ec,
|
| 160 |
+
inputs=[expr],
|
| 161 |
+
outputs=[out_text, out_e, out_c, out_sum]
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
# ========== 双表达 Tab ==========
|
| 165 |
+
|
| 166 |
+
with gr.Tab("双表达对比分析"):
|
| 167 |
+
|
| 168 |
+
with gr.Row():
|
| 169 |
+
with gr.Column(scale=1):
|
| 170 |
+
gr.HTML("<div class='card'>")
|
| 171 |
+
expr1 = gr.Textbox(label="表达 A")
|
| 172 |
+
expr2 = gr.Textbox(label="表达 B")
|
| 173 |
+
btn2 = gr.Button("开始对比")
|
| 174 |
+
gr.HTML("</div>")
|
| 175 |
+
|
| 176 |
+
with gr.Column(scale=2):
|
| 177 |
+
|
| 178 |
+
with gr.Row():
|
| 179 |
+
with gr.Column():
|
| 180 |
+
gr.HTML("<div class='card'>")
|
| 181 |
+
cmp_e = gr.Plot()
|
| 182 |
+
gr.HTML("</div>")
|
| 183 |
+
|
| 184 |
+
with gr.Column():
|
| 185 |
+
gr.HTML("<div class='card'>")
|
| 186 |
+
cmp_c = gr.Plot()
|
| 187 |
+
gr.HTML("</div>")
|
| 188 |
+
|
| 189 |
+
gr.HTML("<div class='card'>")
|
| 190 |
+
heatmap = gr.Plot()
|
| 191 |
+
gr.HTML("</div>")
|
| 192 |
+
|
| 193 |
+
gr.HTML("<div class='card'>")
|
| 194 |
+
cmp_text = gr.Markdown()
|
| 195 |
+
gr.HTML("</div>")
|
| 196 |
+
|
| 197 |
+
_dummy = gr.Textbox(visible=False)
|
| 198 |
+
|
| 199 |
+
btn2.click(
|
| 200 |
+
compare_two,
|
| 201 |
+
inputs=[expr1, expr2],
|
| 202 |
+
outputs=[_dummy, cmp_e, cmp_c, heatmap, cmp_text]
|
| 203 |
+
)
|
| 204 |
+
|
| 205 |
+
demo.launch()
|