whatpull/neuronface
0
1"""2Biologically-Inspired Brain Network3====================================4 5실제 생물 뇌의 계층 구조를 반영한 네트워크 아키텍처.6 7계층:8 Network (전체 뇌)9 └── Region (뇌 영역: V1, Hippocampus, PFC, ...)10 └── CorticalColumn (피질 기둥: 6개 층으로 구성)11 └── Population (같은 타입 뉴런 집단)12 └── Neuron (단일 LIF 뉴런)13 14반영된 생물학적 원칙:15 ① E/I 비율 80:20 (흥분성/억제성)16 ② 희소 연결 (로컬 ~15%, 영역 간 ~2%)17 ③ 피질 6층 구조 (L2/3, L4, L5, L6)18 ④ 영역 간 피드포워드 + 피드백 연결19 ⑤ 신경조절 상태 (전역 변수)20"""21 22from __future__ import annotations23from dataclasses import dataclass, field24from typing import Dict, List, Optional25from enum import Enum26import random27 28from .neuron import Neuron, Synapse # 앞서 만든 LIF 뉴런29 30 31# ============================================================32# 세포 타입 (Cell Type)33# ============================================================34class CellType(Enum):35 """생물학적 뉴런 타입."""36 EXCITATORY_PYRAMIDAL = "excitatory_pyramidal" # 피라미드 세포 (대부분)37 INHIBITORY_BASKET = "inhibitory_basket" # 바스켓 세포 (빠른 억제)38 INHIBITORY_MARTINOTTI = "inhibitory_martinotti" # 마르티노티 세포 (피드백 억제)39 40 @property41 def is_excitatory(self) -> bool:42 return self.value.startswith("excitatory")43 44 45# ============================================================46# Population: 같은 타입 뉴런 집단47# ============================================================48@dataclass49class Population:50 """동일한 세포 타입의 뉴런 집단 (예: L2/3 층의 피라미드 세포들).51 52 생물학적으로 같은 유전자 발현 프로파일을 공유하는 그룹.53 """54 name: str55 cell_type: CellType56 neurons: List[Neuron] = field(default_factory=list)57 58 def populate(self, n: int, **params) -> "Population":59 """n개의 뉴런을 생성. 타입에 따라 생리학적 파라미터 자동 설정."""60 if self.cell_type == CellType.INHIBITORY_BASKET:61 params.setdefault("tau_m", 10.0) # 빠른 스파이크: 작은 시상수62 elif self.cell_type.is_excitatory:63 params.setdefault("tau_m", 20.0) # 피라미드 세포: 느린 시상수64 65 self.neurons = [66 Neuron(name=f"{self.name}_{i}", **params) for i in range(n)67 ]68 return self69 70 def step(self, t: float, dt: float) -> None:71 for n in self.neurons:72 n.step(t, dt)73 74 75# ============================================================76# 확률적 희소 연결 (sparse connectivity)77# ============================================================78def connect_populations(79 source: Population,80 target: Population,81 probability: float = 0.15, # 생물학적 로컬 연결 확률82 weight_mean: float = 0.5,83 weight_std: float = 0.1,84 delay_mean: float = 1.0,85 delay_std: float = 0.2,86) -> int:87 """두 Population 간 확률적으로 시냅스를 생성.88 89 억제성 source면 자동으로 가중치에 음수 부호 적용.90 Returns: 실제로 생성된 시냅스 수.91 """92 sign = 1.0 if source.cell_type.is_excitatory else -1.093 count = 094 for pre in source.neurons:95 for post in target.neurons:96 if pre is post:97 continue98 if random.random() < probability:99 w = sign * max(0.01, random.gauss(weight_mean, weight_std))100 d = max(0.5, random.gauss(delay_mean, delay_std))101 pre.connect_to(post, weight=w, delay=d)102 count += 1103 return count104 105 106# ============================================================107# CorticalColumn: 6층 피질 기둥108# ============================================================109@dataclass110class CorticalColumn:111 """피질 기둥: 신피질의 반복 단위 (실제 뇌에서는 ~10K-100K 뉴런).112 113 Canonical microcircuit:114 입력(L4) → L2/3 → L5 → 출력115 → L6 → 피드백(시상)116 """117 name: str118 layers: Dict[str, Population] = field(default_factory=dict)119 120 def build_canonical(121 self,122 n_per_layer: int = 100,123 excitatory_ratio: float = 0.8, # 생물학적 E:I = 80:20124 ) -> "CorticalColumn":125 """표준 피질 마이크로회로 구성."""126 n_e = int(n_per_layer * excitatory_ratio)127 n_i = n_per_layer - n_e128 129 # 각 층에 E와 I 집단 생성130 for layer in ["L2_3", "L4", "L5", "L6"]:131 self.layers[f"{layer}_E"] = Population(132 f"{self.name}_{layer}_E", CellType.EXCITATORY_PYRAMIDAL133 ).populate(n_e)134 self.layers[f"{layer}_I"] = Population(135 f"{self.name}_{layer}_I", CellType.INHIBITORY_BASKET136 ).populate(n_i)137 138 # --- 층간 피드포워드 연결 (canonical circuit) ---139 connect_populations(self.layers["L4_E"], self.layers["L2_3_E"], 0.15)140 connect_populations(self.layers["L2_3_E"], self.layers["L5_E"], 0.15)141 connect_populations(self.layers["L5_E"], self.layers["L6_E"], 0.10)142 143 # --- 각 층 내 E↔I 피드백 (E/I 균형) ---144 for layer in ["L2_3", "L4", "L5", "L6"]:145 connect_populations(146 self.layers[f"{layer}_E"], self.layers[f"{layer}_I"], 0.20147 )148 connect_populations(149 self.layers[f"{layer}_I"], self.layers[f"{layer}_E"], 0.50150 )151 152 return self153 154 @property155 def input_layer(self) -> Population:156 """외부 입력이 들어오는 층 (L4)."""157 return self.layers["L4_E"]158 159 @property160 def output_layer(self) -> Population:161 """다른 영역으로 출력하는 층 (L5)."""162 return self.layers["L5_E"]163 164 def step(self, t: float, dt: float) -> None:165 for layer in self.layers.values():166 layer.step(t, dt)167 168 169# ============================================================170# Region: 뇌 영역 (V1, PFC, Hippocampus 등)171# ============================================================172@dataclass173class Region:174 """뇌 영역: 하나의 기능 단위 (여러 피질 기둥으로 구성)."""175 name: str176 function: str = ""177 columns: List[CorticalColumn] = field(default_factory=list)178 179 # 신경조절 상태 (전역 변수)180 dopamine: float = 0.0 # 보상·동기181 acetylcholine: float = 0.0 # 주의·각성182 serotonin: float = 0.0 # 기분·억제183 184 def populate(self, n_columns: int, **kwargs) -> "Region":185 for i in range(n_columns):186 col = CorticalColumn(f"{self.name}_col{i}").build_canonical(**kwargs)187 self.columns.append(col)188 return self189 190 def step(self, t: float, dt: float) -> None:191 for col in self.columns:192 col.step(t, dt)193 194 195# ============================================================196# Network: 최상위 네트워크197# ============================================================198@dataclass199class Network:200 """전체 뇌 네트워크: 영역 간 장거리 연결을 관리."""201 regions: Dict[str, Region] = field(default_factory=dict)202 203 def add_region(self, region: Region) -> "Network":204 self.regions[region.name] = region205 return self206 207 def project(208 self,209 source_name: str,210 target_name: str,211 probability: float = 0.02, # 영역 간 연결은 매우 희소212 weight_mean: float = 0.3,213 delay_mean: float = 5.0, # 긴 축삭으로 인한 지연214 ) -> int:215 """영역 간 장거리 축삭 투사 (long-range projection).216 217 피드포워드 원칙: source의 L5(출력) → target의 L4(입력)218 """219 src, tgt = self.regions[source_name], self.regions[target_name]220 total = 0221 for sc in src.columns:222 for tc in tgt.columns:223 total += connect_populations(224 sc.output_layer, tc.input_layer,225 probability=probability,226 weight_mean=weight_mean,227 delay_mean=delay_mean,228 )229 return total230 231 def step(self, t: float, dt: float) -> None:232 for region in self.regions.values():233 region.step(t, dt)234 235 @property236 def total_neurons(self) -> int:237 return sum(238 len(pop.neurons)239 for region in self.regions.values()240 for col in region.columns241 for pop in col.layers.values()242 )243 244 245# ============================================================246# 데모: 시각 피질 계층 (V1 → V2)247# ============================================================248if __name__ == "__main__":249 random.seed(42)250 251 net = Network()252 253 # V1: 1차 시각피질 (하위 영역, 기본 특징 추출)254 v1 = Region(name="V1", function="primary visual cortex")255 v1.populate(n_columns=4, n_per_layer=100)256 net.add_region(v1)257 258 # V2: 2차 시각피질 (상위 영역, 복합 패턴)259 v2 = Region(name="V2", function="secondary visual cortex")260 v2.populate(n_columns=2, n_per_layer=100)261 net.add_region(v2)262 263 # V1 → V2 피드포워드264 ff = net.project("V1", "V2", probability=0.05)265 # V2 → V1 피드백 (주의·예측)266 fb = net.project("V2", "V1", probability=0.02, weight_mean=0.2)267 268 print(f"총 뉴런 수: {net.total_neurons}")269 print(f"V1 피질 기둥: {len(v1.columns)}")270 print(f"V2 피질 기둥: {len(v2.columns)}")271 print(f"V1 → V2 시냅스: {ff} (feedforward)")272 print(f"V2 → V1 시냅스: {fb} (feedback)")273 274 # 도파민 레벨 조절 예시 (신경조절)275 v1.dopamine = 0.8 # 보상 신호 증가276 277 # 짧은 시뮬레이션 (5ms)278 dt = 0.1279 for step in range(50):280 net.step(step * dt, dt)281 print("시뮬레이션 완료 ✓")282 