股票數據清洗與日K轉換周月年K工具 - 完整功能解析-3

更新 發佈閱讀 41 分鐘
投資理財內容聲明


def detect_pingpong_patterns(day_df: pd.DataFrame, price_col='收盤', threshold=0.4) -> pd.DataFrame:

    # ... (函式內容保持不變) ...

    df = day_df.sort_values('日期').reset_index(drop=True).copy()

    if price_col not in df.columns:

        return pd.DataFrame()

    df['pct_change'] = df[price_col].pct_change()

    rows = []

    for i in range(1, len(df)-1):

        prev_change = df.loc[i, 'pct_change']

        next_change = df.loc[i+1, 'pct_change']

        if pd.notna(prev_change) and pd.notna(next_change):

            if abs(prev_change) > threshold and abs(next_change) > threshold and prev_change * next_change < 0:

                rows.append({

                    '日期(異常日)': df.loc[i, '日期'],

                    '前日收盤': df.loc[i-1, price_col],

                    '當日收盤': df.loc[i, price_col],

                    '次日收盤': df.loc[i+1, price_col],

                    '前日變動(%)': round(prev_change * 100, 2),

                    '次日變動(%)': round(next_change * 100, 2),

                })

    return pd.DataFrame(rows)



def _process_one_file(path: str):

    try:

        df_day = _load_day_clean_full(path)

        # 僅保留 20242025(含起始緩衝)

        df_day = _clip_by_date_range(df_day, col='日期',

                                     start=DATE_START, end=DATE_END, pad_start=DATE_PAD_START)



        stem = Path(path).stem

        raw_id, _ = _parse_id_name(stem)

        cid = _canonical_id(raw_id) # StockID 必須在這裡定義



        if df_day.empty or df_day['日期'].max() < DATE_PAD_START:

            return "SKIP", {'StockID': cid, 'file': Path(path).name,

                            'count': 0, 'reason': 'out_of_range'}, f"{Path(path).name}: out_of_range"



        if SKIP_SUSPECT_STOCK:

            suspects = detect_pingpong_patterns(df_day, threshold=PINGPONG_THRESHOLD)

            if not suspects.empty:

                msg = f"{Path(path).name}: [SKIP_PINGPONG] 命中疑似除權錯位 {len(suspects)} 筆"

                # 將 cid 傳入 payload

                return "SKIP", {'StockID': cid, 'file': Path(path).name, 'count': len(suspects), 'reason': 'suspect_pingpong'}, msg



        # 週//K 轉換

        dfw = _resample_ohlc_with_flags(df_day, 'W'); dfw = _add_period_returns(dfw, 'W'); dfw['成交量'] = dfw['成交量'].astype('float64'); dfw['StockID'] = cid

        dfm = _resample_ohlc_with_flags(df_day, 'M'); dfm = _add_period_returns(dfm, 'M'); dfm['成交量'] = dfm['成交量'].astype('float64'); dfm['StockID'] = cid

        dfy = _resample_ohlc_with_flags(df_day, 'Y'); dfy = _add_period_returns(dfy, 'Y'); dfy['成交量'] = dfy['成交量'].astype('float64'); dfy['StockID'] = cid



        # 週//K 只留 20242025(不需要 pad)

        for _df in (dfw, dfm, dfy):

            _df.dropna(subset=['日期'], inplace=True)

            _df['日期'] = pd.to_datetime(_df['日期']).dt.tz_localize(None)

        dfw = dfw[(dfw['日期'] >= DATE_START) & (dfw['日期'] <= DATE_END)]

        dfm = dfm[(dfm['日期'] >= DATE_START) & (dfm['日期'] <= DATE_END)]

        dfy = dfy[(dfy['日期'] >= DATE_START) & (dfy['日期'] <= DATE_END)]



        return True, (dfw, dfm, dfy), None

    except Exception as e:

        return False, None, f"{Path(path).name}: {e}"



def _split_into_shards(items, shard_size):

    return [items[i:i+shard_size] for i in range(0, len(items), shard_size)] if shard_size > 0 else [items]



