هوش مصنوعی

هوش مصنوعی در نیروگاه خورشیدی: مدل‌ها، روش‌ها و معماری

اینورتری که از کار افتاده خودش را اعلام می‌کند. آنچه بی‌سروصدا تولید را می‌خورد، رشته و اینورتری است که کار می‌کند اما کمتر از آنچه باید. این صفحه برای مهندس توضیح می‌دهد موتور نورانت با چه مدل‌ها و روش‌هایی همین را پیدا می‌کند، چه وقت ساکت می‌ماند، مدل زبانی کجای زنجیره است، و چه سهمی روی کامپیوتر نیروگاه و چه سهمی روی سرور اجرا می‌شود.

مسئله: عیبی که کد خطا ندارد

اینورتری که کاملاً از کار افتاده، خودش را اعلام می‌کند: کد خطا می‌دهد، تولیدش صفر می‌شود و هر سامانه‌ای آن را می‌بیند. پول واقعی جای دیگری از دست می‌رود: اینورتری که کار می‌کند اما ۸ درصد کمتر از همسایه‌اش تولید دارد، رشته‌ای که فیوزش سوخته در حالی که مجموع اینورتر هنوز «قابل قبول» است، یا ورودی‌ای که در تنظیمات غیرفعال شده ولی جریان دارد و هرگز پایش نمی‌شود. هیچ‌کدام کد خطا ندارند و هیچ آستانه‌ی ثابتی هم آن‌ها را نمی‌گیرد.

این صفحه برای مهندسی نوشته شده که می‌خواهد بداند پشت کلمه‌ی «هوش مصنوعی» دقیقاً چه مدلی، با چه ورودی، چه مرجع مقایسه‌ای و چه معیار پذیرشی کار می‌کند؛ کدام بخش روی کامپیوتر نیروگاه (لبه) اجرا می‌شود و کدام روی سرور؛ و مدل زبانی کجای این زنجیره است و کجا نیست. کد نمونه‌ها ساده‌شده‌ی همان توابعی‌اند که در محصول اجرا می‌شوند (Python 3، بدون وابستگی بیرونی).

قاعده‌ی اول: سکوت بهتر از حرف اشتباه است. هدف بهینه‌سازی، دقت (precision) است نه بازیابی (recall): یافته‌ای که اپراتور را بیهوده سر سایت بکشاند، اعتماد به یافته‌ی درست بعدی را هم از بین می‌برد. همه‌ی معماری زیر برای «کمتر ولی درست» طراحی شده است.

مدل‌ها و روش‌ها، به نام

هسته‌ی تحلیل آمار مقاوم و مقایسه‌ی نسبی است، نه یک شبکه‌ی عصبی. دلیلش در بخش «چرا یادگیری عمیق نه» آمده است. جدول زیر هر جزء را با نام روش و محل اجرایش نشان می‌دهد:

