Основната цел на това четене е да разбере достатъчно статистическа методология, за да може да използва алгоритмите за машинно обучение в Python’s scikit-learn и след това да приложите тези знания за решаване на класически проблем с машинно обучение.
Първата спирка от пътуването ни ще ни преведе през кратка история на машинното обучение. След това ще се потопим в различни алгоритми. На последната ни спирка ще използваме наученото за решаване на Проблем с прогнозата за оцеляването на Титаник .
Някои отказ от отговорност:
С това отбелязваме, нека се потопим!
Веднага щом се впуснете в тази област, вие осъзнавате това машинно обучение е по-малко романтично, отколкото си мислите. Първоначално бях изпълнен с надежди, че след като научих повече, ще мога да създам свой собствен Jarvis AI, който да прекарва цял ден в кодиране на софтуер и да печели пари за мен, за да мога да прекарвам цели дни на открито в четене на книги, шофиране на мотоциклет, и да се наслаждавам на безразсъден начин на живот, докато моят личен Джарвис прави джобовете ми по-дълбоки. Скоро обаче разбрах, че основата на алгоритмите за машинно обучение е статистиката, която лично аз намирам за скучна и безинтересна. За щастие се оказа, че „тъпата“ статистика има някои много завладяващи приложения.
Скоро ще откриете, че за да стигнете до тези завладяващи приложения, трябва много добре да разбирате статистиката. Една от целите на алгоритмите за машинно обучение е да се намерят статистически зависимости в предоставените данни.
Предоставените данни могат да бъдат от проверка на кръвното налягане спрямо възрастта до намиране на ръкописен текст въз основа на цвета на различни пиксели.
Въпреки това, бях любопитен да видя дали бих могъл да използвам алгоритми за машинно обучение, за да намеря зависимости в криптографските хеш функции (SHA, MD5 и т.н.) - но всъщност не можете да го направите, защото правилните крипто примитиви са конструирани по такъв начин че те премахват зависимостите и произвеждат значително трудно предвидима продукция. Вярвам, че при безкрайно много време алгоритмите за машинно обучение могат да разбият всеки крипто модел.
За съжаление нямаме толкова много време, така че трябва да намерим друг начин за ефективно копаене на криптовалута. Докъде стигнахме до сега?
научете първо c или c++
Корените на алгоритмите за машинно обучение идват от Томас Байес, който е английски статистик, живял през 18 век. Неговата хартия Есе за решаване на проблем в доктрината за шансовете основи Теорема на Байес , който се прилага широко в областта на статистиката.
През 19 век Пиер-Симон Лаплас публикува Аналитична теория на вероятността , разширявайки работата на Байес и дефинирайки това, което познаваме днес като теория на Байес. Малко преди това Адриен-Мари Легендър беше описал метода на „най-малките квадрати“, също широко използван днес в контролираното обучение.
20-ти век е периодът, когато повечето публично известни открития са направени в тази област. Андрей Марков изобретява вериги на Марков, които използва за анализ на стихове. Алън Тюринг предложи учебна машина, която може да стане изкуствено интелигентна, като по същество предвещава генетични алгоритми. Франк Розенблат изобретява Перцептрон , предизвиквайки огромно вълнение и голямо отразяване в медиите.
Но след това през 70-те години се наблюдава доста песимизъм около идеята за ИИ - и по този начин, намалено финансиране - така че този период се нарича AI зима . Преоткриването на обратното размножаване през 80-те години на миналия век предизвика възраждане в изследванията на машинното обучение. И днес това е гореща тема за пореден път.
Покойният Лео Брейман направи разлика между две парадигми на статистическо моделиране: моделиране на данни и алгоритмично моделиране. „Алгоритмично моделиране“ означава повече или по-малко алгоритми за машинно обучение като случайна гора .
Машинното обучение и статистиката са тясно свързани области. Според Майкъл И. Джордан , идеите за машинно обучение, от методологични принципи до теоретични инструменти, имат дълга предистория в статистиката. Той също предложи наука за данни като запазен термин за общия проблем, по който и специалистите по машинно обучение, и статистиците работят по подразбиране.
Полето за машинно обучение стои на два основни стълба, наречени контролирано обучение и учене без надзор . Някои хора обмислят и нова област на обучение - дълбоко обучение —Да бъде отделен от въпроса за контролираното и безучилищното обучение.
Учене под наблюдение е когато компютърът е представен с примери за входове и техните желани изходи. Целта на компютъра е да научи обща формула, която преобразува входовете в изходите. Това може допълнително да бъде разделено на:
За разлика, учене без надзор е, когато изобщо не са дадени етикети и зависи от алгоритъма да намери структурата в нейния вход. Ученето без надзор може да бъде самоцел, когато трябва само да открием скрити модели.
Дълбоко обучение е нова област на изследване, която е вдъхновена от структурата и функциите на човешкия мозък и се основава на изкуствени невронни мрежи, а не само на статистически концепции. Дълбокото обучение може да се използва както в контролирани, така и в неподдържани подходи.
В тази статия ще разгледаме само някои от по-опростените контролирани алгоритми за машинно обучение и ще ги използваме, за да изчислим шансовете за оцеляване на човек при трагично потъване на Титаник. Но като цяло, ако не сте сигурни кой алгоритъм да използвате, хубаво място е да започнете scikit-learn’s алгоритъм за машинно обучение алгоритъм .
Може би най-лесният възможен алгоритъм е линейната регресия. Понякога това може да бъде представено графично като права линия, но въпреки името си, ако има полиномиална хипотеза, тази линия може вместо това да бъде крива. Така или иначе, той моделира връзките между скаларна зависима променлива $ y $ и една или повече обяснителни стойности, обозначени с $ x $.
В термините на неспециалисти това означава, че линейната регресия е алгоритъмът, който научава зависимостта между всеки известен $ x $ и $ y $, така че по-късно можем да го използваме за прогнозиране на $ y $ за неизвестна извадка от $ x $.
В нашия първи пример за контролирано обучение, ние ще използваме основен модел на линейна регресия, за да предскажем кръвното налягане на човек, предвид възрастта му. Това е много прост набор от данни с две значими характеристики: Възраст и кръвно налягане.
Както вече беше споменато по-горе, повечето алгоритми за машинно обучение работят чрез намиране на статистическа зависимост в предоставените им данни. Тази зависимост се нарича a хипотеза и обикновено се обозначава с $ h ( theta) $.
За да разберем хипотезата, нека започнем с зареждане и проучване на данните.
import matplotlib.pyplot as plt from pandas import read_csv import os # Load data data_path = os.path.join(os.getcwd(), 'data/blood-pressure.txt') dataset = read_csv(data_path, delim_whitespace=True) # We have 30 entries in our dataset and four features. The first feature is the ID of the entry. # The second feature is always 1. The third feature is the age and the last feature is the blood pressure. # We will now drop the ID and One feature for now, as this is not important. dataset = dataset.drop(['ID', 'One'], axis=1) # And we will display this graph %matplotlib inline dataset.plot.scatter(x='Age', y='Pressure') # Now, we will assume that we already know the hypothesis and it looks like a straight line h = lambda x: 84 + 1.24 * x # Let's add this line on the chart now ages = range(18, 85) estimated = [] for i in ages: estimated.append(h(i)) plt.plot(ages, estimated, 'b')
[]
На графиката по-горе всяка синя точка представлява нашата извадка от данни, а синята линия е хипотезата, която алгоритъмът трябва да научи. И така, каква точно е тази хипотеза изобщо?
За да разрешим този проблем, трябва да научим зависимостта между $ x $ и $ y $, която се обозначава с $ y = f (x) $. Следователно $ f (x) $ е идеалната целева функция. Алгоритъмът за машинно обучение ще се опита да отгатне функцията на хипотезата $ h (x) $, която е най-близкото приближение на неизвестния $ f (x) $.
Най-простата възможна форма на хипотеза за проблема с линейната регресия изглежда така: $ h_ theta (x) = theta_0 + theta_1 * x $. Имаме една входна скаларна променлива $ x $, която извежда една скаларна променлива $ y $, където $ theta_0 $ и $ theta_1 $ са параметри, които трябва да научим. Процесът на поставяне на тази синя линия в данните се нарича линейна регресия. Важно е да се разбере, че имаме само един входен параметър $ x_1 $; много функции на хипотезата обаче ще включват и единицата за пристрастие ($ x_0 $). Така получената от нас хипотеза има формата на $ h_ theta (x) = theta_0 * x_0 + theta_1 * x_1 $. Но можем да избегнем писането на $ x_0 $, защото почти винаги е равно на 1.
Връщайки се към синята линия. Нашата хипотеза изглежда като $ h (x) = 84 + 1,24x $, което означава, че $ theta_0 = 84 $ и $ theta_1 = 1,24 $. Как можем автоматично да извлечем тези стойности на $ theta $?
Трябва да определим a функция на разходите . По същество това, което прави разходната функция, просто изчислява средно-квадратната грешка между прогнозата на модела и действителната продукция.
[J ( theta) = frac {1} {2m} sum_ {i = 1} ^ m (h_ theta (x ^ {(i)}) - y ^ {(i)}) ^ 2 ]Например, нашата хипотеза предвижда, че за някой, който е на 48 години, кръвното му налягане трябва да бъде $ h (48) = 84 + 1,24 * 48 = 143mmHg $; обаче в нашата извадка за обучение имаме стойност от $ 130 mmHg $. Следователно грешката е $ (143 - 130) ^ 2 = 169 $. Сега трябва да изчислим тази грешка за всеки отделен запис в нашия набор от данни за обучение, след което да я обобщим ($ sum_ {i = 1} ^ m (h_ theta (x ^ {(i)}) - y ^ {(i )}) ^ 2 $) и вземете средната стойност от това.
Това ни дава едно скаларно число, което представлява цената на функцията. Нашата цел е да намерим $ theta $ стойности, така че функцията на разходите да е най-ниската; с други думи, искаме да сведем до минимум функцията на разходите. Надяваме се, че това ще изглежда интуитивно: Ако имаме малка стойност на функцията на разходите, това означава, че грешката на прогнозирането също е малка.
import numpy as np # Let's calculate the cost for the hypothesis above h = lambda x, theta_0, theta_1: theta_0 + theta_1 * x def cost(X, y, t0, t1): m = len(X) # the number of the training samples c = np.power(np.subtract(h(X, t0, t1), y), 2) return (1 / (2 * m)) * sum(c) X = dataset.values[:, 0] y = dataset.values[:, 1] print('J(Theta) = %2.2f' % cost(X, y, 84, 1.24))
J(Theta) = 1901.95
Сега трябва да намерим такива стойности на $ theta $ такива, че нашите функция на разходите стойността е минимална. Но как да го направим?
[minJ ( theta) = frac {1} {2m} sum_ {i = 1} ^ m (h_ theta (x ^ {(i)}) - y ^ {(i)}) ^ 2 ]Има няколко възможни алгоритми, но най-популярният е градиентно спускане . За да разберем интуицията зад метода на градиентното спускане, нека първо го начертаем на графиката. За улеснение ще приемем по-проста хипотеза $ h ( theta) = theta_1 * x $. След това ще начертаем проста 2D диаграма, където $ x $ е стойността на $ theta $, а $ y $ е разходната функция в този момент.
import matplotlib.pyplot as plt fig = plt.figure() # Generate the data theta_1 = np.arange(-10, 14, 0.1) J_cost = [] for t1 in theta_1: J_cost += [ cost(X, y, 0, t1) ] plt.plot(theta_1, J_cost) plt.xlabel(r'$ heta_1$') plt.ylabel(r'$J( heta)$') plt.show()
Функцията на разходите е изпъкнала, което означава, че на интервала $ [a, b] $ има само един минимум. Което отново означава, че най-добрите $ theta $ параметри са в точката, в която разходната функция е минимална.
По принцип градиентното спускане е алгоритъм, който се опитва да намери набора от параметри, които минимизират функцията. Започва с първоначален набор от параметри и итеративно предприема стъпки в отрицателната посока на функционалния градиент.
Ако изчислим производната на хипотезна функция в определена точка, това ще ни даде наклон на допирателната линия към кривата в тази точка. Това означава, че можем да изчислим наклона във всяка една точка на графиката.
Начинът на работа на алгоритъма е следният:
Сега условието за конвергенция зависи от изпълнението на алгоритъма. Може да спрем след 50 стъпки, след някакъв праг или нещо друго.
import math # Example of the simple gradient descent algorithm taken from Wikipedia cur_x = 2.5 # The algorithm starts at point x gamma = 0.005 # Step size multiplier precision = 0.00001 previous_step_size = cur_x df = lambda x: 2 * x * math.cos(x) # Remember the learning curve and plot it while previous_step_size > precision: prev_x = cur_x cur_x += -gamma * df(prev_x) previous_step_size = abs(cur_x - prev_x) print('The local minimum occurs at %f' % cur_x)
The local minimum occurs at 4.712194
Няма да прилагаме тези алгоритми в тази статия. Вместо това ще използваме широко приетата scikit-learn
, библиотека за машинно обучение на Python с отворен код. Той предоставя много много полезни API за различни проблеми с извличането на данни и машинното обучение.
from sklearn.linear_model import LinearRegression # LinearRegression uses the gradient descent method # Our data X = dataset[['Age']] y = dataset[['Pressure']] regr = LinearRegression() regr.fit(X, y) # Plot outputs plt.xlabel('Age') plt.ylabel('Blood pressure') plt.scatter(X, y, color='black') plt.plot(X, regr.predict(X), color='blue') plt.show() plt.gcf().clear()
print( 'Predicted blood pressure at 25 y.o. = ', regr.predict(25) ) print( 'Predicted blood pressure at 45 y.o. = ', regr.predict(45) ) print( 'Predicted blood pressure at 27 y.o. = ', regr.predict(27) ) print( 'Predicted blood pressure at 34.5 y.o. = ', regr.predict(34.5) ) print( 'Predicted blood pressure at 78 y.o. = ', regr.predict(78) )
Predicted blood pressure at 25 y.o. = [[ 122.98647692]] Predicted blood pressure at 45 y.o. = [[ 142.40388395]] Predicted blood pressure at 27 y.o. = [[ 124.92821763]] Predicted blood pressure at 34.5 y.o. = [[ 132.20974526]] Predicted blood pressure at 78 y.o. = [[ 174.44260555]]
Когато работите с данни за проблеми с машинното обучение, е важно да разпознавате различни видове данни. Може да имаме числени (непрекъснати или дискретни), категорични или редови данни.
Числови данни има значение като измерване. Например възраст, тегло, брой биткойни, които човек притежава, или колко статии човек може да напише на месец. Числовите данни могат да бъдат допълнително разделени на дискретни и непрекъснати типове.
Категорични данни представляват стойности като пол на човека, семейно положение, държава и др. Тези данни могат да имат числова стойност, но тези числа нямат математическо значение. Не можете да ги добавяте заедно.
Поредни данни може да бъде комбинация от другите два типа, като категориите могат да бъдат номерирани по математически значим начин. Чест пример са рейтингите: Често от нас се иска да оценяваме нещата по скала от едно до десет и са разрешени само цели числа. Въпреки че можем да използваме това числово - например, за да намерим средна оценка за нещо - ние често се отнасяме към данните, сякаш са категорични, когато става въпрос за прилагане на методи за машинно обучение към него.
Линейната регресия е страхотен алгоритъм, който ни помага да предсказваме числени стойности, например цената на къщата с конкретния размер и броя на стаите. Понякога обаче може да искаме да предскажем категорични данни, за да получим отговори на въпроси като:
Или дори:
Всички тези въпроси са специфични за проблем с класификацията . И се нарича най-простият алгоритъм за класификация логистична регресия , което в крайна сметка е същото като линейна регресия, с изключение на това, че има различна хипотеза.
На първо място, можем да използваме същата линейна хипотеза $ h_ theta (x) = theta ^ T X $ (това е във векторизирана форма). Докато линейната регресия може да изведе произволно число в интервала $ [a, b] $, логистичната регресия може да изведе стойности само в $ [- 1, 1] $, което е вероятността обектът да попадне в дадена категория или не.
Използване на a сигмоидна функция , можем да преобразуваме всяка числова стойност, за да представим стойност на интервала $ [- 1, 1] $.
[f (x) = frac {1} {1 + e ^ x} ]Сега, вместо $ x $, трябва да предадем съществуваща хипотеза и следователно ще получим:
[f (x) = frac {1} {1 + e ^ { theta_0 + theta_1 * x_1 + ... + theta_n * x_n}} ]След това можем да приложим прост праг, който казва, че ако хипотезата е по-голяма от нула, това е истинска стойност, в противен случай невярна.
[h_ theta (x) = begin {случаи} 1 & mbox {if} theta ^ T X> 0 \ 0 & mbox {else} end {случаи} ]Това означава, че можем да използваме същото функция на разходите и същия алгоритъм за градиентно спускане, за да се научи хипотеза за логистична регресия.
В следващия пример за алгоритъм за машинно обучение ще посъветваме пилотите на космическата совалка дали трябва да използват автоматично или ръчно управление на кацането или не. Ние имаме много малък набор от данни —15 проби - което се състои от шест характеристики и фундаментална истина .
В алгоритмите за машинно обучение терминът „ фундаментална истина “Се отнася до точността на класификацията на учебния комплект за контролирани техники на обучение.
Нашият набор от данни е пълен, което означава, че няма липсващи функции; някои от функциите обаче имат '*' вместо категорията, което означава, че тази функция няма значение. Ще заменим всички подобни звездички с нули.
from sklearn.linear_model import LogisticRegression # Data data_path = os.path.join(os.getcwd(), 'data/shuttle-landing-control.csv') dataset = read_csv(data_path, header=None, names=['Auto', 'Stability', 'Error', 'Sign', 'Wind', 'Magnitude', 'Visibility'], na_values='*').fillna(0) # Prepare features X = dataset[['Stability', 'Error', 'Sign', 'Wind', 'Magnitude', 'Visibility']] y = dataset[['Auto']].values.reshape(1, -1)[0] model = LogisticRegression() model.fit(X, y) # For now, we're missing one important concept. We don't know how well our model # works, and because of that, we cannot really improve the performance of our hypothesis. # There are a lot of useful metrics, but for now, we will validate how well # our algorithm performs on the dataset it learned from. 'Score of our model is %2.2f%%' % (model.score(X, y) * 100)
Score of our model is 73.33%
В предишния пример проверихме ефективността на нашия модел, използвайки данните за обучение. Дали обаче това сега е добър вариант, като се има предвид, че нашият алгоритъм може или да недостатъчно превъзхожда данните? Нека да разгледаме по-простия пример, когато имаме една характеристика, която представя размера на къщата, и друга, която представлява нейната цена.
from sklearn.pipeline import make_pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression from sklearn.model_selection import cross_val_score # Ground truth function ground_truth = lambda X: np.cos(15 + np.pi * X) # Generate random observations around the ground truth function n_samples = 15 degrees = [1, 4, 30] X = np.linspace(-1, 1, n_samples) y = ground_truth(X) + np.random.randn(n_samples) * 0.1 plt.figure(figsize=(14, 5)) models = {} # Plot all machine learning algorithm models for idx, degree in enumerate(degrees): ax = plt.subplot(1, len(degrees), idx + 1) plt.setp(ax, xticks=(), yticks=()) # Define the model polynomial_features = PolynomialFeatures(degree=degree) model = make_pipeline(polynomial_features, LinearRegression()) models[degree] = model # Train the model model.fit(X[:, np.newaxis], y) # Evaluate the model using cross-validation scores = cross_val_score(model, X[:, np.newaxis], y) X_test = X plt.plot(X_test, model.predict(X_test[:, np.newaxis]), label='Model') plt.scatter(X, y, edgecolor='b', s=20, label='Observations') plt.xlabel('x') plt.ylabel('y') plt.ylim((-2, 2)) plt.title('Degree {}
MSE = {:.2e}'.format( degree, -scores.mean())) plt.show()
Моделът на алгоритъма за машинно обучение е недооборудване ако не може да обобщи нито данните от обучението, нито новите наблюдения. В горния пример използваме проста линейна хипотеза, която всъщност не представлява действителния набор от данни за обучение и ще има много лошо представяне. Обикновено недостатъчното оборудване не се обсъжда, тъй като може лесно да бъде открито при добра метрика.
Ако нашият алгоритъм запомни всяко едно наблюдение, което е било показано, тогава той ще има лоша ефективност при нови наблюдения извън набора от данни за обучение. Това се казва преоборудване . Например, полиномиален модел от 30-та степен преминава през повечето точки и има много добър резултат на тренировъчния набор, но всичко извън това би се представило зле.
Нашият набор от данни се състои от една функция и е лесен за нанасяне в 2D пространство; обаче в реалния живот може да имаме набори от данни със стотици функции, което ги прави невъзможно да се начертае визуално в евклидово пространство. Какви други опции имаме, за да видим дали моделът е недостатъчно или прекалено подходящ?
Време е да ви запозная с концепцията за крива на обучение . Това е проста графика, която нанася средната квадратична грешка върху броя на учебните проби.
точки на прекъсване на разделителна способност за отзивчив уеб дизайн
В учебните материали обикновено ще видите графики, подобни на тези:
В реалния живот обаче може да не получите такава перфектна картина. Нека начертаем кривата на обучение за всеки от нашите модели.
from sklearn.model_selection import learning_curve, ShuffleSplit # Plot learning curves plt.figure(figsize=(20, 5)) for idx, degree in enumerate(models): ax = plt.subplot(1, len(degrees), idx + 1) plt.title('Degree {}'.format(degree)) plt.grid() plt.xlabel('Training examples') plt.ylabel('Score') train_sizes = np.linspace(.6, 1.0, 6) # Cross-validation with 100 iterations to get a smoother mean test and training # score curves, each time with 20% of the data randomly selected as a validation set. cv = ShuffleSplit(n_splits=100, test_size=0.2, random_state=0) model = models[degree] train_sizes, train_scores, test_scores = learning_curve( model, X[:, np.newaxis], y, cv=cv, train_sizes=train_sizes, n_jobs=4) train_scores_mean = np.mean(train_scores, axis=1) test_scores_mean = np.mean(test_scores, axis=1) plt.plot(train_sizes, train_scores_mean, 'o-', color='r', label='Training score') plt.plot(train_sizes, test_scores_mean, 'o-', color='g', label='Test score') plt.legend(loc = 'best') plt.show()
В нашия симулиран сценарий синята линия, която представлява резултата от тренировката, изглежда като права линия. В действителност тя все още леко намалява - всъщност можете да видите това в полиномната графика от първа степен, но в останалите е твърде фино, за да се каже при тази резолюция. Поне ясно виждаме, че има огромна разлика между кривите на обучение за обучение и тестовите наблюдения със сценарий на „висока пристрастност“.
На „нормалната“ графика на скоростта на обучение в средата можете да видите как се съчетават линиите за обучение и тест.
И на графиката „висока дисперсия“ можете да видите, че при малък брой проби резултатите от теста и обучението са много сходни; обаче, когато увеличите броя на пробите, резултатът от обучението остава почти перфектен, докато резултатът от теста расте далеч от него.
Можем да коригираме модели с недостатъчно оборудване (наричани още модели с висока пристрастност ) ако използваме нелинейна хипотеза, например хипотезата с повече полиномиални характеристики.
Нашият модел за преоборудване ( висока дисперсия ) преминава през всеки отделен пример, който е показан; обаче, когато въвеждаме тестови данни, разликата между кривите на обучение се разширява. Можем да използваме регуларизация, кръстосано валидиране и повече извадки от данни, за да коригираме модели за пренастройване.
Една от често срещаните практики за избягване на пренастройване е да се запази част от наличните данни и да се използва като набор от тестове. Въпреки това, когато оценяваме различни настройки на модела, като например броя на полиномиалните характеристики, ние все още сме изложени на риск от пренастройване на тестовия набор, тъй като параметрите могат да бъдат променени, за да се постигне оптимална производителност на оценителя и поради това знанията ни за тестовия набор могат изтичане в модела. За да разрешим този проблем, трябва да задържим още една част от набора от данни, която се нарича „набор за проверка“. Обучението продължава върху комплекта за обучение и когато смятаме, че сме постигнали оптималното представяне на модела, можем да направим окончателна оценка, използвайки валидиращия набор.
Чрез разделяне на наличните данни на три набора, ние драстично намаляваме броя на пробите, които могат да бъдат използвани за обучение на моделите, а резултатите могат да зависят от конкретен случаен избор за двойката на валидиране на обучението.
Едно от решенията на този проблем е процедура, наречена кръстосана проверка. В стандартната $ k $ -кратна кръстосана проверка ние разделяме данните на $ k $ подмножества, наречени гънки. След това итеративно обучаваме алгоритъма на $ k-1 $ гънки, докато използваме останалото сгъване като набор от тестове (наречен „holdout fold“).
Кръстосаната проверка ви позволява да настройвате параметри само с оригиналния си набор за обучение. Това ви позволява да запазите тестовия си набор като наистина невидим набор от данни за избор на вашия окончателен модел.
Има много повече техники за кръстосано валидиране, като оставете Р навън , стратифициран $ k $ -кратно , разбъркване и разделяне и др., но те са извън обхвата на тази статия.
Това е друга техника, която може да помогне за решаването на проблема с пренастройването на модела. Повечето набори от данни имат модел и известен шум. Целта на регуларизацията е да се намали влиянието на шума върху модела.
Има три основни техники за регулиране: Ласо, Тихонов и еластична мрежа.
L1 регуларизация (или Ласо регулиране ) ще избере някои функции, които да се свият до нула, така че да не играят никаква роля в крайния модел. L1 може да се разглежда като метод за избор на важни характеристики.
L2 регуларизация (или Регулиране на Тихонов ) ще принуди всичко характеристиките да бъдат относително малки, така че да осигурят по-малко влияние върху модела.
Еластична мрежа е комбинация на L1 и L2.
Мащабирането на характеристиките също е важна стъпка при предварителната обработка на данните. Нашият набор от данни може да има функции със стойности $ [- infty, infty] $ и други функции с различен мащаб. Това е метод за стандартизиране на диапазоните от независими стойности.
Мащабирането на характеристиките също е важен процес за подобряване на ефективността на учебните модели. На първо място, градиентното спускане ще се сближи много по-бързо, ако всички характеристики се мащабират до една и съща норма. Също така много алгоритми - например, поддържащи векторни машини (SVM) - работят чрез изчисляване на разстоянието между две точки и ако една от характеристиките има широки стойности, тогава разстоянието ще бъде силно повлияно от тази функция.
SVM е още един широко популярен алгоритъм за машинно обучение, който може да се използва за класификация и регресия. В SVM ние нанасяме всяко наблюдение като точка в $ n $ -мерно пространство, където $ n $ е броят на характеристиките, които имаме. Стойността на всяка характеристика е стойността на определени координати. След това се опитваме да намерим хиперплан, който достатъчно добре разделя два класа.
След като идентифицираме най-добрия хиперплан, искаме да добавим полета, които допълнително да разделят двата класа.
SVM е много ефективен, когато броят на функциите е много голям или ако броят на функциите е по-голям от броя на пробите от данни. Тъй като обаче SVM работи на векторна база, е изключително важно да се нормализират данните преди използването.
Алгоритмите на невронната мрежа са може би най-вълнуващата област на машинно обучение. Невронните мрежи се опитват да имитират как мозъчните неврони са свързани заедно.
Ето как изглежда невронната мрежа. Ние комбинираме много възли заедно, където всеки възел взема набор от входове, прилагаме някои изчисления върху тях и извеждаме стойност.
Съществува огромно разнообразие от алгоритми на невронната мрежа както за контролирано, така и за ненаблюдавано обучение. Невронните мрежи могат да се използват за шофиране на автономни автомобили, игра на игри, кацане на самолети, класифициране на изображения и др.
RMS Titanic е британски пътнически лайнер, който потъва в Северния Атлантически океан на 15 април 1912 г., след като се сблъска с айсберг. Имаше около 2224 души екипаж и пътници, а над 1500 загинаха, което го превърна в едно от най-смъртоносните търговски морски бедствия за всички времена.
Сега, тъй като разбираме интуицията зад най-основните алгоритми за машинно обучение, използвани за класификационни проблеми, можем да приложим знанията си, за да предскажем резултата от оцеляването на тези на борда на Титаник.
Нашият набор от данни ще бъде заимстван от Платформа за състезания по наука за данни Kaggle .
import os from pandas import read_csv, concat # Load data data_path = os.path.join(os.getcwd(), 'data/titanic.csv') dataset = read_csv(data_path, skipinitialspace=True) dataset.head(5)
PassengerId | Оцелял | Клас | Име | Секс | Възраст | SibSp | уважение | Билет | Да направя | Кабина | Качил се | |
0 | един | 0 | 3 | Браунд, господин Оуен Харис | мъжки | 22,0 | един | 0 | A / 5 21171 | 7.2500 | NaN | С |
един | 2 | един | един | Cumings, г-жа Джон Брадли (Флорънс Бригс Th ... | женски пол | 38,0 | един | 0 | PC 17599 | 71,2833 | С85 | ° С |
2 | 3 | един | 3 | Хейкинен, госпожице. Заем | женски пол | 26,0 | 0 | 0 | КАМЪК / O2. 3101282 | 7,9250 | NaN | С |
3 | 4 | един | един | Futrelle, г-жа Jacques Heath (Lily May Peel) | женски пол | 35,0 | един | 0 | 113803 | 53.1000 | С123 | С |
4 | 5 | 0 | 3 | Алън, господин Уилям Хенри | мъжки | 35,0 | 0 | 0 | 373450 | 8.0500 | NaN | С |
Първата ни стъпка би била да заредим и проучим данните. Имаме 891 протокола от тестове; всеки запис има следната структура:
Този набор от данни съдържа както цифрови, така и категорични данни. Обикновено е добра идея да се потопите по-дълбоко в данните и въз основа на това да излезете с предположения. В този случай обаче ще пропуснем тази стъпка и ще преминем направо към прогнози.
import pandas as pd # We need to drop some insignificant features and map the others. # Ticket number and fare should not contribute much to the performance of our models. # Name feature has titles (e.g., Mr., Miss, Doctor) included. # Gender is definitely important. # Port of embarkation may contribute some value. # Using port of embarkation may sound counter-intuitive; however, there may # be a higher survival rate for passengers who boarded in the same port. dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+).', expand=False) dataset = dataset.drop(['PassengerId', 'Ticket', 'Cabin', 'Name'], axis=1) pd.crosstab(dataset['Title'], dataset['Sex'])
Заглавие Пол | женски пол | мъжки |
Капитан | 0 | един |
С | 0 | 2 |
Графиня | един | 0 |
Дон | 0 | един |
Д-р | един | 6 |
Jonkheer | 0 | един |
Дама | един | 0 |
Майор | 0 | 2 |
Учителю | 0 | 40 |
Госпожице | 182 | 0 |
г-ца | 2 | 0 |
Г-жа | един | 0 |
г-н | 0 | 517 |
Г-жа | 125 | 0 |
г-ца | един | 0 |
Преп | 0 | 6 |
Сър | 0 | един |
# We will replace many titles with a more common name, English equivalent, # or reclassification dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col', 'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Other') dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss') dataset['Title'] = dataset['Title'].replace('Ms', 'Miss') dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs') dataset[['Title', 'Survived']].groupby(['Title'], as_index=False).mean()
Заглавие | Оцелял | |
0 | Учителю | 0,575000 |
един | Госпожице | 0,702703 |
2 | г-н | 0,156673 |
3 | Г-жа | 0,793651 |
4 | Други | 0,347826 |
# Now we will map alphanumerical categories to numbers title_mapping = { 'Mr': 1, 'Miss': 2, 'Mrs': 3, 'Master': 4, 'Other': 5 } gender_mapping = { 'female': 1, 'male': 0 } port_mapping = { 'S': 0, 'C': 1, 'Q': 2 } # Map title dataset['Title'] = dataset['Title'].map(title_mapping).astype(int) # Map gender dataset['Sex'] = dataset['Sex'].map(gender_mapping).astype(int) # Map port freq_port = dataset.Embarked.dropna().mode()[0] dataset['Embarked'] = dataset['Embarked'].fillna(freq_port) dataset['Embarked'] = dataset['Embarked'].map(port_mapping).astype(int) # Fix missing age values dataset['Age'] = dataset['Age'].fillna(dataset['Age'].dropna().median()) dataset.head()
Оцелял | Клас | Секс | Възраст | SibSp | уважение | Да направя | Качил се | Заглавие | |
0 | 0 | 3 | 0 | 22,0 | един | 0 | 7.2500 | 0 | един |
един | един | един | един | 38,0 | един | 0 | 71,2833 | един | 3 |
2 | един | 3 | един | 26,0 | 0 | 0 | 7,9250 | 0 | 2 |
3 | един | един | един | 35,0 | един | 0 | 53.1000 | 0 | 3 |
4 | 0 | 3 | 0 | 35,0 | 0 | 0 | 8.0500 | 0 | един |
На този етап ще класираме различни видове алгоритми за машинно обучение в Python, като използваме scikit-learn
за да създадете набор от различни модели. Тогава ще бъде лесно да се види кой се представя най-добре.
За всеки отделен модел ще използваме проверка на $ k $ -кратно.
from sklearn.model_selection import KFold, train_test_split from sklearn.pipeline import make_pipeline from sklearn.preprocessing import PolynomialFeatures, StandardScaler from sklearn.neural_network import MLPClassifier from sklearn.svm import SVC # Prepare the data X = dataset.drop(['Survived'], axis = 1).values y = dataset[['Survived']].values X = StandardScaler().fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state = None) # Prepare cross-validation (cv) cv = KFold(n_splits = 5, random_state = None) # Performance p_score = lambda model, score: print('Performance of the %s model is %0.2f%%' % (model, score * 100)) # Classifiers names = [ 'Logistic Regression', 'Logistic Regression with Polynomial Hypotheses', 'Linear SVM', 'RBF SVM', 'Neural Net', ] classifiers = [ LogisticRegression(), make_pipeline(PolynomialFeatures(3), LogisticRegression()), SVC(kernel='linear', C=0.025), SVC(gamma=2, C=1), MLPClassifier(alpha=1), ]
# iterate over classifiers models = [] trained_classifiers = [] for name, clf in zip(names, classifiers): scores = [] for train_indices, test_indices in cv.split(X): clf.fit(X[train_indices], y[train_indices].ravel()) scores.append( clf.score(X_test, y_test.ravel()) ) min_score = min(scores) max_score = max(scores) avg_score = sum(scores) / len(scores) trained_classifiers.append(clf) models.append((name, min_score, max_score, avg_score)) fin_models = pd.DataFrame(models, columns = ['Name', 'Min Score', 'Max Score', 'Mean Score'])
fin_models.sort_values(['Mean Score']).head()
Име | Моят резултат | Максимален резултат | Среден резултат | |
2 | Линеен SVM | 0,793296 | 0.821229 | 0,803352 |
0 | Логистична регресия | 0,826816 | 0,860335 | 0,846927 |
4 | Невронна мрежа | 0,826816 | 0,860335 | 0,849162 |
един | Логистична регресия с полиномиални хипотези | 0,854749 | 0,882682 | 0,869274 |
3 | RBF SVM | 0,843575 | 0,888268 | 0,869274 |
Добре, така че нашето експериментално изследване казва, че ядрото SVM класификатор с радиална базисна функция (RBF) се представя най-добре. Сега можем да сериализираме нашия модел и да го използваме повторно в производствени приложения.
import pickle svm_model = trained_classifiers[3] data_path = os.path.join(os.getcwd(), 'best-titanic-model.pkl') pickle.dump(svm_model, open(data_path, 'wb'))
Машинното обучение не е сложно, но е много широко поле на обучение и изисква познания по математика и статистика, за да се разберат всички негови концепции.
В момента машинното обучение и дълбокото обучение са сред най-горещите теми за дискусии в Силициевата долина и са хлябът и маслото на почти всеки компания за наука за данни , главно защото те могат да автоматизират много повтарящи се задачи, включително разпознаване на реч, управление на превозни средства, финансова търговия, грижа за пациентите , готвене , маркетинг , и така нататък.
Сега можете да вземете това знание и да решите предизвикателствата на Kaggle.
Това беше много кратко въведение в контролираните алгоритми за машинно обучение. За щастие има много онлайн курсове и информация за алгоритмите за машинно обучение. Аз лично бих препоръчал да започнете с курса на Andrew Ng по Coursera.
Алгоритмите за машинно обучение автоматично формират модели, използвайки статистически анализ, за разлика от традиционните твърдо кодирани алгоритми. Това им позволява да се развиват с течение на времето, докато търсят модели в данните и правят прогнози относно тяхната класификация.
Приложенията на машинното обучение са почти неограничени. Може да се използва за всичко - от просто прогнозиране на времето и клъстериране на данни до сложно обучение на функции; автономно шофиране и летене; разпознаване на изображения, реч и видео; машини за търсене и препоръки; диагностика на пациента; и още.
Надзорната класификация се нуждае от етикети за данни за обучение: Едната снимка е котка, другата е куче. Класификацията без надзор е мястото, където алгоритъмът намира общи черти и сам разделя данните. Няма да ни каже изрично, че изображението е котка, но ще може да отдели котките от кучета.
Ученото под наблюдение е мястото, където изрично казвате на алгоритъма какъв е правилният отговор, така че алгоритъмът може да научи и може да предскаже отговора за невиждани досега данни. Ученето без надзор е мястото, където алгоритъмът трябва сам да измисли отговора.
Най-доброто място да започнете да изучавате машинно обучение е да гледате курса на Andrew's Ng по Coursera, посочен в ресурсите в края на статията. Оттам започнете да приемате предизвикателства на Kaggle, за да развиете по-добра интуиция за различните рамки и подходи.
Има много фактори, които трябва да се вземат предвид при избора на правилния алгоритъм: размерът на набора от данни, естеството на данните, скоростта срещу точността и т.н. Докато не развиете собствената си интуиция, можете да използвате съществуващите таблици с мами като тази scikit-learn осигурява.