یادداشت های یک دیتاساینتیست: يادگيری ماشين آن طور که در دنيای واقعی کار می کند

قبل از اينکه حتی درباره مدل و الگوريتم حرف بزنيم، يک قدم ساده اما حياتی داريم: داده را درست بخوانيم.
اکثر آدم ها فکر می کنند “لود کردن CSV که کاری ندارد”، ولی در عمل همين مرحله اگر درست انجام نشود، کل پروژه از همان اول کج می رود.
خشت اول گر نهد معمار کج
تا ثريا می رود ديوار کج
در اين درس، دقيقا با همين ديتاست معروف Pima Indians کار می کنيم و ياد می گيريم چطور آن را مستقيم از اين لينک بخوانيم و اگر خواستيم دانلودش کنيم و محلی ذخيره کنيم:
dataset_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" # Dataset URL
اين ديتاست برای آموزش لود کردن داده انتخاب خيلی خوبی است، چون هم ساده است، هم واقعی است، و هم در ده ها مثال آموزشی تکرار شده.
داده ها مربوط به پرونده های پزشکی هستند و هدف اين است که پيش بينی کنيم آيا فرد در چند سال آينده ممکن است ديابت بگيرد يا نه.
چند نکته که بد نيست همين اول بدانيم:
هر سطر، اطلاعات يک نفر است (يک رکورد پزشکی).
همه ستون ها عددی هستند، يعنی با مشکل متن و رشته و اينها کمتر درگير می شويم.
ستون آخر، خروجی است و فقط دو مقدار دارد: 0 يا 1.
پس مسئله ما طبقه بندی (Classification) است، چون قرار است بين دو حالت تصميم بگيريم.
در اين ديتاست، معنی Outcome اين است:
Outcome = 0 يعنی ديابت تشخيص داده نشده است
Outcome = 1 يعنی ديابت تشخيص داده شده است
اينکه ديتاست “ساده” است، به اين معنی نيست که “بی دردسر” است. مثلا يک نکته مهم در همين ديتاست اين است که بعضی ستون ها مقدار صفر دارند، در حالی که در دنيای واقعی صفر بودنشان منطقی نيست (مثل Insulin يا BMI). اين را فعلا فقط در ذهن نگه دار، چون در درس های بعدی وقتی رفتيم سراغ آمار توصيفی (Descriptive Statistics) و آماده سازی داده (Data Preparation) دوباره برمی گرديم به همين موضوع.
در اين ديتاست ما 9 ستون داريم. من معنی هر کدام را در يک جمله می گويم تا وقتی کد می زنی، فقط عدد نبينی، مفهوم پشت عدد را هم بفهمی:
Pregnancies: تعداد دفعات بارداری فرد را نشان می دهد.
Glucose: ميزان قند خون (غلظت گلوکز) را نشان می دهد که معمولا يکی از مهم ترين نشانه ها در ديابت است.
BloodPressure: فشار خون دياستوليک را نشان می دهد (همان عدد پايين فشار خون).
SkinThickness: ضخامت چين پوستی (معمولا پشت بازو) است که به عنوان يک شاخص تقريبی برای چربی بدن استفاده می شود.
Insulin: ميزان انسولين اندازه گيری شده در بدن است (در بعضی رکوردها صفر آمده که بعدا درباره اش حرف می زنيم).
BMI: شاخص توده بدنی است که نسبت وزن به قد را خلاصه می کند و تصويری کلی از اضافه وزن می دهد.
DiabetesPedigreeFunction: يک عدد خلاصه شده برای نشان دادن سابقه خانوادگی ديابت و ريسک ژنتيکی است.
Age: سن فرد است (به سال).
Outcome: برچسب نهايی است که می گويد فرد ديابت دارد (1) يا ندارد (0).
اين بخش را جدی بگير. چون وقتی بعدا مدل می سازی، مدل فقط عدد می بيند، اما تو بايد بدانی اين عددها دارند درباره چه چيزی حرف می زنند.
اين فايل در نسخه اصلی هدر ندارد. يعنی سطر اول هم داده است.
پس اگر بخواهيم ستون ها را درست و خوانا داشته باشيم، بايد اسم ستون ها را خودمان بدهيم.
اسم ستون های رايج:
Pregnancies
Glucose
BloodPressure
SkinThickness
Insulin
BMI
DiabetesPedigreeFunction
Age
Outcome
اين CSV با کاما جدا شده است، پس delimiter برابر "," است.
در اين فايل کامنت نداريم، ولی اگر فايلی داشتی که خط هایش با # شروع می شد، بايد به خواننده بگويی آن خط ها داده نيستند.
اين فايل کوتیشن خاصی ندارد، ولی بعضی CSV ها مقدارهای داخل کوتیشن دارند و بايد مشخص شود.
کتابخانه استاندارد پایتون يک ماژول به اسم csv دارد. ما می توانيم فايل را از URL باز کنيم و خط به خط بخوانيم.
import csv # Read CSV rows from urllib.request import urlopen # Open a URL stream from io import TextIOWrapper # Convert bytes to text import numpy as np # Convert to numeric arrays dataset_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" # Dataset URL response = urlopen(dataset_url) # Download file as a stream text_stream = TextIOWrapper(response, encoding="utf-8") # Decode bytes to text csv_reader = csv.reader(text_stream, delimiter=",") # Create CSV reader rows_as_text = list(csv_reader) # Read all rows into a list data_array = np.array(rows_as_text, dtype=float) # Convert all values to float print("Shape:", data_array.shape) # Print dataset shape (rows, cols) print("First row:", data_array[0]) # Show the first row to confirm it looks correct
Output:
Shape: (768, 9) First row: [ 6. 148. 72. 35. 0. 33.6 0.627 50. 1. ]
اين روش کمک می کند بفهمی “خام خام” داده چطور وارد برنامه می شود.
اين روش خيلی جمع و جور و سريع است، به شرطی که همه چيز عددی باشد (که در اين ديتاست هست).
import numpy as np # Numerical arrays from urllib.request import urlopen # Open URL stream dataset_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" # Dataset URL with urlopen(dataset_url) as response: # Open URL as a stream data_array = np.loadtxt(response, delimiter=",") # Load CSV into NumPy array print("Shape:", data_array.shape) # Print dataset shape print("First row:", data_array[0]) # Quick sanity check
Output:
نکته تجربه ای: اگر يک روز فايلت حتی يک مقدار خالی يا متن داشته باشد، اين روش سريع خطا می دهد.
پانداس برای يادگيری ماشين خيلی خوش دست است چون خروجی DataFrame می دهد و همان لحظه آماده خلاصه گرفتن و رسم نمودار است.
چون اين فايل هدر ندارد، ما اسم ستون ها را خودمان می دهيم تا کارمان خوانا باشد.
import pandas as pd # Work with DataFrame dataset_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" # Dataset URL column_names = [ # Column names for readability "Pregnancies", # Number of pregnancies "Glucose", # Plasma glucose concentration "BloodPressure", # Diastolic blood pressure "SkinThickness", # Triceps skin fold thickness "Insulin", # 2-Hour serum insulin "BMI", # Body mass index "DiabetesPedigreeFunction", # Diabetes pedigree function "Age", # Age in years "Outcome" # Target label (0 or 1) ] df = pd.read_csv(dataset_url, names=column_names) # Read CSV from URL and assign column names print("Shape:", df.shape) # Print dataset shape print(df.head()) # Show first 5 rows
Output:
اگر بخواهی سريع مطمئن شوی همه چيز درست لود شده:
print(df.dtypes) # Check data types of columns print(df["Outcome"].value_counts()) # Check how many 0s and 1s we have
اينجا يک کار خيلی کاربردی انجام می دهيم: فايل را از همين لينک دانلود می کنيم و روی سيستم ذخيره می کنيم، طوری که بعدا بدون اينترنت هم بتوانند با آن کار کنند.
from urllib.request import urlopen # Download from URL dataset_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" # Dataset URL output_filename = "pima-indians-diabetes.data.csv" # Local file name to save with urlopen(dataset_url) as response: # Open URL stream file_bytes = response.read() # Read all bytes from the response with open(output_filename, "wb") as file_handle: # Open a local file in binary write mode file_handle.write(file_bytes) # Save downloaded bytes to disk print("Saved file as:", output_filename) # Confirm file was saved successfully
حس خوب اين کار اين است که:
يک بار دانلود می کنند
بعدش همه تمرين ها را روی فايل محلی انجام می دهند
و هر بار وابسته به لينک و اينترنت نيستند
در اين درس ياد گرفتيم:
قبل از لود CSV بايد هدر، جداکننده، کامنت و کوتیشن را چک کنيم
ديتاست Pima Indians چيست و هر ستون چه معنی دارد
سه روش لود کردن را تمرين کرديم: استاندارد پایتون، نامپای (NumPy)، پانداس (Pandas)
و در نهايت ياد گرفتيم چطور فايل را دانلود و روی سيستم ذخيره کنيم
حالا که داده را درست لود کرديم، وقتش است واقعا به آن نگاه کنيم.
در درس بعدی می رويم سراغ آمار توصيفی (Descriptive Statistics) تا با چند عدد ساده بفهميم داده چه شکلی است، کجاها مشکوک است، و قبل از مدل سازی چه چيزهايی بايد اصلاح شود.