جزءروش / مدلمحل اجرا
نرمال‌سازی نسبت به همتانسبت هر کمیت به میانه‌ی همتایان هم‌زمان (cross-sectional normalization): رشته به رشته‌های همان اینورتر، اینورتر به اینورترهای همان نیروگاه. نیروگاه، سنسور تابش خودش استلبه
آمار مقاوممیانه، MAD مقیاس‌شده (×۱٫۴۸۲۶)، z-score مقاوم با کف مطلق و کف نسبی جداگانه برای هر شاخصلبه + سرور (یک فایل، تست بایت‌به‌بایت)
روندتخمین‌گر Theil–Sen (میانه‌ی شیب‌های دوبه‌دو) و ETA تا رسیدن به حدلبه + سرور
خط مبنای آموخته‌شدهمرجع مشروط به نقطه‌ی کار (باند بار، نه ساعت) برای هر اینورتر؛ مرجع ساعت‌ـهفته برای پاورآنالایزرهالبه
تحلیلگر DCطبقه‌بند قاعده‌محور روی ویژگی‌های ادغام‌شده‌ی یک روز کامل هر ورودی: نسبت جریان، نسبت ولتاژ، سهم «مرده»، تشخیص نقطه‌ی تغییر (change-point)، شمار قطع‌ووصل و پنجره‌ی سایهلبه
امضای ولتاژنسبت ولتاژ MPPT به میانه‌ی MPPTهای دیگر (نور و دمای سلول حذف می‌شود) و Voc سحرگاهیلبه
بررسی تنظیماتمقایسه‌ی سیم‌بندی اعلام‌شده با جریان اندازه‌گیری‌شده، فقط در نور قویلبه
دروازه‌ی شواهدفیلتر دقت‌محور: نور، پایداری با هیسترزیس، تفکیک علت مشترک، کارنامه‌ی همان نوع یافته در همان نیروگاهلبه (+ نسخه‌ی سرور برای نسخه‌های قدیمی)
تابش روی صفحه‌ی پنلGHI از Open-Meteo، تفکیک مستقیم/پخش با همبستگی Erbs، انتقال به صفحه‌ی شیب‌دار با مدل آسمان هم‌سانگرد Liu–Jordanسرور (ساعتی) + لبه (روزانه)
پیش‌بینی تولیدتولید آسمان صاف × شاخص صافی هوا، کالیبره با بهترین روز اندازه‌گیری‌شده؛ بازه‌ی P10–P90 از صدک‌های تجربیِ نسبت «واقعی ÷ پیش‌بینی» همین نیروگاهلبه
یادگیری ناوگانداده‌پرت‌های بین‌نیروگاهی، افت PR با حذف فصل از روی میانه‌ی ناوگان، افت سال‌به‌سال PR، رانش سهم اینورتر (Theil–Sen)؛ تجمیع آماره‌ها با میانه، شبیه یادگیری فدرالسرور
مدل زبانی (اختیاری)Qwen3-4B-Instruct با کوانتیزاسیون Q4_K_M در قالب GGUF (حدود ۲٫۵ گیگابایت، مجوز Apache-2.0)، اجرا با llama.cpp (llama-server، فقط CPU). روی کامپیوتر با ۱۶ گیگابایت حافظه: Qwen3-8B-Instruct. فقط برای پاسخ به پرسش اپراتور از روی واقعیت‌های اندازه‌گیری‌شدهلبه، بدون اینترنت

مرجع نسبی: چرا به سنسور تابش نیاز ندارد

رشته‌های یک اینورتر در یک لحظه یک آسمان را می‌بینند. اگر جریان هر رشته بر میانه‌ی جریان رشته‌های کناری‌اش تقسیم شود، ابر، گردوغبار و ساعت روز از نسبت حذف می‌شوند و آنچه می‌ماند داستان خود آن رشته است. یک رشته‌ی خراب نباید مرجع «عادی» را جابه‌جا کند؛ برای همین مرجع میانه است و پراکندگی MAD:

MAD_TO_SIGMA = 1.4826          # MAD to a normal-equivalent sigma

def mad_spread(values, center=None):
    c = median(values) if center is None else center
    return MAD_TO_SIGMA * median([abs(v - c) for v in values])

def robust_z(value, center, spread, floor=0.0, relative_floor=0.04):
    # A metric that never moves has MAD ~ 0; without a floor every wobble
    # becomes a 40-sigma "critical". The floor is per metric: conversion
    # efficiency sits near 99 %, so its relative floor is 0, not 4 %.
    denominator = max(spread, floor, relative_floor * abs(center))
    return 0.0 if denominator <= 0 else (value - center) / denominator

def theil_sen_slope(xs, ys):
    # median of all pairwise slopes: one outage day cannot invent a trend
    return median([(ys[j] - ys[i]) / (xs[j] - xs[i])
                   for i in range(len(xs)) for j in range(i + 1, len(xs))
                   if xs[j] != xs[i]])