def build_wmy_parquets(market_key: str):

    base_dir = LOCAL_BASE if WRITE_MODE in ('A','B') else DRIVE_BASE

    market_abbr = MARKET_ABBR_MAP.get(market_key, market_key.replace('-share','').upper())



    # 1) 本地快取

    local_dayk_dir = _prepare_local_dayk(market_key)

    if not local_dayk_dir:

        return None, None, None



    # 2) 輸出路徑

    out_week  = f"{base_dir}/{market_key}/weekK_{market_abbr}.parquet"

    out_month = f"{base_dir}/{market_key}/monthK_{market_abbr}.parquet"

    out_year  = f"{base_dir}/{market_key}/yearK_{market_abbr}.parquet"

    Path(f"{base_dir}/{market_key}").mkdir(parents=True, exist_ok=True)



    # 3) 檔案清單

    files = sorted(glob.glob(f"{local_dayk_dir}/*.csv"))

    if not files:

        print(f"❌ 快取路徑 {local_dayk_dir} 內無檔案,程式終止。")

        return None, None, None



    shards = _split_into_shards(files, SHARD_SIZE)

    print(f"\n📦 [{market_key}] 共 {len(files)} 檔,分 {len(shards)} 批處理")



    # 調整欄位列表以包含 IsFiltered_QA

    base_front = ['StockID','日期','開盤','最高','最低','收盤','成交量']

    base_common_wmy = ['CurPeriod_Days','PrevPeriod_Days', 'HasResume', 'IsFiltered_QA']

    base_common_w = ['CurWeek_Days','PrevWeek_Days', 'HasResume']



    ret_cols = [f'PrevC_{f}' for f in ['W','M','Y']] + [f'Ret_Gap_{f}' for f in ['W','M','Y']] + \

               [f'Ret_Trad_{f}' for f in ['W','M','Y']] + [f'Ret_C_{f}' for f in ['W','M','Y']] + \

               [f'Ret_Max_H_{f}' for f in ['W','M','Y']] + [f'Ret_Min_L_{f}' for f in ['W','M','Y']] + \

               [f'Range_{f}' for f in ['W','M','Y']] + [f'Ret_Max_H_Pos_{f}' for f in ['W','M','Y']] + \

               [f'Ret_H_from_O_{f}' for f in ['W','M','Y']] + [f'Ret_L_from_O_{f}' for f in ['W','M','Y']] + \

               [f'Ret_End_RelH_{f}' for f in ['W','M','Y']] + [f'Ret_End_RelL_{f}' for f in ['W','M','Y']]

    ret_cols = sorted(list(set(ret_cols)))



    wk_cols = base_front + base_common_w + [c for c in ret_cols if c.endswith('_W')] + ['ISO_Week']

    mo_cols = base_front + base_common_wmy + [c for c in ret_cols if c.endswith('_M')]

    yr_cols = base_front + base_common_wmy + [c for c in ret_cols if c.endswith('_Y')]



    # 移除重複的 Period/Week 欄位

    mo_cols = [c for c in mo_cols if not c.startswith('CurWeek') and not c.startswith('PrevWeek')]

    yr_cols = [c for c in yr_cols if not c.startswith('CurWeek') and not c.startswith('PrevWeek')]

    wk_cols = [c for c in wk_cols if not c.startswith('CurPeriod') and not c.startswith('PrevPeriod') and c != 'IsFiltered_QA']



    w_writer = ParquetStreamer(out_week,  keep_cols=wk_cols)

    m_writer = ParquetStreamer(out_month, keep_cols=mo_cols)

    y_writer = ParquetStreamer(out_year,  keep_cols=yr_cols)



    total_ok = total_fail = 0

    skip_records = []



    t0 = time.time()

    for si, shard in enumerate(shards, 1):

        print(f"🧩 Shard {si}/{len(shards)}: {len(shard)} 檔")

        shard_w, shard_m, shard_y = [], [], []



        # [***修正點: 將 futs 和 as_completed 移入 with 區塊***]

        with ThreadPoolExecutor(max_workers=MAX_WORKERS) as ex:

            # 建立 futures 字典,用於追蹤檔案路徑

            futs = {ex.submit(_process_one_file, p): p for p in shard}



            # 遍歷 futures

            for f in as_completed(futs):

                path = futs[f]  # 從字典中獲取當前檔案路徑

                try:

                    status, payload, err = f.result()

                except Exception as e:

                    # 處理執行緒層級的極端錯誤

                    total_fail += 1

                    err = f"{Path(path).name}: Thread execution failed ({e})"

                    if total_fail <= 20:

                        print(" ❌", err)

                    continue



                if status is True:

                    dfw, dfm, dfy = payload

                    shard_w.append(dfw); shard_m.append(dfm); shard_y.append(dfy)

                    total_ok += 1

                elif status == "SKIP":

                    info = payload or {}

                    # 從 payload 中安全獲取 StockID

                    stock_id = info.get('StockID', Path(path).stem.split("_")[0])

                    skip_records.append({'StockID': stock_id, 'file': Path(path).name,

                                         'reason': info.get('reason', 'suspect_pingpong'), 'count': info.get('count', 0)})

                    if total_fail + total_ok + len(skip_records) <= 20 and err:

                        print(" ⏭️", err)

                else:

                    total_fail += 1

                    if total_fail <= 20 and err:

                        print(" ⚠️", err)



        if shard_w: w_writer.append_df(pd.concat(shard_w, ignore_index=True))

        if shard_m: m_writer.append_df(pd.concat(shard_m, ignore_index=True))

        if shard_y: y_writer.append_df(pd.concat(shard_y, ignore_index=True))

        time.sleep(0.5 + random.random()*0.5)



    w_writer.close(); m_writer.close(); y_writer.close()

    print(f"⏱️ 批次耗時:{time.time() - t0:.1f} 秒")



    if skip_records:

        qa_dir = Path(f"{DRIVE_BASE}/{market_key}/_qa")

        qa_dir.mkdir(parents=True, exist_ok=True)

        pd.DataFrame(skip_records).to_csv(qa_dir / "skip_pingpong.csv", index=False, encoding='utf-8-sig')

        print(f"🧹 已輸出略過名單:{qa_dir / 'skip_pingpong.csv'}({len(skip_records)} 檔)")



    market_abbr = MARKET_ABBR_MAP.get(market_key, market_key.replace('-share','').upper())

    final_week  = f"{DRIVE_BASE}/{market_key}/weekK_{market_abbr}.parquet"

    final_month = f"{DRIVE_BASE}/{market_key}/monthK_{market_abbr}.parquet"

    final_year  = f"{DRIVE_BASE}/{market_key}/yearK_{market_abbr}.parquet"



    if WRITE_MODE == 'A':

        for src, dst in [(out_week, final_week), (out_month, final_month), (out_year, final_year)]:

            if Path(src).exists():

                Path(dst).parent.mkdir(parents=True, exist_ok=True)

                Path(dst).unlink(missing_ok=True)

                Path(src).replace(dst)

        print("📤 A 模式:已將本機 Parquet 移動到 Google Drive")



    elif WRITE_MODE == 'B':

        for src, dst in [(out_week, final_week), (out_month, final_month), (out_year, final_year)]:

            if Path(src).exists():

                Path(dst).parent.mkdir(parents=True, exist_ok=True)

                copy2(str(src), str(dst))

        print("📤 B 模式:已將本機 Parquet 複製到 Google Drive(本機仍保留)")



    else:   # WRITE_MODE == 'C'

        final_week, final_month, final_year = out_week, out_month, out_year

        print("☁️ C 模式:直接寫入 Google Drive")



    return final_week, final_month, final_year



