{"id":3905,"date":"2025-09-13T23:19:37","date_gmt":"2025-09-13T15:19:37","guid":{"rendered":"http:\/\/viplao.com\/?p=3905"},"modified":"2025-09-13T23:19:39","modified_gmt":"2025-09-13T15:19:39","slug":"%e3%80%90python%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b%e3%80%91%e7%94%b5%e5%95%86%e5%b9%b3%e5%8f%b0%e6%95%b0%e6%8d%ae%e5%88%86%e6%9e%90%e5%92%8c%e6%8c%96%e6%8e%98-%e5%8a%a8%e6%80%81%e5%91%8a%e8%ad%a6","status":"publish","type":"post","link":"http:\/\/viplao.com\/index.php\/2025\/09\/13\/%e3%80%90python%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b%e3%80%91%e7%94%b5%e5%95%86%e5%b9%b3%e5%8f%b0%e6%95%b0%e6%8d%ae%e5%88%86%e6%9e%90%e5%92%8c%e6%8c%96%e6%8e%98-%e5%8a%a8%e6%80%81%e5%91%8a%e8%ad%a6\/","title":{"rendered":"\u3010Python\u5b9e\u8df5\u6848\u4f8b\u3011\u7535\u5546\u5e73\u53f0\u6570\u636e\u5206\u6790\u548c\u6316\u6398 &#8211; \u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b"},"content":{"rendered":"\n<p>\u5f00\u53d1\u601d\u8def\uff1a\u6211\u4eec\u6765\u521b\u5efa\u4e00\u4e2aPython\u811a\u672c\uff0c\u7528\u4e8e\u6f14\u793a\u5982\u4f55\u4e3a\u7535\u5546\u5e73\u53f0\u7684\u4e0d\u540c\u76d1\u63a7\u6307\u6807\u7c7b\u578b\uff08\u4f8b\u5982\uff1aCPU\u4f7f\u7528\u7387\u3001\u5185\u5b58\u4f7f\u7528\u7387\u3001\u7f51\u7edc\u6d41\u91cf\u3001\u8ba2\u5355\u91cf\u3001\u9519\u8bef\u7387\u7b49\uff09\u9884\u6d4b\u548c\u8bbe\u7f6e\u52a8\u6001\u544a\u8b66\u9608\u503c\uff0c\u4ee5\u63d0\u5347\u76d1\u63a7\u7684\u8986\u76d6\u7387\u548c\u6709\u6548\u6027\u3002<\/p>\n\n\n\n<p>\u8be5\u811a\u672c\u5c06\u5305\u542b\u4ee5\u4e0b\u529f\u80fd\uff1a<\/p>\n\n\n\n<ol>\n<li>\u6a21\u62df\u751f\u6210\u591a\u79cd\u7c7b\u578b\u7684\u7535\u5546\u5e73\u53f0\u76d1\u63a7\u6307\u6807\u65f6\u95f4\u5e8f\u5217\u6570\u636e\u3002<\/li>\n\n\n\n<li>\u5bf9\u6bcf\u79cd\u6307\u6807\u7c7b\u578b\u8fdb\u884c\u6570\u636e\u63a2\u7d22\u548c\u7279\u5f81\u5206\u6790\u3002<\/li>\n\n\n\n<li>\u4f7f\u7528\u7edf\u8ba1\u65b9\u6cd5\uff08\u5982\u57fa\u4e8e\u5386\u53f2\u5206\u4f4d\u6570\uff09\u548c\u673a\u5668\u5b66\u4e60\u65b9\u6cd5\uff08\u5982Isolation Forest\u7528\u4e8e\u5f02\u5e38\u68c0\u6d4b\uff09\u6765\u52a8\u6001\u8ba1\u7b97\u544a\u8b66\u9608\u503c\u3002<\/li>\n\n\n\n<li>\u53ef\u89c6\u5316\u5c55\u793a\u539f\u59cb\u6570\u636e\u548c\u8ba1\u7b97\u51fa\u7684\u52a8\u6001\u9608\u503c\u3002<\/li>\n\n\n\n<li>\u751f\u6210\u4e00\u4efd\u5305\u542b\u5206\u6790\u8fc7\u7a0b\u3001\u9608\u503c\u8bbe\u5b9a\u903b\u8f91\u548c\u5efa\u8bae\u7684\u7efc\u5408\u62a5\u544a\u3002<\/li>\n<\/ol>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import pandas as pd\nimport numpy as np\nfrom sklearn.ensemble import IsolationForest\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom datetime import datetime, timedelta\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n# --- \u914d\u7f6e ---\nNUM_DAYS = 30  # \u6a21\u62df30\u5929\u7684\u6570\u636e\nREPORT_PREFIX = '\u7535\u5546\u591a\u7c7b\u578b\u6307\u6807\u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b\u62a5\u544a'\nRANDOM_SEED = 42\nnp.random.seed(RANDOM_SEED)\n\n# \u5b9a\u4e49\u6307\u6807\u7c7b\u578b\u53ca\u5176\u57fa\u7840\u53c2\u6570\nMETRIC_CONFIGS = {\n    'cpu_utilization': {\n        'name': 'CPU\u4f7f\u7528\u7387 (%)',\n        'base_level': 30,\n        'trend_slope': 0.05, # \u6bcf\u5929\u5e73\u5747\u53d8\u53160.05%\n        'noise_std': 5,\n        'seasonal_weekly': True,\n        'event_multiplier_range': (2, 5) # \u5927\u4fc3\u65f6\u53d8\u4e3a2-5\u500d\n    },\n    'memory_utilization': {\n        'name': '\u5185\u5b58\u4f7f\u7528\u7387 (%)',\n        'base_level': 50,\n        'trend_slope': 0.02,\n        'noise_std': 4,\n        'seasonal_weekly': True,\n        'event_multiplier_range': (1.5, 3)\n    },\n    'network_in_traffic': {\n        'name': '\u5165\u7ad9\u7f51\u7edc\u6d41\u91cf (MB\/s)',\n        'base_level': 100,\n        'trend_slope': 0.5,\n        'noise_std': 20,\n        'seasonal_weekly': True,\n        'event_multiplier_range': (3, 8)\n    },\n    'order_count': {\n        'name': '\u8ba2\u5355\u6570\u91cf (\u5355\/\u5206\u949f)',\n        'base_level': 50,\n        'trend_slope': 0.3,\n        'noise_std': 15,\n        'seasonal_weekly': True,\n        'event_multiplier_range': (5, 15)\n    },\n    'error_rate': {\n        'name': '\u9519\u8bef\u7387 (\u4e07\u5206\u4e4b\u4e00)',\n        'base_level': 5,\n        'trend_slope': 0.01,\n        'noise_std': 2,\n        'seasonal_weekly': False,\n        'event_multiplier_range': (3, 10)\n    }\n}\n\n# --- \u6570\u636e\u751f\u6210 ---\n\ndef generate_sample_metrics_data(n_days, configs):\n    \"\"\"\u751f\u6210\u6a21\u62df\u7684\u591a\u79cd\u7535\u5546\u76d1\u63a7\u6307\u6807\u6570\u636e\"\"\"\n    print(\"--- \u6b63\u5728\u751f\u6210\u6a21\u62df\u7535\u5546\u76d1\u63a7\u6307\u6807\u6570\u636e ---\")\n    start_date = datetime.now() - timedelta(days=n_days-1)\n    dates = pd.date_range(start=start_date, periods=n_days, freq='D')\n    \n    data_dict = {'date': dates}\n    \n    for metric_key, config in configs.items():\n        # 1. \u57fa\u7840\u6c34\u5e73\u548c\u957f\u671f\u8d8b\u52bf\n        base_level = config&#91;'base_level']\n        trend_slope = config&#91;'trend_slope']\n        trend = np.arange(n_days) * trend_slope\n        \n        # 2. \u5b63\u8282\u6027 (\u5468\u5ea6)\n        weekly_effect = np.ones(n_days)\n        if config&#91;'seasonal_weekly']:\n            day_of_week = pd.Series(dates).dt.dayofweek\n            # \u5047\u8bbe\u5468\u672b\u4e1a\u52a1\u91cf\u5927\uff0c\u8d44\u6e90\u4f7f\u7528\u9ad8\n            weekly_effect = np.where(day_of_week.isin(&#91;5, 6]), 1.2, 1.0)\n        \n        # 3. \u7279\u5b9a\u4e8b\u4ef6\u6548\u5e94 (\u6a21\u62df\u5927\u4fc3)\n        event_effect = np.ones(n_days)\n        # \u6a21\u62df\u4e00\u4e2a\u5927\u4fc3\u65e5 (\u4f8b\u5982\u7b2c15\u5929)\n        promo_day_idx = n_days \/\/ 2\n        if 0 &lt;= promo_day_idx &lt; n_days:\n            multiplier = np.random.uniform(*config&#91;'event_multiplier_range'])\n            event_effect&#91;promo_day_idx] *= multiplier\n            if promo_day_idx &gt; 0:\n                event_effect&#91;promo_day_idx-1] *= np.random.uniform(1.2, multiplier * 0.8)\n            if promo_day_idx &lt; n_days - 1:\n                event_effect&#91;promo_day_idx+1] *= np.random.uniform(1.1, multiplier * 0.6)\n        \n        # 4. \u968f\u673a\u566a\u58f0\n        noise = np.random.normal(0, config&#91;'noise_std'], n_days)\n        \n        # 5. \u7ec4\u5408\u6240\u6709\u6210\u5206\n        values = base_level + trend\n        if config&#91;'seasonal_weekly']:\n            values = values * weekly_effect\n        values = values * event_effect + noise\n        \n        # \u786e\u4fdd\u503c\u5728\u5408\u7406\u8303\u56f4\u5185 (\u4f8b\u5982CPU\u4f7f\u7528\u7387\u4e0d\u8d85\u8fc7100%)\n        if 'utilization' in metric_key:\n            values = np.clip(values, 0, 100)\n        elif metric_key == 'error_rate':\n            values = np.maximum(values, 0) # \u9519\u8bef\u7387\u4e0d\u80fd\u4e3a\u8d1f\n            \n        data_dict&#91;metric_key] = np.round(values, 2)\n    \n    df = pd.DataFrame(data_dict)\n    \n    csv_filename = f'{REPORT_PREFIX}_\u6a21\u62df\u76d1\u63a7\u6307\u6807\u6570\u636e.csv'\n    df.to_csv(csv_filename, index=False, encoding='utf-8-sig')\n    print(f\"\u6a21\u62df\u76d1\u63a7\u6307\u6807\u6570\u636e\u5df2\u751f\u6210\u5e76\u4fdd\u5b58\u81f3: {csv_filename}\")\n    return df\n\n# --- \u9608\u503c\u9884\u6d4b ---\n\ndef calculate_dynamic_thresholds(df, configs):\n    \"\"\"\u4e3a\u6bcf\u79cd\u6307\u6807\u8ba1\u7b97\u52a8\u6001\u544a\u8b66\u9608\u503c\"\"\"\n    print(\"\\n--- \u6b63\u5728\u8ba1\u7b97\u52a8\u6001\u544a\u8b66\u9608\u503c ---\")\n    thresholds = {}\n    \n    for metric_key, config in configs.items():\n        values = df&#91;metric_key].values\n        metric_name = config&#91;'name']\n        \n        print(f\"  -&gt; \u4e3a '{metric_name}' \u8ba1\u7b97\u9608\u503c...\")\n        \n        # \u65b9\u6cd51: \u57fa\u4e8e\u5386\u53f2\u5206\u4f4d\u6570 (\u4f8b\u598295%\u5206\u4f4d\u6570\u4f5c\u4e3a\u4e0a\u9650\u9608\u503c)\n        upper_threshold_percentile = 95\n        lower_threshold_percentile = 5 # \u4f8b\u5982\uff0c\u5bf9\u4e8e\u67d0\u4e9b\u6307\u6807\uff0c\u8fc7\u4f4e\u4e5f\u53ef\u80fd\u5f02\u5e38\n        upper_threshold = np.percentile(values, upper_threshold_percentile)\n        lower_threshold = np.percentile(values, lower_threshold_percentile)\n        \n        # \u65b9\u6cd52: \u4f7f\u7528Isolation Forest\u8fdb\u884c\u65e0\u76d1\u7763\u5f02\u5e38\u68c0\u6d4b\n        # \u8be5\u65b9\u6cd5\u53ef\u4ee5\u8bc6\u522b\u4e0e\u5386\u53f2\u6a21\u5f0f\u663e\u8457\u4e0d\u540c\u7684\u70b9\n        clf = IsolationForest(contamination=0.1, random_state=RANDOM_SEED) # \u5047\u8bbe\u670910%\u7684\u5f02\u5e38\n        # Isolation Forest\u9700\u89812D\u6570\u7ec4\n        values_reshaped = values.reshape(-1, 1)\n        anomaly_labels = clf.fit_predict(values_reshaped)\n        \n        # \u83b7\u53d6\u88ab\u6807\u8bb0\u4e3a\u5f02\u5e38\u7684\u70b9\uff0c\u7528\u4e8e\u786e\u5b9a\u9608\u503c\u8fb9\u754c\n        # \u6ce8\u610f\uff1aIsolation Forest\u53ef\u80fd\u6807\u8bb0\u9ad8\u4f4e\u4e24\u79cd\u5f02\u5e38\uff0c\u9700\u8981\u533a\u5206\n        normal_values = values&#91;anomaly_labels == 1]\n        if len(normal_values) &gt; 0:\n            # \u57fa\u4e8e\u6b63\u5e38\u6570\u636e\u91cd\u65b0\u8ba1\u7b97\u5206\u4f4d\u6570\uff0c\u66f4\u7a33\u5065\n            robust_upper = np.percentile(normal_values, upper_threshold_percentile)\n            robust_lower = np.percentile(normal_values, lower_threshold_percentile)\n        else:\n            # \u5982\u679c\u6240\u6709\u70b9\u90fd\u88ab\u6807\u8bb0\u4e3a\u5f02\u5e38\uff08\u4e0d\u592a\u53ef\u80fd\uff09\uff0c\u56de\u9000\u5230\u539f\u59cb\u65b9\u6cd5\n            robust_upper, robust_lower = upper_threshold, lower_threshold\n            \n        # \u786e\u5b9a\u6700\u7ec8\u9608\u503c (\u53ef\u4ee5\u7ed3\u5408\u591a\u79cd\u65b9\u6cd5)\n        # \u8fd9\u91cc\u6211\u4eec\u91c7\u7528\u4e00\u79cd\u7b80\u5355\u7684\u7b56\u7565\uff1a\u4f7f\u7528\u7a33\u5065\u5206\u4f4d\u6570\uff0c\u5e76\u7559\u6709\u4e00\u5b9abuffer\n        buffer_percent = 2.0\n        final_upper = robust_upper * (1 + buffer_percent\/100.0) if robust_upper &gt; 0 else robust_upper + buffer_percent\n        final_lower = robust_lower * (1 - buffer_percent\/100.0) if robust_lower &gt; 0 and 'utilization' not in metric_key else max(0, robust_lower - buffer_percent)\n        \n        # \u5bf9\u4e8e\u5229\u7528\u7387\u7c7b\u6307\u6807\uff0c\u4e0a\u9650\u901a\u5e38\u8bbe\u4e3a100\n        if 'utilization' in metric_key:\n            final_upper = min(final_upper, 100.0)\n            \n        thresholds&#91;metric_key] = {\n            'name': metric_name,\n            'method': f'Isolation Forest + \u7a33\u5065{upper_threshold_percentile}\u5206\u4f4d\u6570',\n            'upper': round(final_upper, 2),\n            'lower': round(final_lower, 2),\n            'raw_upper_percentile': round(upper_threshold, 2),\n            'raw_lower_percentile': round(lower_threshold, 2),\n            'robust_upper': round(robust_upper, 2),\n            'robust_lower': round(robust_lower, 2)\n        }\n        \n    return thresholds\n\n# --- \u53ef\u89c6\u5316 ---\n\ndef visualize_thresholds(df, thresholds, configs):\n    \"\"\"\u53ef\u89c6\u5316\u6570\u636e\u548c\u9608\u503c\"\"\"\n    print(\"\\n--- \u6b63\u5728\u751f\u6210\u53ef\u89c6\u5316\u56fe\u8868 ---\")\n    plot_paths = &#91;]\n    \n    n_metrics = len(configs)\n    n_cols = 2\n    n_rows = (n_metrics + n_cols - 1) \/\/ n_cols\n    \n    fig, axes = plt.subplots(n_rows, n_cols, figsize=(15, 5 * n_rows))\n    axes = axes.flatten() if n_metrics &gt; 1 else &#91;axes]\n    \n    for i, (metric_key, config) in enumerate(configs.items()):\n        ax = axes&#91;i]\n        metric_name = config&#91;'name']\n        values = df&#91;metric_key]\n        threshold_info = thresholds&#91;metric_key]\n        \n        ax.plot(df&#91;'date'], values, marker='o', linestyle='-', markersize=4, label='\u5386\u53f2\u6570\u636e')\n        ax.axhline(y=threshold_info&#91;'upper'], color='r', linestyle='--', linewidth=1.5, label=f\"\u52a8\u6001\u4e0a\u9650\u9608\u503c: {threshold_info&#91;'upper']}\")\n        ax.axhline(y=threshold_info&#91;'lower'], color='orange', linestyle='--', linewidth=1.5, label=f\"\u52a8\u6001\u4e0b\u9650\u9608\u503c: {threshold_info&#91;'lower']}\")\n        ax.axhline(y=threshold_info&#91;'raw_upper_percentile'], color='pink', linestyle=':', linewidth=1, label=f\"\u539f\u59cb95%\u5206\u4f4d\u6570: {threshold_info&#91;'raw_upper_percentile']}\")\n        \n        ax.set_title(f\"{metric_name} \u52a8\u6001\u9608\u503c\")\n        ax.set_xlabel('\u65e5\u671f')\n        ax.set_ylabel(metric_name)\n        ax.legend()\n        ax.grid(True, alpha=0.5)\n    \n    # \u9690\u85cf\u591a\u4f59\u7684\u5b50\u56fe\n    for j in range(i+1, len(axes)):\n        fig.delaxes(axes&#91;j])\n        \n    plt.tight_layout()\n    plot_filename = f'{REPORT_PREFIX}_\u52a8\u6001\u9608\u503c\u53ef\u89c6\u5316.png'\n    plt.savefig(plot_filename, bbox_inches='tight')\n    plt.close()\n    plot_paths.append(plot_filename)\n    print(f\"\u52a8\u6001\u9608\u503c\u53ef\u89c6\u5316\u56fe\u8868\u5df2\u4fdd\u5b58\u81f3: {plot_filename}\")\n    \n    return plot_paths\n\n# --- \u62a5\u544a\u751f\u6210 ---\n\ndef generate_threshold_report(thresholds, plot_paths):\n    \"\"\"\u751f\u6210\u6700\u7ec8\u7684\u9608\u503c\u9884\u6d4b\u5206\u6790\u62a5\u544a\"\"\"\n    print(\"\\n--- \u6b63\u5728\u751f\u6210\u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b\u62a5\u544a ---\")\n    from datetime import datetime\n    report_filename = f\"{REPORT_PREFIX}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\"\n    \n    with open(report_filename, 'w', encoding='utf-8') as f:\n        f.write(\"=\" * 70 + \"\\n\")\n        f.write(\"        \u7535\u5546\u5e73\u53f0\u591a\u7c7b\u578b\u6307\u6807\u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b\u4e0e\u5206\u6790\u62a5\u544a\\n\")\n        f.write(f\"              \u751f\u6210\u65f6\u95f4: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n\")\n        f.write(\"=\" * 70 + \"\\n\\n\")\n\n        f.write(\"--- 1. \u9879\u76ee\u6982\u8ff0 ---\\n\")\n        f.write(\"\u672c\u9879\u76ee\u65e8\u5728\u4e3a\u7535\u5546\u5e73\u53f0\u7684\u591a\u79cd\u5173\u952e\u76d1\u63a7\u6307\u6807\uff08\u5982CPU\u3001\u5185\u5b58\u3001\u7f51\u7edc\u3001\u8ba2\u5355\u3001\u9519\u8bef\u7387\u7b49\uff09\\n\")\n        f.write(\"\u9884\u6d4b\u548c\u8bbe\u5b9a\u52a8\u6001\u544a\u8b66\u9608\u503c\u3002\u76f8\u6bd4\u4e8e\u9759\u6001\u9608\u503c\uff0c\u52a8\u6001\u9608\u503c\u80fd\u66f4\u597d\u5730\u9002\u5e94\u4e1a\u52a1\u53d8\u5316\uff0c\\n\")\n        f.write(\"\u51cf\u5c11\u8bef\u62a5\u548c\u6f0f\u62a5\uff0c\u4ece\u800c\u63d0\u5347\u76d1\u63a7\u7cfb\u7edf\u7684\u8986\u76d6\u8303\u56f4\u548c\u6709\u6548\u6027\u3002\\n\\n\")\n\n        f.write(\"--- 2. \u6570\u636e\u6982\u89c8 ---\\n\")\n        f.write(f\"\u6570\u636e\u6765\u6e90: \u6a21\u62df\u751f\u6210\u7684 {NUM_DAYS} \u5929\u7535\u5546\u5e73\u53f0\u76d1\u63a7\u6307\u6807\u6570\u636e\u3002\\n\")\n        f.write(\"\u5305\u542b\u7684\u6307\u6807\u7c7b\u578b:\\n\")\n        for key, config in METRIC_CONFIGS.items():\n            f.write(f\"  - {config&#91;'name']}\\n\")\n        f.write(\"\u6570\u636e\u7279\u5f81: \u5305\u542b\u957f\u671f\u8d8b\u52bf\u3001\u5468\u5ea6\u5b63\u8282\u6027\u4ee5\u53ca\u6a21\u62df\u7684\u5927\u4fc3\u4e8b\u4ef6\u6548\u5e94\u3002\\n\")\n        f.write(\"\u539f\u59cb\u6570\u636e\u5df2\u4fdd\u5b58\u4e3a CSV \u6587\u4ef6\u3002\\n\\n\")\n\n        f.write(\"--- 3. \u9608\u503c\u8ba1\u7b97\u65b9\u6cd5 ---\\n\")\n        f.write(\"\u91c7\u7528\u4ee5\u4e0b\u65b9\u6cd5\u76f8\u7ed3\u5408\u6765\u8ba1\u7b97\u52a8\u6001\u9608\u503c\uff1a\\n\")\n        f.write(\"1. \u5386\u53f2\u5206\u4f4d\u6570\u6cd5: \\n\")\n        f.write(\"   - \u8ba1\u7b97\u6307\u6807\u5386\u53f2\u6570\u636e\u7684\u9ad8\u767e\u5206\u4f4d\u6570(\u598295%)\u548c\u4f4e\u767e\u5206\u4f4d\u6570(\u59825%)\u3002\\n\")\n        f.write(\"   - \u4f5c\u4e3a\u521d\u6b65\u7684\u9608\u503c\u53c2\u8003\u3002\\n\")\n        f.write(\"2. Isolation Forest (\u9694\u79bb\u68ee\u6797) \u5f02\u5e38\u68c0\u6d4b:\\n\")\n        f.write(\"   - \u4e00\u79cd\u65e0\u76d1\u7763\u673a\u5668\u5b66\u4e60\u7b97\u6cd5\uff0c\u80fd\u8bc6\u522b\u4e0e\u5927\u591a\u6570\u6570\u636e\u663e\u8457\u4e0d\u540c\u7684\u70b9\u3002\\n\")\n        f.write(\"   - \u7528\u4e8e\u8fc7\u6ee4\u6389\u5386\u53f2\u6570\u636e\u4e2d\u7684\u5f02\u5e38\u6ce2\u52a8\uff0c\u4f7f\u9608\u503c\u8ba1\u7b97\u66f4\u7a33\u5065\u3002\\n\")\n        f.write(\"3. \u7efc\u5408\u7b56\u7565:\\n\")\n        f.write(\"   - \u57fa\u4e8eIsolation Forest\u8fc7\u6ee4\u540e\u7684\u201c\u6b63\u5e38\u201d\u6570\u636e\uff0c\u91cd\u65b0\u8ba1\u7b97\u5206\u4f4d\u6570\u3002\\n\")\n        f.write(\"   - \u5728\u7a33\u5065\u5206\u4f4d\u6570\u57fa\u7840\u4e0a\u589e\u52a0\u4e00\u4e2a\u5c0f\u7684\u5b89\u5168\u7f13\u51b2\u533a(Buffer)\u3002\\n\")\n        f.write(\"   - \u5bf9\u7279\u5b9a\u6307\u6807\uff08\u5982\u5229\u7528\u7387\uff09\u65bd\u52a0\u786c\u6027\u9650\u5236\uff08\u5982&lt;=100%\uff09\u3002\\n\\n\")\n        \n        f.write(\"--- 4. \u5404\u6307\u6807\u52a8\u6001\u9608\u503c\u7ed3\u679c ---\\n\")\n        for metric_key, threshold_info in thresholds.items():\n            f.write(f\"\\n  -&gt; \u6307\u6807: {threshold_info&#91;'name']}\\n\")\n            f.write(f\"     - \u8ba1\u7b97\u65b9\u6cd5: {threshold_info&#91;'method']}\\n\")\n            f.write(f\"     - \u6700\u7ec8\u52a8\u6001\u4e0a\u9650\u9608\u503c: {threshold_info&#91;'upper']}\\n\")\n            f.write(f\"     - \u6700\u7ec8\u52a8\u6001\u4e0b\u9650\u9608\u503c: {threshold_info&#91;'lower']}\\n\")\n            f.write(f\"     - \u539f\u59cb95%\u5206\u4f4d\u6570(\u4e0a\u9650\u53c2\u8003): {threshold_info&#91;'raw_upper_percentile']}\\n\")\n            f.write(f\"     - \u539f\u59cb5%\u5206\u4f4d\u6570(\u4e0b\u9650\u53c2\u8003): {threshold_info&#91;'raw_lower_percentile']}\\n\")\n            f.write(f\"     - Isolation Forest\u8fc7\u6ee4\u540e95%\u5206\u4f4d\u6570: {threshold_info&#91;'robust_upper']}\\n\")\n            f.write(f\"     - Isolation Forest\u8fc7\u6ee4\u540e5%\u5206\u4f4d\u6570: {threshold_info&#91;'robust_lower']}\\n\")\n        f.write(\"\\n\")\n\n        f.write(\"--- 5. \u53ef\u89c6\u5316\u5206\u6790 ---\\n\")\n        f.write(\"\u6240\u6709\u6307\u6807\u7684\u5386\u53f2\u6570\u636e\u53ca\u5176\u5bf9\u5e94\u7684\u52a8\u6001\u9608\u503c\u5df2\u5728\u56fe\u8868\u4e2d\u5c55\u793a\u3002\\n\")\n        for path in plot_paths:\n            f.write(f\"  - \u56fe\u8868: {path}\\n\")\n        f.write(\"\\n\")\n\n        f.write(\"--- 6. \u7ed3\u8bba\u4e0e\u5efa\u8bae ---\\n\")\n        f.write(\"1. \u9608\u503c\u52a8\u6001\u5316: \\n\")\n        f.write(\"   - \u4e0d\u540c\u7c7b\u578b\u7684\u6307\u6807\u5e94\u91c7\u7528\u4e0d\u540c\u7684\u9608\u503c\u7b56\u7565\u3002\\n\")\n        f.write(\"   - \u52a8\u6001\u9608\u503c\u80fd\u81ea\u52a8\u9002\u5e94\u4e1a\u52a1\u7684\u81ea\u7136\u6ce2\u52a8\uff08\u5982\u5468\u672b\u9ad8\u5cf0\uff09\uff0c\u51cf\u5c11\u65e0\u6548\u544a\u8b66\u3002\\n\")\n        f.write(\"2. \u6a21\u578b\u8fed\u4ee3: \\n\")\n        f.write(\"   - \u5efa\u8bae\u5b9a\u671f\uff08\u5982\u6bcf\u65e5\/\u6bcf\u5468\uff09\u4f7f\u7528\u6700\u65b0\u6570\u636e\u91cd\u65b0\u8ba1\u7b97\u9608\u503c\uff0c\u4ee5\u9002\u5e94\u7cfb\u7edf\u548c\u4e1a\u52a1\u7684\u957f\u671f\u53d8\u5316\u3002\\n\")\n        f.write(\"3. \u591a\u6a21\u578b\u878d\u5408: \\n\")\n        f.write(\"   - \u53ef\u4ee5\u7ed3\u5408\u66f4\u591a\u7edf\u8ba1\u6a21\u578b\uff08\u5982ARIMA\u9884\u6d4b\u533a\u95f4\uff09\u6216\u673a\u5668\u5b66\u4e60\u6a21\u578b\u6765\u8fdb\u4e00\u6b65\u4f18\u5316\u9608\u503c\u3002\\n\")\n        f.write(\"4. \u4e1a\u52a1\u8054\u52a8: \\n\")\n        f.write(\"   - \u5728\u5df2\u77e5\u7684\u5927\u4fc3\u6d3b\u52a8\u524d\uff0c\u53ef\u4ee5\u4e34\u65f6\u8c03\u6574\u9608\u503c\u8ba1\u7b97\u903b\u8f91\uff0c\u6216\u5c06\u6d3b\u52a8\u671f\u6570\u636e\u4f5c\u4e3a\u7279\u6b8a\u573a\u666f\u5904\u7406\u3002\\n\")\n        f.write(\"5. \u544a\u8b66\u5206\u7ea7: \\n\")\n        f.write(\"   - \u53ef\u4ee5\u8bbe\u7f6e\u591a\u7ea7\u9608\u503c\uff08\u5982\u8b66\u544a\u3001\u4e25\u91cd\uff09\uff0c\u5bf9\u5e94\u4e0d\u540c\u7684\u54cd\u5e94\u6d41\u7a0b\u3002\\n\")\n        f.write(\"6. \u53ef\u89c6\u5316\u76d1\u63a7: \\n\")\n        f.write(\"   - \u5c06\u52a8\u6001\u9608\u503c\u5b9e\u65f6\u5c55\u793a\u5728\u76d1\u63a7\u9762\u677f\u4e0a\uff0c\u4fbf\u4e8e\u8fd0\u7ef4\u4eba\u5458\u7406\u89e3\u544a\u8b66\u80cc\u666f\u3002\\n\\n\")\n\n        f.write(\"=\" * 70 + \"\\n\")\n        f.write(\"                             \u62a5\u544a\u7ed3\u675f\\n\")\n        f.write(\"=\" * 70 + \"\\n\")\n\n    print(f\"\u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b\u62a5\u544a\u5df2\u751f\u6210: {report_filename}\")\n\n# --- \u4e3b\u51fd\u6570 ---\n\ndef main():\n    \"\"\"\u4e3b\u51fd\u6570\"\"\"\n    # 1. \u751f\u6210\u6570\u636e\n    df_metrics = generate_sample_metrics_data(NUM_DAYS, METRIC_CONFIGS)\n    \n    # 2. \u8ba1\u7b97\u52a8\u6001\u9608\u503c\n    thresholds = calculate_dynamic_thresholds(df_metrics, METRIC_CONFIGS)\n    \n    # 3. \u53ef\u89c6\u5316\n    plot_paths = visualize_thresholds(df_metrics, thresholds, METRIC_CONFIGS)\n    \n    # 4. \u751f\u6210\u62a5\u544a\n    generate_threshold_report(thresholds, plot_paths)\n    \n    print(\"\\n\u7535\u5546\u5e73\u53f0\u591a\u7c7b\u578b\u6307\u6807\u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b\u5206\u6790\u6d41\u7a0b\u5b8c\u6210\u3002\")\n\nif __name__ == \"__main__\":\n    main()\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5f00\u53d1\u601d\u8def\uff1a\u6211\u4eec\u6765\u521b\u5efa\u4e00\u4e2aPython\u811a\u672c\uff0c\u7528\u4e8e\u6f14\u793a\u5982\u4f55\u4e3a\u7535\u5546\u5e73\u53f0\u7684\u4e0d\u540c\u76d1\u63a7\u6307\u6807\u7c7b\u578b\uff08\u4f8b\u5982\uff1aCPU\u4f7f\u7528&hellip; <a href=\"http:\/\/viplao.com\/index.php\/2025\/09\/13\/%e3%80%90python%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b%e3%80%91%e7%94%b5%e5%95%86%e5%b9%b3%e5%8f%b0%e6%95%b0%e6%8d%ae%e5%88%86%e6%9e%90%e5%92%8c%e6%8c%96%e6%8e%98-%e5%8a%a8%e6%80%81%e5%91%8a%e8%ad%a6\/\" class=\"more-link read-more\" rel=\"bookmark\">\u7ee7\u7eed\u9605\u8bfb <span class=\"screen-reader-text\">\u3010Python\u5b9e\u8df5\u6848\u4f8b\u3011\u7535\u5546\u5e73\u53f0\u6570\u636e\u5206\u6790\u548c\u6316\u6398 &#8211; \u52a8\u6001\u544a\u8b66\u9608\u503c\u9884\u6d4b<\/span><i class=\"fa fa-arrow-right\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[28],"views":391,"_links":{"self":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/3905"}],"collection":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/comments?post=3905"}],"version-history":[{"count":2,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/3905\/revisions"}],"predecessor-version":[{"id":3916,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/3905\/revisions\/3916"}],"wp:attachment":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/media?parent=3905"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/categories?post=3905"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/tags?post=3905"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}