همین ایده در سه سطح پشت سر هم به کار می‌رود (قاعده‌ای که از تجربه‌ی بهره‌بردار گرفته شد): رشته‌ی کناری ← بقیه‌ی همان اینورتر ← اینورترهای دیگر. اگر یک رشته افت کند ولی کناری‌اش هم همان‌قدر افت کرده باشد، سایه یا ابر است؛ اگر همه‌ی رشته‌های یک اینورتر با هم و نسبت به اینورترهای دیگر پایین باشند، مشکل از کل آرایه یا ردیاب MPPT همان اینورتر است؛ و اگر فقط یک ورودی پایین است، مشکل همان ورودی است. هر یافته دامنه‌ی خودش را می‌گوید: ورودی، اینورتر یا نیروگاه.

تحلیلگر DC: یک روز کامل هر ورودی، مثل خواندن نمودار

به‌جای ده آشکارساز که هر کدام یک کمیت را در یک لحظه نگاه می‌کردند، هر ورودیِ سیم‌بندی‌شده یک حکم می‌گیرد که از سه اندازه‌گیری ادغام‌شده ساخته می‌شود: جریان رشته (جایی که اینورتر گزارش می‌کند و جمعش با جریان MPPT می‌خواند)، جریان MPPT تقسیم بر تعداد رشته‌ها، و ولتاژ MPPT نسبت به همتایان. فقط نمونه‌های «نور خوب» وارد می‌شوند (توان اینورتر ≥ ۳۰٪ اوج همان روزش و جریان مرجع ≥ ۱٫۵ آمپر):

def classify(day):                     # one input, one day
    cr, vr = day.current_ratio, day.voltage_ratio   # vs sibling median
    if vr is not None and vr <= 0.10 and cr >= 0.5:  return "dc.input_short"
    if day.dead_share >= 0.80:                       return "dc.input_dead"
    if day.step_at is not None:                      return "dc.input_dropped"
    if day.dropouts >= 3:                            return "dc.input_intermittent"
    if parallel_strings(day) and abs(cr - (n - 1) / n) <= 0.08:
        return "dc.string_missing"     # one of n parallel strings is open
    if day.shade_hours:                              return "dc.shading"
    v_low, i_low = vr is not None and vr <= 0.955, cr <= 0.90
    if v_low and i_low:  return "dc.mismatch"        # damaged / heavily shaded
    if v_low:            return "dc.modules_low"     # bypass diode, missing panel
    if i_low:            return "dc.current_low"     # soiling, degradation
    return ""                                        # healthy

بررسی تنظیمات: دسته‌ی جداگانه‌ی «تنظیمات»

نقشه‌ی مدباس هر برند همه‌ی MPPTها و همه‌ی ورودی‌های رشته‌ی مدل را دارد، هر چه بهره‌بردار تیک زده باشد. پس داده‌ها نشان می‌دهند واقعاً چه چیزی سیم‌بندی شده است. اشتباه تنظیمات خرابی نیست — از پشت میز درست می‌شود، نه با اعزام تکنسین — برای همین این یافته‌ها در همه‌ی صفحه‌ها (دسکتاپ، سایت شرکتی، اپ و وب‌اپ) در دسته‌ی جداگانه‌ی «تنظیمات» کنار «خیلی مهم، مهم، معمولی» می‌آیند و هیچ فیلتر سطحی آن‌ها را قاطی خطاها نمی‌کند.

شرط نور قوی: صبح، غروب و هوای ابری جریان‌ها کوچک‌اند و ورودی‌هایی که رو به جهت‌های متفاوت دارند از هم جدا می‌شوند؛ تصمیم درباره‌ی تنظیمات در آن ساعت‌ها اشتباه است. یک نمونه فقط وقتی حساب می‌شود که خورشید دست‌کم ۲۵ درجه بالا باشد و میانه‌ی جریان هر رشته‌ی همان اینورتر دست‌کم ۳ آمپر باشد — مرجعی که از همه‌ی ورودی‌های دارای جریان ساخته می‌شود، تیک‌خورده یا نه، تا یک تیک اشتباه مرجع خودش را خم نکند:

STRONG_A, MIN_SUN_DEG, MIN_MINUTES, AGREE = 3.0, 25.0, 60, 0.80