# --------------------------------------------------------------------------------

# Colab Cell 4: QA 稽核函式 (Part 4)

# --------------------------------------------------------------------------------



def _geom_chain_return(day_df: pd.DataFrame, start, end) -> float:

    # ... (函式內容保持不變) ...

    sub = day_df[(day_df['日期'] >= start) & (day_df['日期'] <= end)].copy().sort_values('日期')

    c = sub['收盤'].to_numpy(dtype='float64')

    if len(c) < 2 or not np.all(np.isfinite(c)) or np.any(c <= 0):

        return np.nan

    return float(np.prod(c[1:] / c[:-1]) - 1.0)



def _week_bins():

    # ... (函式內容保持不變) ...

    edges = [-1000, -200, -100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0,

             10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 1000, 10000]

    labels = [f"{edges[i]}~{edges[i+1]}%" for i in range(len(edges)-1)]

    return edges, labels



def audit_weekly_parquet(market_key: str, week_path: str):

    # ... (函式內容保持不變) ...

    qa_dir = Path(f"{DRIVE_BASE}/{market_key}/_qa"); qa_dir.mkdir(parents=True, exist_ok=True)

    if not Path(week_path).exists():

        print("❌ QA: 找不到週K Parquet。")

        pd.DataFrame(columns=['ISO_Week','reason','max_abs_z']).to_csv(qa_dir / "weekly_drift_alerts.csv", index=False, encoding='utf-8-sig')

        pd.DataFrame(columns=['ISO_Week','日期','StockID','ret_pct','abs_z','bin']).to_csv(qa_dir / "weekly_top_outliers.csv", index=False, encoding='utf-8-sig')

        return



    dfw = pd.read_parquet(week_path)

    dfw['日期'] = pd.to_datetime(dfw['日期']).dt.tz_localize(None)

    dfw = dfw[(dfw['日期'] >= DATE_START) & (dfw['日期'] <= DATE_END)]



    edges, labels = _week_bins()

    wk = dfw[['ISO_Week','StockID','日期','PrevC_W','開盤','最高','最低','收盤','Ret_Trad_W']].dropna(subset=['Ret_Trad_W']).copy()

    wk['ret_pct'] = (wk['Ret_Trad_W'] * 100).astype('float64')

    wk['bin'] = pd.cut(wk['ret_pct'], bins=edges, labels=labels, right=False)



    dist = wk.pivot_table(index='ISO_Week', columns='bin', values='StockID', aggfunc='count', fill_value=0)

    dist = dist.div(dist.sum(axis=1).replace(0, np.nan), axis=0)

    dist.sort_index().to_csv(qa_dir / "weekly_distribution_summary.csv", encoding='utf-8-sig')



    roll_win = 26

    alerts = []

    if len(dist) >= roll_win + 1:

        for i in range(roll_win, len(dist)):

            cur = dist.iloc[i]

            base = dist.iloc[i-roll_win:i]

            mu = base.mean(); sigma = base.std(ddof=1).replace(0, np.nan)

            z = (cur - mu) / sigma

            big_tail = ['100~200%', '200~1000%', '1000~10000%']

            trig1 = (z.abs() > 5).any()

            trig2 = any((k in z.index) and np.isfinite(z[k]) and (z[k] > 3) for k in big_tail)

            if trig1 or trig2:

                alerts.append({'ISO_Week': dist.index[i], 'reason': 'distribution_drift', 'max_abs_z': float(z.abs().max(skipna=True))})

    pd.DataFrame(alerts).to_csv(qa_dir / "weekly_drift_alerts.csv", index=False, encoding='utf-8-sig')



    wk['abs_z'] = wk.groupby('ISO_Week')['ret_pct'].transform(lambda s: (s - s.mean()) / (s.std(ddof=1) if pd.notna(s.std(ddof=1)) and s.std(ddof=1)!=0 else np.nan)).abs()

    tail_mask = wk['bin'].isin(['100~200%', '200~1000%', '1000~10000%', '-1000~-200%', '-200~-100%'])

    outliers = wk.loc[tail_mask].copy()

    outliers['abs_z_rank'] = outliers.groupby('ISO_Week')['abs_z'].rank(ascending=False, method='first')

    outliers = outliers.sort_values(['ISO_Week','abs_z_rank']).groupby('ISO_Week').head(200)

    outliers[['ISO_Week','日期','StockID','ret_pct','abs_z','bin']].to_csv(qa_dir / "weekly_top_outliers.csv", index=False, encoding='utf-8-sig')

    print(f"🧪 QA 週K(收盤)分布/漂移/厚尾 → {qa_dir}")



