از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
استفاده از یادگیری ماشینی برای پیش بینی آب و هوا: قسمت 1
سرفصلهای مطلب
قسمت 1: جمع آوری داده ها از آب و هوای زیرزمینی
این اولین مقاله از یک مجموعه چند قسمتی است روی استفاده از Python و Machine Learning برای ساخت مدل هایی برای پیش بینی دمای هوا بر اساس داده های جمع آوری شده از Weather Underground. این مجموعه از سه مقاله مختلف تشکیل شده است که جنبه های اصلی یک پروژه یادگیری ماشین را توضیح می دهد. موضوعاتی که قرار است پوشش داده شود عبارتند از:
- جمع آوری و پردازش داده ها (این مقاله)
- مدل های رگرسیون خطی (ماده 2)
- مدل های شبکه عصبی (ماده 3)
داده های مورد استفاده در این مجموعه از سرویس وب API لایه رایگان Weather Underground جمع آوری می شود. من از کتابخانه درخواستها برای تعامل با API برای جمعآوری دادههای آبوهوا از سال 2015 برای شهر لینکلن، نبراسکا استفاده خواهم کرد. پس از جمع آوری، داده ها باید جمع آوری شوند process و در قالبی که برای تجزیه و تحلیل داده ها مناسب است جمع آوری و سپس پاکسازی شود.
مقاله دوم تمرکز خواهد کرد روی تحلیل روند داده ها با هدف انتخاب ویژگی های مناسب برای ساخت الف رگرسیون خطی مدل با استفاده از مدل های آماری و scikit-یادگیری کتابخانه های پایتون من اهمیت درک مفروضات لازم برای استفاده از یک مدل رگرسیون خطی را مورد بحث قرار خواهم داد و نشان خواهم داد که چگونه می توان ویژگی ها را برای ساخت یک مدل قوی ارزیابی کرد. این مقاله با بحث در مورد آزمایش و اعتبارسنجی مدل رگرسیون خطی به پایان خواهد رسید.
مقاله نهایی تمرکز خواهد کرد روی با استفاده از شبکه های عصبی من مقایسه خواهم کرد process ساخت یک مدل شبکه عصبی، تفسیر نتایج و دقت کلی بین مدل رگرسیون خطی ساخته شده در مقاله قبلی و مدل شبکه عصبی.
آشنایی با آب و هوای زیرزمینی
آب و هوا زیرزمینی شرکتی است که داده ها را جمع آوری و توزیع می کند روی اندازه گیری های مختلف آب و هوا در سراسر جهان این شرکت مجموعه ای از API ها را ارائه می دهد که هم برای استفاده های تجاری و هم برای استفاده های غیر تجاری در دسترس هستند. در این مقاله، روش برداشت برنامهای دادههای آب و هوای روزانه از Weather Underground را با استفاده از سطح رایگان خدمات موجود برای اهداف غیرتجاری شرح خواهم داد.
اگر می خواهید همراه با آموزش دنبال کنید، می خواهید برای حساب توسعه دهنده رایگان آنها در اینجا ثبت نام کنید. این حساب یک کلید API برای دسترسی به وب سرویس با نرخ 10 درخواست در دقیقه و در مجموع حداکثر 500 درخواست در روز ارائه می دهد.
Weather Underground بسیاری از API های سرویس وب مختلف را برای دسترسی به داده ها ارائه می دهد، اما موردی که ما به آن توجه خواهیم کرد API تاریخچه آنها است. تاریخچه API خلاصه ای از اندازه گیری های مختلف آب و هوا برای یک شهر و ایالت را ارائه می دهد روی یک روز خاص
فرمت درخواست منبع تاریخچه API به شرح زیر است:
http://api.wunderground.com/api/API_KEY/history_YYYYMMDD/q/STATE/CITY.json
API_KEY
: API_KEY که Weather Underground با حساب شما ارائه می کندYYYYMMDD
: رشته ای که تاریخ هدف درخواست شما را نشان می دهدSTATE
: مخفف حالت دو حرفی در ایالات متحده استCITY
: نام شهر مرتبط با ایالتی که درخواست کردید
درخواست به API
برای درخواست به Weather Underground history API و process داده های برگشتی از چند کتابخانه استاندارد و همچنین برخی از کتابخانه های محبوب شخص ثالث استفاده خواهم کرد. در زیر جدولی از کتابخانه هایی که استفاده خواهم کرد و توضیحات آنها آمده است. برای دستورالعملهای نصب، لطفاً به اسناد ذکر شده مراجعه کنید.
کتابخانه | شرح استفاده | Source |
---|---|---|
زمان قرار | برای افزایش درخواست های ما در روز استفاده می شود | کتابخانه استاندارد |
زمان | برای به تأخیر انداختن درخواست های اقامت زیر 10 در دقیقه استفاده می شود | کتابخانه استاندارد |
مجموعه ها | از namedtuples برای جمع آوری ساختار یافته داده ها استفاده کنید | کتابخانه استاندارد |
پانداها | عادت داشتن process، داده ها را سازماندهی و تمیز کنید | کتابخانه شخص ثالث |
درخواست ها | برای ایجاد درخواست های شبکه ای به API استفاده می شود | کتابخانه شخص ثالث |
matplotlib | برای تجزیه و تحلیل گرافیکی استفاده می شود | کتابخانه شخص ثالث |
اجازه دهید با وارد کردن این کتابخانه ها شروع کنیم:
from datetime import datetime, timedelta
import time
from collections import namedtuple
import pandas as pd
import requests
import matplotlib.pyplot as plt
حالا من چند ثابت را تعریف می کنم که من را نشان می دهد API_KEY
و BASE_URL
از نقطه پایانی API که درخواست خواهم کرد. توجه داشته باشید که باید برای یک حساب کاربری با Weather Underground ثبت نام کنید و حساب خود را دریافت کنید API_KEY
. تا زمانی که این مقاله منتشر شود، این یکی را غیرفعال خواهم کرد.
BASE_URL
یک رشته با دو نگهدارنده مکان است که با براکت های مجعد نشان داده شده است. اولین {}
توسط پر خواهد شد API_KEY
و دومی {}
با یک تاریخ قالب بندی رشته ای جایگزین می شود. هر دو مقدار در درون یابی می شوند BASE_URL
رشته با استفاده از str.format (…) تابع.
API_KEY = '7052ad35e3c73564'
BASE_URL = "http://api.wunderground.com/api/{}/history_{}/q/NE/Lincoln.json"
سپس تاریخ هدف را به اولین روز سال در سال 2015 مقداردهی می کنم. سپس ویژگی هایی را که می خواهم از پاسخ های برگردانده شده از API تجزیه و تحلیل کنم، مشخص می کنم. ویژگی ها به سادگی کلیدهای موجود در هستند history -> dailysummary
بخشی از پاسخ JSON از این ویژگی ها برای تعریف a استفاده می شود namedtuple
تماس گرفت DailySummary
که من از آن برای سازماندهی داده های درخواست فردی در لیستی از تاپل های DailySummary استفاده خواهم کرد.
target_date = datetime(2016, 5, 16)
features = ("date", "meantempm", "meandewptm", "meanpressurem", "maxhumidity", "minhumidity", "maxtempm",
"mintempm", "maxdewptm", "mindewptm", "maxpressurem", "minpressurem", "precipm")
DailySummary = namedtuple("DailySummary", features)
در این بخش، درخواستهای واقعی را به API انجام میدهم و پاسخهای موفق را با استفاده از تابع تعریف شده در زیر جمعآوری میکنم. این تابع پارامترها را می گیرد url
، api_key
، target_date
و days
.
def extract_weather_data(url, api_key, target_date, days):
records = ()
for _ in range(days):
request = BASE_URL.format(API_KEY, target_date.strftime('%Y%m%d'))
response = requests.get(request)
if response.status_code == 200:
data = response.json()('history')('dailysummary')(0)
records.append(DailySummary(
date=target_date,
meantempm=data('meantempm'),
meandewptm=data('meandewptm'),
meanpressurem=data('meanpressurem'),
maxhumidity=data('maxhumidity'),
minhumidity=data('minhumidity'),
maxtempm=data('maxtempm'),
mintempm=data('mintempm'),
maxdewptm=data('maxdewptm'),
mindewptm=data('mindewptm'),
maxpressurem=data('maxpressurem'),
minpressurem=data('minpressurem'),
precipm=data('precipm')))
time.sleep(6)
target_date += timedelta(days=1)
return records
من با تعریف لیستی به نام رکوردها شروع می کنم که داده های تجزیه شده را به عنوان نگه می دارد DailySummary
namedtuple
س حلقه for طوری تعریف می شود که برای تعداد روزهایی که به تابع منتقل می شود روی حلقه تکرار می شود.
سپس درخواست با استفاده از فرمت می شود str.format()
تابع درون یابی API_KEY
و رشته فرمت شده است target_date
هدف – شی. پس از قالب بندی، متغیر درخواست به آن ارسال می شود get()
روش از requests
شی و پاسخ به متغیری به نام تخصیص داده می شود response
.
با بازگشت پاسخ، میخواهم با ارزیابی اینکه کد وضعیت HTTP برابر با 200 است، مطمئن شوم که درخواست موفقیتآمیز بوده است. اگر موفقیت آمیز بود، بدنه پاسخ را با استفاده از JSON به JSON تجزیه میکنم. json()
متد شی پاسخ برگشتی زنجیر شده به همان json()
فراخوانی متد، فهرستهای تاریخچه و ساختارهای خلاصه روزانه را انتخاب میکنم، سپس اولین مورد را در آن میگیرم dailysummary
لیست کنید و آن را به متغیری با نام اختصاص دهید data
.
اکنون که ساختار دادهای شبیه dict را دارم که به آن ارجاع داده شده است data
متغیر من می توانم فیلدهای مورد نظر را انتخاب کنم و نمونه جدیدی از آن را نمونه سازی کنم DailySummary
namedtuple
که به ضمیمه شده است records
فهرست
در نهایت، هر تکرار از حلقه با فراخوانی به پایان می رسد sleep
روش ماژول زمان برای توقف اجرای حلقه به مدت شش ثانیه، تضمین می کند که بیش از 10 درخواست در دقیقه انجام نمی شود و ما را در محدوده Weather Underground نگه می دارد.
سپس target_date
با استفاده از 1 روز افزایش می یابد timedelta
موضوع از datetime
ماژول، بنابراین تکرار بعدی حلقه، خلاصه روزانه را برای روز بعد بازیابی می کند.
اولین دسته از درخواست ها
بدون تأخیر بیشتر، اولین مجموعه درخواستها را برای حداکثر درخواست اختصاص داده شده روزانه تحت حساب توسعهدهنده رایگان 500 شروع میکنم. سپس به شما پیشنهاد میکنم قهوه (یا نوشیدنی ترجیحی دیگر) خود را دوباره پر کنید و درگیر شوید. روی برنامه تلویزیونی مورد علاقه شما، زیرا بسته به عملکرد حداقل یک ساعت طول می کشد روی تأخیر شبکه با این کار، ما درخواستهای روزانه خود را به حداکثر رساندهایم، و این فقط نیمی از دادههایی است که با آن کار خواهیم کرد.
بنابراین، فردا برگردید، جایی که آخرین دسته درخواستها را تکمیل میکنیم، سپس میتوانیم کار را شروع کنیم روی پردازش و قالب بندی داده ها به روشی مناسب برای پروژه یادگیری ماشین ما.
records = extract_weather_data(BASE_URL, API_KEY, target_date, 500)
اتمام بازیابی داده ها
بسیار خوب، اکنون که روز جدیدی است، ما یک صفحه تمیز و حداکثر 500 درخواست داریم که میتوان به API تاریخچه آب و هوای زیرزمینی ارسال کرد. دسته ای از 500 درخواست ما که دیروز صادر شد آغاز شد روی 1 ژانویه 2015 و به پایان رسید روی 15 مه 2016 (با فرض اینکه هیچ درخواست ناموفقی نداشته باشید). یک بار دیگر اجازه دهید دسته ای دیگر از 500 درخواست را شروع کنیم، اما، این بار من را برای این روز رها نکنید، زیرا هنگامی که این آخرین تکه داده جمع آوری شد، ما شروع به قالب بندی آن به یک Pandas DataFrame می کنیم و ویژگی های بالقوه مفیدی را استخراج می کنیم.
records += extract_weather_data(BASE_URL, API_KEY, target_date, 500)
راه اندازی Pandas DataFrame ما
اکنون که من یک لیست رکوردهای خوب و قابل توجهی دارم DailySummary
به نام tuples من از آن برای ساخت یک استفاده خواهم کرد Pandas DataFrame. Pandas DataFrame یک ساختار داده بسیار مفید برای بسیاری از کارهای برنامه نویسی است که بیشتر برای تمیز کردن و پردازش داده ها برای استفاده در پروژه ها (یا آزمایشات) یادگیری ماشین شناخته شده است.
من استفاده خواهم کرد Pandas.DataFrame(...)
سازنده کلاس برای نمونه سازی یک شی DataFrame. پارامترهای ارسال شده به سازنده رکوردهایی هستند که داده های DataFrame را نشان می دهند، لیست ویژگی هایی که من نیز برای تعریف آن استفاده کردم. DailySummary
namedtuple
s که ستون های DataFrame را مشخص می کند. این set_index()
متد به نمونه DataFrame زنجیر می شود تا تاریخ را به عنوان شاخص مشخص کند.
df = pd.DataFrame(records, columns=features).set_index('date')
استخراج ویژگی ها
پروژههای یادگیری ماشینی که به آنها آزمایش نیز گفته میشود، اغلب دارای چند ویژگی هستند که کمی به هم ریخته هستند. منظور من این است که داشتن دانش موضوعی در حوزه مورد بررسی برای کمک به انتخاب ویژگی های معنادار برای بررسی همراه با یک فرض متفکرانه از الگوهای احتمالی در داده ها بسیار مفید است.
با این حال، من متغییرها و الگوهای توضیحی بسیار تأثیرگذار را نیز دیدهام که از پیشفرضهای تقریباً سادهلوحانه یا حداقل بسیار باز و حداقلی در مورد دادهها ناشی میشوند. داشتن شهود مبتنی بر دانش برای دانستن اینکه کجا باید ویژگیها و الگوهای مفید بالقوه را جستجو کرد و همچنین توانایی جستجوی ویژگیهای غیرقابل پیشبینی به شیوهای بیطرفانه بخش بسیار مهمی از یک پروژه تحلیلی موفق است.
در این راستا، ما چندین ویژگی را در حین تجزیه داده های خلاصه روزانه بازگشتی برای استفاده در مطالعه خود انتخاب کرده ایم. با این حال، من کاملاً انتظار دارم که بسیاری از این موارد در پیشبینی دمای هوا یا نامزدهای نامناسب باشند. روی نوع مدلی که استفاده می شود، اما نکته اصلی این است که تا زمانی که داده ها را به دقت بررسی نکنید، نمی دانید.
اکنون نمی توانم بگویم که دانش قابل توجهی از هواشناسی یا مدل های پیش بینی آب و هوا دارم، اما یک جستجوی حداقلی در کار قبلی انجام دادم. روی استفاده از یادگیری ماشینی برای پیش بینی دمای هوا همانطور که مشخص است تعداد زیادی مقاله تحقیقاتی وجود دارد روی موضوع و در سال 2016 Holmstrom، Liu، و Vo استفاده از رگرسیون خطی را برای انجام این کار توصیف کردند. در مقاله خود، یادگیری ماشینی برای پیش بینی آب و هوا به کار می رود، آنها از داده های آب و هوا استفاده کردند روی دو روز قبل برای اندازه گیری های زیر
- حداکثر دما
- دمای دقیقه
- میانگین رطوبت
- میانگین فشار اتمسفر
من لیست ویژگی های آنها را با استفاده از موارد ذکر شده در زیر گسترش خواهم داد و به جای استفاده از دو روز قبل، سه روز به عقب باز خواهم گشت.
- میانگین دما
- میانگین نقطه شبنم
- فشار متوسط
- حداکثر رطوبت
- حداقل رطوبت
- حداکثر نقطه شبنم
- نقطه شبنم دقیقه
- حداکثر فشار
- حداقل فشار
- ته نشینی
بنابراین، راه بعدی پیدا کردن راهی برای گنجاندن این ویژگی های جدید به عنوان ستون در DataFrame ما است. برای انجام این کار، یک زیرمجموعه کوچکتر از DataFrame فعلی ایجاد می کنم تا کار با آن را در حین توسعه الگوریتمی برای ایجاد این ویژگی ها آسان تر کنم. یک را خواهم ساخت tmp
DataFrame فقط از 10 رکورد و ویژگی ها تشکیل شده است meantempm
و meandewptm
.
tmp = df(('meantempm', 'meandewptm')).head(10)
tmp
تاریخ | meantempm | meandewptm |
---|---|---|
01-01-2015 | -6 | -12 |
02/01/2015 | -6 | -9 |
03/01/2015 | -4 | -11 |
04/01/2015 | -14 | -19 |
05/01/2015 | -9 | -14 |
06/01/2015 | -10 | -15 |
07/01/2015 | -16 | -22 |
08/01/2015 | -7 | -12 |
09/01/2015 | -11 | -19 |
2015/01/10 | -6 | -12 |
اجازه دهید آنچه را که امیدواریم انجام دهیم، تجزیه و سپس آن را به کد ترجمه کنیم. برای هر روز (ردیف) و برای یک ویژگی معین (ستون) می خواهم مقدار آن ویژگی را N روز قبل پیدا کنم. برای هر مقدار N (در مورد ما 1-3) میخواهم یک ستون جدید برای آن ویژگی ایجاد کنم که نشاندهنده Nامین اندازهگیری روز قبل است.
N = 1
feature = 'meantempm'
rows = tmp.shape(0)
nth_prior_measurements = (None)*N + (tmp(feature)(i-N) for i in range(N, rows))
col_name = "{}_{}".format(feature, N)
tmp(col_name) = nth_prior_measurements
tmp
تاریخ | meantempm | meandewptm | meantempm_1 |
---|---|---|---|
01-01-2015 | -6 | -12 | هیچ یک |
02/01/2015 | -6 | -9 | -6 |
03/01/2015 | -4 | -11 | -6 |
04/01/2015 | -14 | -19 | -4 |
05/01/2015 | -9 | -14 | -14 |
06/01/2015 | -10 | -15 | -9 |
07/01/2015 | -16 | -22 | -10 |
08/01/2015 | -7 | -12 | -16 |
09/01/2015 | -11 | -19 | -7 |
2015/01/10 | -6 | -12 | -11 |
بسیار خوب، بنابراین به نظر می رسد که ما مراحل اولیه مورد نیاز برای ایجاد ویژگی های جدید خود را داریم. اکنون این مراحل را در یک تابع قابل استفاده مجدد قرار می دهم و آن را برای ایجاد تمام ویژگی های مورد نظر کار می کنم.
def derive_nth_day_feature(df, feature, N):
rows = df.shape(0)
nth_prior_measurements = (None)*N + (df(feature)(i-N) for i in range(N, rows))
col_name = "{}_{}".format(feature, N)
df(col_name) = nth_prior_measurements
اکنون یک حلقه برای چرخش بر روی ویژگیهای لیست ویژگیهایی که قبلاً تعریف شده است مینویسم، و برای هر ویژگی که “تاریخ” نیست و برای N روز 1 تا 3 ما تابع خود را فراخوانی میکنیم تا ویژگیهای مشتق شدهای را که میخواهیم ارزیابی کنیم، اضافه کنیم. برای پیش بینی دما
for feature in features:
if feature != 'date':
for N in range(1, 4):
derive_nth_day_feature(df, feature, N)
و برای اندازه گیری خوب، نگاهی به ستون ها می اندازم تا مطمئن شوم که مطابق انتظار به نظر می رسند.
df.columns
Index(('meantempm', 'meandewptm', 'meanpressurem', 'maxhumidity',
'minhumidity', 'maxtempm', 'mintempm', 'maxdewptm', 'mindewptm',
'maxpressurem', 'minpressurem', 'precipm', 'meantempm_1', 'meantempm_2',
'meantempm_3', 'meandewptm_1', 'meandewptm_2', 'meandewptm_3',
'meanpressurem_1', 'meanpressurem_2', 'meanpressurem_3',
'maxhumidity_1', 'maxhumidity_2', 'maxhumidity_3', 'minhumidity_1',
'minhumidity_2', 'minhumidity_3', 'maxtempm_1', 'maxtempm_2',
'maxtempm_3', 'mintempm_1', 'mintempm_2', 'mintempm_3', 'maxdewptm_1',
'maxdewptm_2', 'maxdewptm_3', 'mindewptm_1', 'mindewptm_2',
'mindewptm_3', 'maxpressurem_1', 'maxpressurem_2', 'maxpressurem_3',
'minpressurem_1', 'minpressurem_2', 'minpressurem_3', 'precipm_1',
'precipm_2', 'precipm_3'),
dtype='object')
عالی! به نظر می رسد آنچه را که نیاز داریم داریم. کار بعدی که می خواهم انجام دهم این است که کیفیت داده ها را ارزیابی کرده و در صورت لزوم آن ها را پاکسازی کنم.
پاکسازی داده ها – مهمترین بخش
همانطور که عنوان بخش می گوید، مهمترین بخش یک پروژه تحلیلی این است که مطمئن شوید از داده های با کیفیت استفاده می کنید. ضرب المثل “زباله داخل، زباله بیرون” مثل همیشه در مورد یادگیری ماشینی مناسب است. با این حال، بخش تمیز کردن دادهها در یک پروژه تحلیلی نه تنها یکی از مهمترین بخشها است، بلکه زمانبرترین و پر زحمتترین بخش نیز است. برای اطمینان از کیفیت دادههای این پروژه، در این بخش به دنبال شناسایی دادههای غیرضروری، مقادیر از دست رفته، سازگاری انواع دادهها و موارد پرت هستم و سپس در مورد روش رسیدگی به آنها در صورت بروز تصمیمگیری میکنم.
اولین کاری که میخواهم انجام دهم این است که ستونهایی از DataFrame را که علاقهای به آنها ندارم رها کنم تا حجم دادهای را که با آن کار میکنم کاهش دهم. هدف این پروژه پیش بینی دمای آینده بر اساس سه روز گذشته اندازه گیری آب و هوا است. با در نظر گرفتن این موضوع، ما فقط میخواهیم حداقل، حداکثر و میانگین دما را برای هر روز به اضافه همه متغیرهای مشتق شده جدیدی که در بخشهای گذشته اضافه کردیم، حفظ کنیم.
to_remove = (feature
for feature in features
if feature not in ('meantempm', 'mintempm', 'maxtempm'))
to_keep = (col for col in df.columns if col not in to_remove)
df = df(to_keep)
df.columns
Index(('meantempm', 'maxtempm', 'mintempm', 'meantempm_1', 'meantempm_2',
'meantempm_3', 'meandewptm_1', 'meandewptm_2', 'meandewptm_3',
'meanpressurem_1', 'meanpressurem_2', 'meanpressurem_3',
'maxhumidity_1', 'maxhumidity_2', 'maxhumidity_3', 'minhumidity_1',
'minhumidity_2', 'minhumidity_3', 'maxtempm_1', 'maxtempm_2',
'maxtempm_3', 'mintempm_1', 'mintempm_2', 'mintempm_3', 'maxdewptm_1',
'maxdewptm_2', 'maxdewptm_3', 'mindewptm_1', 'mindewptm_2',
'mindewptm_3', 'maxpressurem_1', 'maxpressurem_2', 'maxpressurem_3',
'minpressurem_1', 'minpressurem_2', 'minpressurem_3', 'precipm_1',
'precipm_2', 'precipm_3'),
dtype='object')
کار بعدی که میخواهم انجام دهم این است که از برخی توابع داخلی پاندا استفاده کنم تا درک بهتری از دادهها داشته باشم و به طور بالقوه مناطقی را برای تمرکز انرژی خود شناسایی کنم. روی. اولین تابع یک متد DataFrame است که نامیده می شود info()
که، شگفتی بزرگ … اطلاعاتی را ارائه می دهد روی DataFrame ستون “نوع داده” خروجی مورد توجه است.
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1000 entries, 2015-01-01 to 2017-09-27
Data columns (total 39 columns):
meantempm 1000 non-null object
maxtempm 1000 non-null object
mintempm 1000 non-null object
meantempm_1 999 non-null object
meantempm_2 998 non-null object
meantempm_3 997 non-null object
meandewptm_1 999 non-null object
meandewptm_2 998 non-null object
meandewptm_3 997 non-null object
meanpressurem_1 999 non-null object
meanpressurem_2 998 non-null object
meanpressurem_3 997 non-null object
maxhumidity_1 999 non-null object
maxhumidity_2 998 non-null object
maxhumidity_3 997 non-null object
minhumidity_1 999 non-null object
minhumidity_2 998 non-null object
minhumidity_3 997 non-null object
maxtempm_1 999 non-null object
maxtempm_2 998 non-null object
maxtempm_3 997 non-null object
mintempm_1 999 non-null object
mintempm_2 998 non-null object
mintempm_3 997 non-null object
maxdewptm_1 999 non-null object
maxdewptm_2 998 non-null object
maxdewptm_3 997 non-null object
mindewptm_1 999 non-null object
mindewptm_2 998 non-null object
mindewptm_3 997 non-null object
maxpressurem_1 999 non-null object
maxpressurem_2 998 non-null object
maxpressurem_3 997 non-null object
minpressurem_1 999 non-null object
minpressurem_2 998 non-null object
minpressurem_3 997 non-null object
precipm_1 999 non-null object
precipm_2 998 non-null object
precipm_3 997 non-null object
dtypes: object(39)
memory usage: 312.5+ KB
توجه داشته باشید که نوع داده هر ستون از نوع “object” است. برای نوع تحلیل عددی که امیدواریم انجام دهیم، باید همه این ستونهای ویژگی را به شناور تبدیل کنیم. برای این کار از apply()
روش DataFrame برای اعمال پانداها to_numeric
روش به تمام مقادیر DataFrame. این error='coerce'
پارامتر هر مقدار متنی را پر می کند NaNs. یافتن مقادیر متنی در دادههای وحشی که معمولاً از جمعآورنده دادهها که در آن دادهها گم شده یا نامعتبر است، منشأ میگیرند، معمول است.
df = df.apply(pd.to_numeric, errors='coerce')
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1000 entries, 2015-01-01 to 2017-09-27
Data columns (total 39 columns):
meantempm 1000 non-null int64
maxtempm 1000 non-null int64
mintempm 1000 non-null int64
meantempm_1 999 non-null float64
meantempm_2 998 non-null float64
meantempm_3 997 non-null float64
meandewptm_1 999 non-null float64
meandewptm_2 998 non-null float64
meandewptm_3 997 non-null float64
meanpressurem_1 999 non-null float64
meanpressurem_2 998 non-null float64
meanpressurem_3 997 non-null float64
maxhumidity_1 999 non-null float64
maxhumidity_2 998 non-null float64
maxhumidity_3 997 non-null float64
minhumidity_1 999 non-null float64
minhumidity_2 998 non-null float64
minhumidity_3 997 non-null float64
maxtempm_1 999 non-null float64
maxtempm_2 998 non-null float64
maxtempm_3 997 non-null float64
mintempm_1 999 non-null float64
mintempm_2 998 non-null float64
mintempm_3 997 non-null float64
maxdewptm_1 999 non-null float64
maxdewptm_2 998 non-null float64
maxdewptm_3 997 non-null float64
mindewptm_1 999 non-null float64
mindewptm_2 998 non-null float64
mindewptm_3 997 non-null float64
maxpressurem_1 999 non-null float64
maxpressurem_2 998 non-null float64
maxpressurem_3 997 non-null float64
minpressurem_1 999 non-null float64
minpressurem_2 998 non-null float64
minpressurem_3 997 non-null float64
precipm_1 889 non-null float64
precipm_2 889 non-null float64
precipm_3 888 non-null float64
dtypes: float64(36), int64(3)
memory usage: 312.5 KB
اکنون که همه دادههای ما دارای نوع دادهای هستند که من میخواهم، میخواهم نگاهی به برخی از آمار خلاصه ویژگیها بیندازم و از قانون آماری آماری برای بررسی وجود نقاط پرت شدید استفاده کنم. روش DataFrame describe()
یک DataFrame حاوی تعداد، میانگین، انحراف معیار، حداقل، صدک 25، صدک 50 (یا میانه)، صدک 75 و حداکثر مقدار تولید می کند. این می تواند اطلاعات بسیار مفیدی برای ارزیابی توزیع داده های ویژگی باشد.
من می خواهم با محاسبه ستون خروجی دیگری که نشان دهنده وجود نقاط پرت است به این اطلاعات اضافه کنم. قاعده کلی برای شناسایی یک نقطه پرت شدید مقداری است که کمتر از 3 باشد محدوده های بین چارکی زیر صدک 25 یا 3 محدوده بین چارکی بالاتر از صدک 75. محدوده بین چارکی به سادگی تفاوت بین صدک 75 و صدک 25 است.
spread = df.describe().T
IQR = spread('75%') - spread('25%')
spread('outliers') = (spread('min')<(spread('25%')-(3*IQR)))|(spread('max') > (spread('75%')+3*IQR))
spread.ix(spread.outliers,)
شمردن | منظور داشتن | std | دقیقه | 25% | 50% | 75% | حداکثر | موارد پرت | |
---|---|---|---|---|---|---|---|---|---|
حداکثر رطوبت_1 | 999.0 | 88.107107 | 9.273053 | 47.0 | 83.0 | 90.0 | 93.00 | 100.00 | درست است، واقعی |
حداکثر رطوبت_2 | 998.0 | 88.102204 | 9.276407 | 47.0 | 83.0 | 90.0 | 93.00 | 100.00 | درست است، واقعی |
حداکثر رطوبت_3 | 997.0 | 88.093280 | 9.276775 | 47.0 | 83.0 | 90.0 | 93.00 | 100.00 | درست است، واقعی |
maxpressurem_1 | 999.0 | 1019.924925 | 7.751874 | 993.0 | 1015.0 | 1019.0 | 1024.00 | 1055.00 | درست است، واقعی |
maxpressurem_2 | 998.0 | 1019.922846 | 7.755482 | 993.0 | 1015.0 | 1019.0 | 1024.00 | 1055.00 | درست است، واقعی |
maxpressurem_3 | 997.0 | 1019.927783 | 7.757805 | 993.0 | 1015.0 | 1019.0 | 1024.00 | 1055.00 | درست است، واقعی |
minpressurem_1 | 999.0 | 1012.329329 | 7.882062 | 956.0 | 1008.0 | 1012.0 | 1017.00 | 1035.00 | درست است، واقعی |
minpressurem_2 | 998.0 | 1012.326653 | 7.885560 | 956.0 | 1008.0 | 1012.0 | 1017.00 | 1035.00 | درست است، واقعی |
minpressurem_3 | 997.0 | 1012.326981 | 7.889511 | 956.0 | 1008.0 | 1012.0 | 1017.00 | 1035.00 | درست است، واقعی |
precipm_1 | 889.0 | 2.908211 | 8.874345 | 0.0 | 0.0 | 0.0 | 0.51 | 95.76 | درست است، واقعی |
precipm_2 | 889.0 | 2.908211 | 8.874345 | 0.0 | 0.0 | 0.0 | 0.51 | 95.76 | درست است، واقعی |
precipm_3 | 888.0 | 2.888885 | 8.860608 | 0.0 | 0.0 | 0.0 | 0.51 | 95.76 | درست است، واقعی |
ارزیابی تاثیر بالقوه نقاط دورافتاده بخش دشواری از هر پروژه تحلیلی است. از یک طرف، شما باید نگران پتانسیل معرفی مصنوعات داده های جعلی باشید که به طور قابل توجهی بر مدل های شما تأثیر می گذارد یا سوگیری می کند. از سوی دیگر، نقاط پرت می توانند در پیش بینی نتایجی که در شرایط خاص به وجود می آیند بسیار معنادار باشند. ما در مورد هر یک از این موارد پرت که حاوی ویژگیها هستند بحث خواهیم کرد و خواهیم دید که آیا میتوانیم به یک نتیجه معقول در مورد روش برخورد با آنها برسیم.
به نظر می رسد اولین مجموعه از ویژگی ها به حداکثر رطوبت مربوط می شود. با نگاه کردن به داده ها می توانم بگویم که نقطه پرت برای این دسته ویژگی به دلیل مقدار کم ظاهرا بسیار کم است. در واقع به نظر می رسد که این مقدار بسیار کم است و من فکر می کنم می خواهم نگاهی دقیق تر به آن بیندازم، ترجیحاً به صورت گرافیکی. برای این کار از هیستوگرام استفاده می کنم.
%matplotlib inline
plt.rcParams('figure.figsize') = (14, 8)
df.maxhumidity_1.hist()
plt.title('Distribution of maxhumidity_1')
plt.xlabel('maxhumidity_1')
plt.show()
نگاهی به هیستوگرام مقادیر برای maxhumidity
دادهها کمی انحراف منفی را نشان میدهند. من می خواهم این را در هنگام انتخاب مدل های پیش بینی و ارزیابی قدرت تأثیر حداکثر رطوبت در نظر داشته باشم. بسیاری از روش های آماری اساسی فرض می کنند که داده ها به طور معمول توزیع شده اند. در حال حاضر فکر می کنم آنها را به حال خود رها خواهم کرد، اما خوب است که این را در ذهن داشته باشیم و نسبت به آن شک و تردید داشته باشیم.
در ادامه به توزیع ویژگی فشار حداقل می پردازم.
df.minpressurem_1.hist()
plt.title('Distribution of minpressurem_1')
plt.xlabel('minpressurem_1')
plt.show()
این طرح ویژگی جالب دیگری را به نمایش می گذارد. از این نمودار، داده ها است چند وجهی، که من را به این باور می رساند که دو مجموعه بسیار متفاوت از شرایط محیطی در این داده ها آشکار است. من در حذف این مقادیر مردد هستم زیرا می دانم که نوسانات دما در این منطقه از کشور می تواند بسیار شدید باشد به خصوص در بین فصول سال. من نگران هستم که حذف این مقادیر پایین ممکن است سودمندی توضیحی داشته باشد، اما یک بار دیگر در همان زمان در مورد آن تردید خواهم داشت.
طبقه بندی نهایی ویژگی های حاوی نقاط پرت، یعنی بارش، کمی راحت تر قابل درک است. از آنجایی که روزهای خشک (یعنی بدون بارندگی) بسیار بیشتر است، دیدن نقاط پرت در اینجا معقول است. برای من این دلیلی برای حذف این ویژگی ها نیست.
آخرین مشکل کیفیت داده که باید به آن پرداخته شود، کمبود مقادیر است. با توجه به روشی که من DataFrame را ساختهام، مقادیر از دست رفته توسط NaNs نشان داده میشوند. احتمالاً به خاطر دارید که من عمداً مقادیر گمشده را برای سه روز اول دادههای جمعآوریشده با استخراج ویژگیهایی که سه روز قبل از اندازهگیریها را نشان میدهند، معرفی کردهام. تا روز سوم نیست که میتوانیم آن ویژگیها را استخراج کنیم، بنابراین واضح است که میخواهم آن سه روز اول را از مجموعه دادهها حذف کنم.
دوباره به خروجی آخرین باری که من صادر کردم نگاه کنید info
روش. یک ستون خروجی وجود دارد که مقادیر غیر تهی را برای هر ستون ویژگی فهرست می کند. با نگاهی به این اطلاعات می توانید ببینید که در بیشتر موارد ویژگی ها حاوی مقادیر نسبتاً کمی گمشده (تهی / NaN) هستند، عمدتاً فقط مواردی که من معرفی کردم. با این حال، به نظر می رسد که ستون های بارش بخش قابل توجهی از داده های خود را از دست داده اند.
داده های از دست رفته یک مشکل ایجاد می کند زیرا اکثر روش های یادگیری ماشینی به مجموعه داده های کامل و عاری از هرگونه داده از دست رفته نیاز دارند. جدا از این موضوع که بسیاری از روشهای یادگیری ماشینی به دادههای کامل نیاز دارند، اگر بخواهم تمام ردیفها را فقط به این دلیل حذف کنم که ویژگی بارش حاوی دادههای از دست رفته است، بسیاری از اندازهگیریهای ویژگی مفید دیگر را حذف میکنم.
همانطور که می بینم من چند گزینه برای مقابله با این مشکل داده های از دست رفته دارم:
- من به سادگی میتوانم ردیفهایی را که حاوی مقادیر از دست رفته هستند حذف کنم، اما همانطور که قبلاً اشاره کردم با بیرون ریختن این مقدار داده، مقدار زیادی از دادهها حذف میشود.
- من می توانم مقادیر از دست رفته را با یک مقدار درون یابی شده پر کنم که تخمین معقولی از مقادیر واقعی است.
از آنجایی که ترجیح میدهم تا آنجا که میتوانم دادهها را حفظ کنم، در جایی که کمترین خطر وارد کردن مقادیر اشتباه وجود دارد، میخواهم مقادیر بارش از دست رفته را با رایجترین مقدار صفر پر کنم. من احساس می کنم این یک تصمیم معقول است زیرا اکثر مقادیر در اندازه گیری های بارش صفر هستند.
for precip_col in ('precipm_1', 'precipm_2', 'precipm_3'):
missing_vals = pd.isnull(df(precip_col))
df(precip_col)(missing_vals) = 0
اکنون که تمام مقادیر از دست رفته را که میتوانم پر کردهام، در حالی که مراقب بودم تأثیر منفی بر کیفیت نداشته باشم، راحت میتوانم رکوردهای باقیمانده حاوی مقادیر گمشده را از مجموعه دادهها حذف کنم. رها کردن ردیف هایی از DataFrame حاوی NaN بسیار آسان است. تنها کاری که باید انجام دهم این است که متد را فراخوانی کنم dropna()
و پانداها همه کارها را برای من انجام خواهند داد.
df = df.dropna()
منابع
آیا می خواهید ابزارها، یادگیری ماشینی و تجزیه و تحلیل داده های مورد استفاده در این آموزش را یاد بگیرید؟ در اینجا چند منبع عالی برای شروع شما وجود دارد:
نتیجه
در این مقاله من شرح داده ام process جمع آوری، تمیز کردن و پردازش یک مجموعه داده با اندازه مناسب برای استفاده در مقالات آینده روی یک پروژه یادگیری ماشینی که در آن دمای هوای آینده را پیشبینی میکنیم.
در حالی که این احتمالاً خشک ترین مقاله در مورد این پروژه یادگیری ماشینی خواهد بود، من سعی کرده ام بر اهمیت جمع آوری داده های با کیفیت مناسب برای یک آزمایش یادگیری ماشینی ارزشمند تأکید کنم.
ممنون که خواندید و امیدوارم منتظر مقالات بعدی باشید روی این پروژه.
به دنبال قسمت های 2 و 3 این مجموعه هستید؟ اینجا برو:
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-29 03:52:04