for r in readings:                         # yesterday + today, archive
    if r.sun_deg is not None and r.sun_deg < MIN_SUN_DEG:
        continue
    per_string = [i / u.strings for i, u in zip(currents(r), inputs) if i > 0.5]
    ref = median(per_string)               # the plant is its own sensor
    if len(per_string) < 2 or ref < STRONG_A:
        continue                           # dawn, dusk, cloud: decide nothing
    strong.append((r, ref))

# an input set inactive that carries current on 80 % of the strong readings
held = mean(i >= max(1.0, 0.25 * ref) for i, ref in samples(unticked_input))
if strong_minutes >= MIN_MINUTES and held >= AGREE:
    report("cfg.input_unconfigured", inverter, mppt, string, mean_a, ref)
کدیعنیچرا با خرابی اشتباه نمی‌شود
cfg.input_unconfiguredورودی (یا MPPT، یا MPPTای بیرون از تعداد تنظیم‌شده) غیرفعال شده ولی جریان داردورودی خراب جریان ندارد؛ جریانِ بدون تیک فقط یعنی تیک اشتباه است
cfg.input_silentورودی «متصل» تیک خورده، ولی در نور قوی هرگز جریان نداشتهفقط اگر حافظه‌ی ۶۰ روزه هرگز تولیدش را ندیده باشد؛ اگر تولید داشته و قطع شده، خرابی است و تحلیلگر DC می‌گوید
cfg.string_countMPPTای که جریان تک‌رشته‌ها را گزارش نمی‌کند، به اندازه‌ی رشته‌های بیشتری از تعداد تیک‌خورده جریان داردیک ردیاب بیشتر از رشته‌هایش جریان نمی‌دهد؛ «بیشتر» هرگز خرابی نیست

متن یافته دقیقاً می‌گوید کدام ورودی و چه اختلافی، مثلاً: «اینورتر ۷ · MPPT ۲ · رشته ۲: رشته ۲ از MPPT ۲ اینورتر ۷ را در تنظیمات غیرفعال کرده‌اید، ولی فعال است: در ۱۱۹ دقیقه نور قوی به‌طور میانگین ۸٫۰ آمپر جریان داشت (هر رشته‌ی فعال همین اینورتر ۸٫۰ آمپر).» برای اینورترهایی که جریان تک‌رشته را نمی‌دهند، نام همان ورودیِ غیرفعال‌شده‌ای را می‌برد که باید فعال شود.

مقایسه با دیروز، هفته، ماه و سال قبل — با حذف آب‌وهوا

مقایسه‌ی خام با گذشته در نیروگاه خورشیدی بی‌معناست: امروز ابری‌تر است، این ماه گرم‌تر است. دو روش برای حذف آب‌وهوا به کار می‌رود: مقایسه با همتا (همتایان هم‌زمان یک آسمان دارند) و تقسیم بر تابش (نسبت عملکرد، PR).

افقچه چیزی با چه چیزیآب‌وهوا چطور حذف می‌شود
روزهر ورودی در سه روز اخیر (دو از سه)نسبت به همتایان هم‌زمان
هفته۷ روز اخیر هر اینورتر در برابر ۷ روز قبلش، با تاریخ شروع افت (فهرست زیان)بازده ویژه تقسیم بر میانه‌ی همان روزِ اینورترهای همان نیروگاه
ماهدما و بازده تبدیل هفته‌ی اخیر در برابر روزهای ۲۲ تا ۳۵ قبل، فقط در بار بالا؛ ولتاژ MPPT در برابر ۳۰ روز قبلتغییر هر اینورتر منهای میانه‌ی تغییر بقیه (فصل حذف می‌شود)
ماه (نیروگاه)PR چهار هفته‌ی اخیر در برابر چهار هفته‌ی قبلتقسیم بر تابش روی صفحه‌ی پنل؛ اثر دمای فصل با میانه‌ی ناوگان حذف می‌شود؛ روزهای گردوغباری کنار می‌روند
سال۶۰ روز اخیر در برابر همان ۶۰ روز پارسالفصل با مقایسه‌ی هم‌فصل حذف می‌شود؛ آب‌وهوا با مقایسه‌ی PR (تابش هر دو فصل ذخیره است)، و فقط بدون تابش، بازده ویژه — که متن یافته هم همین را می‌گوید