# [已修改] 函式名稱: audit_weekly_vs_daily

def audit_weekly_vs_daily(market_key: str):

    """

    [🌟 修正路徑] QA 稽核路徑:改為讀取本地快取。

    """

    market_abbr = MARKET_ABBR_MAP.get(market_key, market_key)

    week_path = Path(f"{DRIVE_BASE}/{market_key}/weekK_{market_abbr}.parquet")

    qa_dir = Path(f"{DRIVE_BASE}/{market_key}/_qa"); qa_dir.mkdir(parents=True, exist_ok=True)



    if not week_path.exists():

        pd.DataFrame(columns=['StockID','ISO_Week','geom_day_chain','Ret_Trad_W','diff']).to_csv(qa_dir / "weekly_vs_daily_diff.csv", index=False, encoding='utf-8-sig')

        print("❌ QA: 找不到週K Parquet,跳過週 vs 日 對比。")

        return



    dfw = pd.read_parquet(week_path).sort_values(['StockID','日期'])

    dfw['日期'] = pd.to_datetime(dfw['日期']).dt.tz_localize(None)

    dfw = dfw[(dfw['日期'] >= DATE_START) & (dfw['日期'] <= DATE_END)]



    # 🌟 關鍵修正:從 Drive 路徑改為本地快取路徑

    local_dayk_dir = Path(f"{LOCAL_DAYK_CACHE}/{market_key}")

   

    cache = {}

    for csv in local_dayk_dir.glob("*.csv"): # 從本地快取讀取

        sid = csv.stem.split("_")[0]

        try:

            d = _read_csv_fast(str(csv))

            dc, cc = _pick(d, DATE_COLS), _pick(d, CLOSE_COLS)

            d = d.rename(columns={dc:'日期', cc:'收盤'})

            d['日期'] = pd.to_datetime(d['日期'], errors='coerce').dt.tz_localize(None)

            d = d.dropna(subset=['日期','收盤']).sort_values('日期')

            d = d[(d['日期'] >= DATE_PAD_START) & (d['日期'] <= DATE_END)]

            cache[sid] = d[['日期','收盤']]

        except:

            pass



    rows = []

    for sid, g in dfw.groupby('StockID'):

        day_df = cache.get(sid)

        if day_df is None:

            continue

        for _, r in g.iterrows():

            week = r['ISO_Week']

            iso = day_df['日期'].dt.isocalendar()

            mask = (iso.year.astype(str) + '-' + iso.week.astype(str).str.zfill(2)) == week

            se = day_df.loc[mask, '日期']

            if se.empty:

                continue

            gret = _geom_chain_return(day_df, se.min(), se.max())

            diff = gret - r['Ret_Trad_W'] if np.isfinite(gret) and np.isfinite(r['Ret_Trad_W']) else np.nan

            rows.append({'StockID': sid, 'ISO_Week': week, 'geom_day_chain': gret, 'Ret_Trad_W': r['Ret_Trad_W'], 'diff': diff})



    rep = pd.DataFrame(rows)

    rep.to_csv(qa_dir / "weekly_vs_daily_diff.csv", index=False, encoding='utf-8-sig')

    if not rep.empty:

        bias = rep['diff'].replace([np.inf,-np.inf], np.nan).dropna()

        print(f"📐 週 vs 日 幾何連乘差異:中位 {bias.median():.6f},|diff|>0.05 的比例 {(bias.abs()>0.05).mean():.2%}")

    print(f"🧪 QA 週K對日K 完成 → {qa_dir/'weekly_vs_daily_diff.csv'}")