دروازه‌ی شواهد: یک یافته چه وقت گفته می‌شود

بازبینی ۳۰ روزه‌ی یافته‌های ناوگان نشان داد بیش از نیمی از آن‌ها در سپیده‌دم و غروب صادر شده بود: اینورتری که هنوز بیدار نشده بود و «عدم تعادل ۷۰ درصد» می‌خواند، یا سایه‌ای که از روی همه‌ی اینورترها رد می‌شد و برای هر کدام «فیوز سوخته» ثبت می‌کرد. هر یافته ابتدا در یکی از پنج دسته قرار می‌گیرد:

دستهچیستبا آن چه می‌شود
گزارش اینورترخطا یا آلارمی که خود اینورتر اعلام کردههرگز فیلتر نمی‌شود؛ توضیح کنارش می‌آید، نه به‌جایش
تاریخینتیجه‌ی روزهای کامل آرشیو: روند، تنظیمات، فهرست زیانچون از روزهای کامل ساخته شده، خودش پایدار است
لحظه‌ایقضاوت درباره‌ی همین لحظهباید همه‌ی شرط‌های پایین را بگذراند
اطلاعاتیوضعیت است، مشکل نیستروی صفحه هست، آلارم نمی‌شود
حذفچیزی که شاهد هیچ‌چیز نیست: «احتمال خرابی ۱۰۰٪»هرگز گفته نمی‌شود
def admit(finding, ctx):                       # a LIVE finding
    if ctx.sun_elevation < 20 or ctx.plant_share_of_capacity < 0.15:
        return HOLD                            # not enough light to judge
    if seen_on(finding.family, ctx) >= max(3, 0.40 * ctx.online_inverters):
        return COMMON_CAUSE                    # the sky / the layout, not this unit
    if ctx.ledger.minutes_held(finding) < persistence(finding):  # 30 / 60 / 180
        return WAIT                            # a 20-min data gap restarts the clock
    hit_rate, judged = ctx.track_record(finding.code)
    if judged >= 5 and hit_rate <= 0.34:
        return SILENCED                        # wrong here two times in three
    return SAY

زیان فقط وقتی کنار یافته می‌آید که اندازه‌گیری شده باشد: از توان همین لحظه ضرب در سهم آن اینورتر از انرژی دیروز، یا از روزهای کامل آرشیو. یک حدس کنار دو عدد واقعی، هر سه را بی‌اعتبار می‌کند.

یک موضوع، یک یافته؛ و آدرس کامل

موتور تحلیل در چند دور بازسازی شده و هر دور آشکارسازی کنار قبلی‌ها گذاشته است. برای اینکه یک عیب چهار بار با چهار اسم گفته نشود، هر موضوع یک «مالک» دارد و بقیه برای همان اینورتر کنار می‌روند:

هر یافته، خطا و آلارم — در دسکتاپ، سرور، سایت شرکتی، اپ، وب‌اپ و اعلان گوشی — با آدرس کامل گفته می‌شود: «اینورتر ۲ · MPPT ۳ · رشته ۱» به‌همراه اختلاف اندازه‌گیری‌شده. آدرس هم در خود جمله می‌آید و هم به‌صورت فیلد ساخت‌یافته (location: {inverter, mppt, string})، تا هیچ صفحه‌ای مجبور به استخراج آن از متن نباشد. یافته‌ی تجمیعی (مثلاً یک الگو روی ۱۵ ورودی) هر ۱۵ عضو را با آدرس و عدد خودش فهرست می‌کند.

مدل زبانی: کجای زنجیره هست و کجا نیست

هیچ عدد، رتبه یا علتی را مدل زبانی انتخاب نمی‌کند. هر جمله‌ی گزارش از قالب و داده‌ی اندازه‌گیری‌شده ساخته می‌شود، چون درباره‌ی نیروگاهی است که کسی تا آنجا رانندگی می‌کند. مدل زبانی Qwen3-4B-Instruct (یا Qwen3-8B روی کامپیوتر ۱۶ گیگابایتی) فقط یک کار دارد: پاسخ به پرسش اپراتور در «از نیروگاه بپرس».

  1. بازیابی قطعی، نه ابزاربه یک مدل ۴ میلیارد پارامتری ابزار داده نمی‌شود (ابزار اشتباه یا آرگومان اشتباه را صدا می‌زند). برنامه خودش واقعیت‌ها را جمع می‌کند — فهرست زیان، یافته‌های باز، آلارم‌ها، تولید و پیش‌بینی با بازه — به ترتیب اهمیت و با سقف اندازه تا در پنجره‌ی متن جا شود.
  2. تولید مقید به متنمدل فقط از روی همان متن پاسخ می‌دهد، از طریق API سازگار با OpenAI روی 127.0.0.1. فرایند جداست: اگر حافظه کم بیاورد یا آنتی‌ویروس آن را ببندد، پایش ادامه دارد.
  3. راستی‌آزمایی عددیپاسخ پیش از نمایش بررسی می‌شود؛ اگر رد شود، خود واقعیت‌ها نمایش داده می‌شوند.
def check(answer: str, facts: str) -> bool:
    # every number in the answer must be a number the facts contain
    # (Persian/Arabic digits and thousands separators normalised first)
    if not numbers(answer) <= numbers(facts):
        return False      # "about 40" for 42 is computing; refuse
    # and stay with its inverter: a set of numbers cannot see
    # inverter 5's 31 kWh moved onto inverter 3
    for inverter, number in pairs(answer):
        if (inverter, number) not in pairs(facts):
            return False
    return True

در آزمایش پیش از انتشار، یک مدل کوچک‌تر تولید دیروز را با پیش‌بینی فردا جمع زد و همین بررسی جلوی آن را گرفت؛ و بازنویسی فارسی گزارش هفتگی توسط Qwen3-4B اینورترها را «دو نیروگاه خورشیدی» نامید — برای همین گزارش هفتگی بازنویسی نمی‌شود. مدل با کلید نصب برنامه یا از فلش نصب می‌شود، فایل‌هایش با SHA-256 تأیید می‌شوند، روی کامپیوتری با حافظه‌ی کمتر از ۸ گیگابایت نصب نمی‌شود، و بقیه‌ی برنامه بدون آن کامل کار می‌کند. Qwen2.5-3B به‌دلیل مجوزش عمداً کنار گذاشته شد.

چه چیزهایی را پیدا می‌کند

یافتهروشچرا آستانه‌ی ساده آن را نمی‌گیرد
رشته یا ورودی مرده، قطع ناگهانی، قطع‌ووصلتحلیلگر DC: سهم نمونه‌های زیر ۵٪ همتایان، نقطه‌ی تغییر، شمار افت به صفرمجموع اینورتر هنوز قابل قبول است
رشته‌ی موازیِ بازولتاژ عادی و جریان ورودی ≈ (n−۱)/n همتایانبسیاری از اینورترها جریان تک‌رشته را نمی‌دهند
اتصال کوتاه ورودیولتاژ کاری زیر ۱۰٪ همتایان در حالی که جریان داردجریان «عادی» به نظر می‌رسد
دیود بای‌پس، کمبود ماژولنسبت ولتاژ به همتایان در تمام ساعت‌های آفتابی، و Voc سحرگاهی (پیش از اتصال، ±۳ ولت بین ورودی‌ها؛ یک ماژول ≈ ۳۸ ولت، یک دیود ≈ ۱۳ ولت)جریان تقریباً تغییر نمی‌کند
سایه‌ی ثابتساعت‌هایی که هر روز پایین‌تر از ساعت‌های خوب همان ورودی‌اندمیانگین روز تقریباً عادی است
اینورتر کم‌تولید یا متوقف بدون خطافهرست زیان و مقایسه‌ی جریان رشته‌های هر اینورتر با اینورترهای دیگرعدد مطلق در محدوده‌ی مجاز می‌ماند
تنظیمات اشتباهدسته‌ی «تنظیمات»: ورودی‌ها و رشته‌ها (بالا)، توان بیش از پلاک، نسبت DC به AC، ظرفیت نیروگاههمه‌ی شاخص‌ها را آرام و ثابت خراب می‌کند
ساعت اینورترشمارنده‌ی روزانه‌ای که وسط روز صفر می‌شودشبیه افت تولید است ولی نیست
روند پیش از خرابیگرم‌تر شدن در بار مشابه (≥ ۶ درجه)، افت بازده تبدیل (≥ ۱ واحد)، خطایی که دو برابر بیشتر برمی‌گرددهر روز نسبت به دیروز تغییر ناچیز است
کیفیت توان و شبکهفقط از اینورتری که ≥ ۱ کیلووات تزریق دارد و همه‌ی فازهایش ≥ ۱۰۰ ولت استنمونه‌های لحظه‌ی بیدار شدن بی‌معنی‌اند
آلودگی و افت PRروزهای کامل و تابش روی صفحه‌ی پنل؛ روزهای گردوغبار جداتغییر روزانه ناچیز است