留言
avatar-img
《炒股不看周月年K漲幅機率就是耍流氓》
16會員
290內容數
普通上班族,用 AI 與 Python 將炒股量化。我的數據宣言是:《炒股不做量化,都是在耍流氓》。
2025/11/08
因為程式碼太常超過篇幅字數限制所以分段
2025/11/08
因為程式碼太常超過篇幅字數限制所以分段
2025/11/08
📋 程式概述 這是一個企業級股票數據清洗與時間週期轉換系統,專門處理日 K 線數據並轉換為週/月/年 K 線,同時進行多層次的數據品質控管與異常偵測。程式採用玩股網口徑標準,確保數據品質符合量化交易需求。 🎯 核心功能架構 1. 數據來源與處理範圍 時間範圍:2000-01-01
2025/11/08
📋 程式概述 這是一個企業級股票數據清洗與時間週期轉換系統,專門處理日 K 線數據並轉換為週/月/年 K 線,同時進行多層次的數據品質控管與異常偵測。程式採用玩股網口徑標準,確保數據品質符合量化交易需求。 🎯 核心功能架構 1. 數據來源與處理範圍 時間範圍:2000-01-01
2025/11/05
我不是什麼量化高手,也不是什麼金融工程師。 我只是那種會自己寫下載器、跑回測的人。 但說真的,如果沒有 AI 幫我,我根本不知道怎麼處理這些資料。 🧠 問題一:ETF 拆股後,Yahoo Finance 的 Adj Close 竟然沒調整? 理論上: Adj Close = Close
2025/11/05
我不是什麼量化高手,也不是什麼金融工程師。 我只是那種會自己寫下載器、跑回測的人。 但說真的,如果沒有 AI 幫我,我根本不知道怎麼處理這些資料。 🧠 問題一:ETF 拆股後,Yahoo Finance 的 Adj Close 竟然沒調整? 理論上: Adj Close = Close
看更多
你可能也想看
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
為了讓資料更適合進行後續的分析、建立模型,模型的決策準確性,資料探索與清理是資料分析過程中非常重要的步驟,主要目的在於確保資料的品質和可靠性。 因為前幾篇的例子中的資料,並沒有缺失值與重複值的部分,我另外找了一份有包含的資料來做案例分析,由於找到的資料沒有重複值的部分,故本文主要解釋處理缺失值的部
Thumbnail
為了讓資料更適合進行後續的分析、建立模型,模型的決策準確性,資料探索與清理是資料分析過程中非常重要的步驟,主要目的在於確保資料的品質和可靠性。 因為前幾篇的例子中的資料,並沒有缺失值與重複值的部分,我另外找了一份有包含的資料來做案例分析,由於找到的資料沒有重複值的部分,故本文主要解釋處理缺失值的部
Thumbnail
歡迎來到Scikit-learn教學系列的第二篇文章!在上篇中,我們介紹了Scikit-learn與機器學習基礎,並探索了Iris資料集。這一篇將聚焦於資料預處理,我們將學習如何使用Scikit-learn清理資料、處理缺失值、進行特徵縮放與類別編碼,並以真實資料集進行實作。
Thumbnail
歡迎來到Scikit-learn教學系列的第二篇文章!在上篇中,我們介紹了Scikit-learn與機器學習基礎,並探索了Iris資料集。這一篇將聚焦於資料預處理,我們將學習如何使用Scikit-learn清理資料、處理缺失值、進行特徵縮放與類別編碼,並以真實資料集進行實作。
Thumbnail
從基本概念開始,然後逐步深入學習 pandas 的各種功能。這是一個非常強大的 Python 資料分析工具,常用於處理結構化數據。 基本概念 pandas 主要有兩個核心資料結構: Series: 一維的資料結構,類似於 Python 中的列表,但它可以帶有標籤(index)。 DataFr
Thumbnail
從基本概念開始,然後逐步深入學習 pandas 的各種功能。這是一個非常強大的 Python 資料分析工具,常用於處理結構化數據。 基本概念 pandas 主要有兩個核心資料結構: Series: 一維的資料結構,類似於 Python 中的列表,但它可以帶有標籤(index)。 DataFr
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 整理目前手上有的素材: AI說書 - 從0開始 - 180 | RoBERTa 預訓練前言:RoBERTa 預訓練前言 AI說書 - 從0開始 - 181 | 預訓
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 整理目前手上有的素材: AI說書 - 從0開始 - 180 | RoBERTa 預訓練前言:RoBERTa 預訓練前言 AI說書 - 從0開始 - 181 | 預訓
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News