فهرست زیان: از «نشانه» به «تصمیم»

صاحب نیروگاه می‌پرسد: کدام اینورتر بیشترین انرژی را از من می‌گیرد، از کی، چرا، و آیا امروز ارزش فرستادن کسی را دارد؟ فهرست زیان از روزهای کامل اندازه‌گیری‌شده جواب می‌دهد: انرژی روز هر اینورتر از افزایش شمارنده‌ی کل عمر (حداکثر ۱۵ kWh/kW)، تقسیم بر ظرفیت پنل‌هایش و بر میانه‌ی همان روز بین همتایان؛ «کم‌تولید پایدار» (زیر ۰٫۹۵ در ۵ روز از ۷)، «افت تازه» (از یک روز مشخص زیر ۰٫۹۲) یا «بدون تولید»؛ زیان به کیلووات‌ساعت و ریال؛ و علت محتمل از خطاهای خود اینورتر یا یافته‌های تأییدشده — یا صادقانه «هنوز چیزی علت را توضیح نمی‌دهد».

یک نمونه‌ی واقعی: در اولین روز اجرای این لایه روی داده‌ی سرور، در یک نیروگاه ۳۵ اینورتری دو اینورتر روزانه حدود ۳۶۰ و ۲۸۶ کیلووات‌ساعت کمتر از همسایه‌هایشان تولید داشتند، بی هیچ کد خطایی.

معماری: تقسیم کار بر اساس تفکیک‌پذیری داده

کامپیوتر نیروگاه هر چند ثانیه همه‌ی رجیسترها را دارد؛ سرور هر چند دقیقه یک خلاصه می‌گیرد و در عوض تاریخچه‌ی سال‌ها و همه‌ی نیروگاه‌ها را دارد. الگویی که زیر یک ساعت رخ می‌دهد، در داده‌ی سرور اصلاً وجود ندارد — پس آنجا جست‌وجو نمی‌شود.

🖥️
لبه: کامپیوتر نیروگاه

کیفیت داده، لایه‌ی کانونی خطاها، تحلیلگر DC، بررسی تنظیمات، خط مبنای آموخته‌شده، دروازه‌ی شواهد، حافظه‌ی یافته‌ها، فهرست زیان، مدل زبانی اختیاری. مستقل از اینترنت.

☁️
سرور

تابش روی صفحه‌ی پنل، یادگیری ناوگان، افت PR ماهانه و سالانه، کنترل کیفیت پیام‌ها، سنجش دقت با بازخورد مالکان.

📱
نمایش

اپ، وب‌اپ، سایت شرکتی و پرتال استیشن. هیچ استنتاجی نمی‌کنند؛ اولویت، دسته و متن یک‌بار تعیین می‌شود و همه‌جا یکی است.

  1. نیروگاه به سرورMQTT روی TLS با امضای HMAC. هر یافته با کد، سطح یا دسته، آدرس، زیان اندازه‌گیری‌شده، درجه‌ی اطمینان، علت و راهکار. یافته‌ها بر اساس موضوع (کد + آدرس) یکی می‌شوند.
  2. دانش، نه داده‌ی خامهر نیروگاه روزی یک‌بار آماره‌های آموخته‌شده‌اش را می‌فرستد؛ سرور با میانه ادغام می‌کند و بسته‌ی ناوگان را با درخواست امضاشده برمی‌گرداند (برای نیروگاه بدون اینترنت، فایل .nai).
  3. بازخورد مالک«درست بود / چیزی نبود / برطرف شد» در دسکتاپ و (با پکیج نگهداری) در اپ و وب‌اپ؛ کامپیوتر نیروگاه آن را برمی‌دارد و در دفتر یافته‌ها ثبت می‌کند. درجه‌ی اطمینان یافته‌های بعدی بیش از هر چیز از همین کارنامه در همین نیروگاه می‌آید.

حاکمیت داده: هیچ داده‌ای از نیروگاه به خارج از کشور نمی‌رود و از هیچ سرویس تحریمی یا مسدودی استفاده نمی‌شود. مدل زبانی روی خود کامپیوتر نیروگاه اجرا می‌شود. تنها چیزی که بیرون می‌رود، مختصات هر نیروگاه است، روزی یک‌بار و فقط از سرور، برای داده‌ی هواشناسی.

محدودیت‌ها، بی‌پرده

پرسش‌های فنی

چرا شبکه‌ی عصبی یا یادگیری عمیق نه؟

داده‌ی برچسب‌خورده‌ی خرابی برای هر نیروگاه بسیار کم است و خرابی‌ها از نیروگاهی به نیروگاه دیگر فرق می‌کنند؛ یک مدل نظارت‌شده روی چنین داده‌ای بیش‌برازش می‌کند و یک مدل بی‌ناظر (مثلاً autoencoder) «غیرعادی» را بدون علت می‌گوید. مقایسه با همتا و آمار مقاوم بدون برچسب کار می‌کند، روی یک کامپیوتر معمولی و بدون GPU اجرا می‌شود، و هر یافته تا عدد اندازه‌گیری‌شده‌اش قابل ردیابی است. یافته‌ای که نشود توضیحش داد، کسی را سر سایت نمی‌فرستد.

خط مبنا چطور یاد گرفته می‌شود؟

از تاریخچه‌ی همین نیروگاه، مشروط به نقطه‌ی کار (باند بار)، نه ساعت روز: اگر بر اساس ساعت دسته‌بندی شود، ساعتی که امروز ارزیابی می‌شود ممکن است هرگز در آموزش دیده نشده باشد. هر شاخص کف نسبی خودش را دارد. ناوگان آستانه‌ی پیشنهادی می‌دهد ولی فقط یک انسان آن را می‌پذیرد، با ثبت نام و زمان، و همیشه قابل بازگشت است.

چرا ولتاژ سحرگاهی، وقتی ولتاژ ظهر هم خوانده می‌شود؟

ولتاژ ظهر ولتاژ کاری است و به نقطه‌ای که ردیاب MPPT انتخاب کرده بستگی دارد؛ در داده‌ی واقعی ورودی‌ای ۲۰ ولت پایین‌تر کار می‌کرد ولی ۷٪ جریان بیشتر و توان برابر داشت. پیش از اتصال صبحگاهی جریانی نیست و ولتاژ همان Voc است، و ورودی‌ها هنوز هم‌دما هستند.

اگر اپراتور یافته‌ای را «چیزی نبود» بزند چه می‌شود؟

در دفتر آن موضوع ثبت می‌شود. وقتی همان نوع یافته در همان نیروگاه دست‌کم ۵ بار قضاوت شده و دست‌کم دوسوم مواقع اشتباه بوده، دیگر گفته نمی‌شود. یافته‌ای که «برطرف شد» خورده و برگردد، با سابقه‌اش برمی‌گردد.

ادامه‌ی مطلب

بخش‌های دیگر نورانت

می‌خواهید بدانید در نیروگاه شما چه چیزی پنهان مانده؟

در جلسه‌ی دمو، تحلیل را روی داده‌ی واقعی نیروگاه خودتان نشان می‌دهیم.

همین شماره در واتساپ، تلگرام، ایتا و بله پاسخگوست.