«Машинное обучение в действии» — анализ машин опорных векторов и оптимизация SMO

машинное обучение

Давайте временно обновим эту серию статей о машинном обучении вручную. В настоящее время завершена поддержка векторной машины SVM, дерева решений, KNN, байесовской, линейной регрессии и логистической регрессии. Для других алгоритмов, пожалуйста, позвольте Taoye отдать должное здесь сначала Позже будет время наверстать упущенное.

Это обновление также получило положительные отзывы от некоторых читателей. Хотя это не так много, я очень благодарен за вашу поддержку, и я надеюсь, что каждый читатель, прочитавший его, сможет что-то почерпнуть.

Все содержание этой серии статей написано Таойе исключительно от руки.Также есть отсылки ко многим книгам и общедоступным ресурсам.Общее количество слов в серии около 15W (включая исходный код), которые будут заполнены позже.Подробнее технические статьи могут посетить общественность Taoye.Циничный кодер. Документ можно распространять свободно, но будьте осторожны, не изменяйте его содержание.

Если в статье есть какие-либо вопросы, которые вы не понимаете, вы можете задать их напрямую, и Taoye ответит, как только они ее увидят.В то же время каждый может прийти сюда, чтобы напомнить Taoye в частном порядке:Циничный кодер, в официальном аккаунте также есть личная контактная информация Таое. Несколько слов, Таойе может говорить с тобой тайно только там (#`О')

Чтобы улучшить опыт чтения для всех, серия статей Taoye по машинному обучению была организована в видеPDF и HTML, эффект чтения очень хороший,Ответьте на [666] под официальным аккаунтом [Cynical Coder], чтобы получить его бесплатно.

Туман густой, а облака беспокоят вечно.

Я очень волнуюсь. Разве я не обновил статью о машинах опорных векторов в прошлый раз?«Машинное обучение в действии» — анализ машин опорных векторов, разрыв линейного SVM одной рукой. Хотя эффект неплохой, наборы данных в принципе можно правильно классифицировать, а эффективность обучения модели можно сказать в прошлом, но это основано на предпосылке, что наши наборы данных обучающей выборки относительно невелики, а количество итераций меньше. относительно маленький.

Если мы говорим, что наш набор данных относительно большой, и нам нужно много раз итерироваться, эффективность алгоритма SMO, использованного в предыдущей статье, не может быть оценена, а скорость обучения сравнима с таковой у черепах. Луна темная, а ночью сильный ветер, убивающий людей и поджигающий. Нет, нет, нет, луна темная, и ветер ночью сильный, и время сумасшедшее. Поскольку общий алгоритм SMO неэффективен, его необходимо дополнительно оптимизировать.

Всего несколько дней назад я услышал по радио, что есть много крупных боссов в стране и за границей, которые постоянно исследуют новые алгоритмы для дальнейшего повышения эффективности обучения алгоритма SMO. Услышав это, Таойе обрадовался: «Если я смогу придумать новый алгоритм оптимизации, у нас с братом будет отличный шанс прославиться, а стремление к господству над миром уже не за горами! Ха-ха-ха!!!» Хоть и хорошо, но как его оптимизировать? В эту туманную облачную ночь луна темна, а ветер сильный, мысли Таоэ летают по небу, и он очень волнуется.

Преднамеренно посаженные цветы не будут цвести, нечаянно посаженные ивы и ивы.

Очевидно, я уже знаю, что есть слишком много мест для оптимизации алгоритма SMO, но я просто не знаю, с чего начать.После долгих раздумий у меня сильно болит мозг. В этот момент лаборатория была пуста.Таойе повернула стул и посмотрела в окно.Яркий лунный свет всегда наводил на людей бесконечные задумчивости.

Вот и все, вместо того, чтобы угрюмо здесь сажать цветы, лучше выйти погулять, может быть, удастся застать нежданный урожай, а я приду сюда ненароком сажать ивы и вербы? Если скажешь иди, пошли (тон немного не тот~~), выключи кондиционер, надень пальто, запри дверь, засунь руки в карманы и выходи.

Возможно, это было из-за того, что слишком долго работал кондиционер, или лаборатория слишком долго находилась в лаборатории.В тот момент, когда я вышел, я почувствовал себя отдохнувшим и отдохнувшим.Я очень хотел спеть песню в этот момент. Через некоторое время стало немного холодно, поэтому перед выходом я надел пальто. Двигайте мышцами и костями и идите к озеру. Шли и шли, по незнанию подошли к пешеходному мосту, на спокойной озерной глади, ни единой ряби не качнулось. Повернувшись налево, глядя вниз на небритого и изможденного себя в озере, я снова увидел уголком глаза. . . ┭┮﹏┭┮ . . Глядя на несколько пар у озера, то разговаривающих, то смеющихся, то шепчущихся, то флиртующих, зизизи, немного интересно, только я все думаю, как оптимизировать алгоритм SMO.

Подождите минуту. . . Маленькая парочка? ? ? Оптимизация СМО? ? ?

Я помню, что в основной идее алгоритма SMO, написанного в предыдущей статье, это постоянная итерация по парамальфаi\alpha_iиальфаj\alpha_j, но «маленькая парочка» в то время была случайным образом объединена в пары, поэтому было слишком много возможностей для перестановок и комбинаций, что снижало эффективность всего обучения модели. Если говорят, что когда я выбрал эту «маленькую пару» в то время, это было выбрано не случайно, а сознательно и условно, чтобы я мог избежать множества ненужных расчетов возможности, чтобы я мог иметь эффективность обучения модель была значительно улучшена? ? ?

Держу травку, милый, я такой гений, я все это придумал? ? ? Вспышка вдохновения вспыхнула в моем сердце, как первый гром, который я услышал, когда меня мучила жажда, я побежал в лабораторию, и пара молодых пар посмотрела на меня странными и удивленными глазами. . .

Часть вышеуказанного контента является вымышленной и используется только для получения следующего.

Перед этим давайте успокоимся и разберем основной алгоритм SMO из предыдущей статьи:

Приведенное выше изображение — это то, что мы написали, объясняя линейный SVM с отрывом от руки.linear_smoметод см.:«Машинное обучение в действии» — анализ машин опорных векторов, разрыв линейного SVM одной рукой. Среди них Taoye обвел три блока кода, чтобы представить вам:

Первый блок кода, мы можем найти поведение кодаfor i in range(m):,думаю все знают что это оператор цикла.В данном методе он конкретно означает что индекс выбирается за один раз по количеству отсчетовii, а затем использовать этот индекс для определенияальфаi\alpha_i, так что он в конечном итоге "проходит" по всем образцам.

Второй кодовый блок основан наiiЗначение сбрасывается вmmвыбрать один изiiидентичныйjj, а затем в соответствии с этимjjизменить соответствующийальфаj\alpha_j

Третий блок кода, где мы вычисляем большое количество матриц и векторов, мы можем найти, что независимо от первых двухi,jя, джКакой выбор , третий блок кода будет выполняться и вычисляться, но некоторые вычисления совершенно не нужны, что сильно снижает эффективность всего алгоритма SMO, а это не то, что нам нужно.

Подводя итог, нам необходимоальфа\alphaПовозиться с выделением, чтобы оно пропустило вычисление третьего блока кода на некоторое количество.

  • Первыйальфаi\alpha_iвыбор

В предыдущей статье мы также упомянули, что большинство выборок бесполезны для определения поверхностей принятия решений, и только небольшое количество точек выборки может определить конкретные поверхности принятия решений. иальфа\alphaДля выборки выполняется следующее соотношение:

{альфаi=0<=>yi(wT+b)1альфаi=C<=>yi(wT+b)10альфаiC<=>yi(wT+b)=1\left\{ \begin{array}{c} \alpha_i=0 \quad <=> \quad y_i(w^T+b)\geq1\\ \alpha_i=C \quad <=> \quad y_i(w^T+b)\leq1\\ 0\leq\alpha_i\leq C \quad <=> \quad y_i(w^T+b)=1\\ \end{array} \right.

во-первыхальфаi\alpha_iвыбор, инициализацияальфа\alphaВектор равен 0, поэтому первая итерация выполняется для всех точек выборки. После завершения первой итерацииальфа\alphaВектор обновлен, в последующем итерационном процессе нам не нужно проходить все выборки, а выбрать(0,C)(0, C)интервалальфаi\alpha_iзначение, потому что другиеальфа\alphaЗначение мало влияет на определение окончательной поверхности принятия решений.

во-первыхальфаi\alpha_iВыбор основного кода выглядит следующим образом, т. е. нашвнешний цикл. вdata_structЭто структура данных, в которой хранятся некоторые общедоступные свойства, о которых мы поговорим позже:

"""
    Author:Taoye
    微信公众号:玩世不恭的Coder
    Explain:外层循环,选取第一个合适alpha
    Parameters:
        x_data: 样本属性特征矩阵
        y_label: 属性特征对应的标签
        C:惩罚参数
        toler:容错率
        max_iter:迭代次数
    Return:
        b: 决策面的参数b
        alphas:获取决策面参数w所需要的alphas
"""
def outer_smo(self, data_struct, x_data, y_label, C, toler, max_iter):
	iter_num, ergodic_flag, alpha_optimization_num = 0, True, 0
	while (iter_num < max_iter) and ((alpha_optimization_num > 0) or (ergodic_flag)):
		alpha_optimization_num = 0
		if ergodic_flag:
			for i in range(data_struct.m):
				alpha_optimization_num += self.inner_smo(i, data_struct)
				print("遍历所有样本数据:第%d次迭代,样本为:%d,alpha优化的次数:%d" % (iter_num, i, alpha_optimization_num))
			iter_num += 1
		else:
			no_zero_index = np.nonzero((data_struct.alphas.A > 0) * (data_struct.alphas.A < C))[0]
			for i in no_zero_index:
				alpha_optimization_num += self.inner_smo(i, data_struct)
				print("非边界遍历样本数据:第%d次迭代,样本为:%d,alpha优化的次数:%d" % (iter_num, i, alpha_optimization_num))
			iter_num += 1
		if ergodic_flag: ergodic_flag = False
		elif alpha_optimization_num == 0: ergodic_flag = True
		print("迭代次数:%d" % iter_num)
	return data_struct.b, data_struct.alphas
  • секундаальфаj\alpha_jвыбор

для второгоальфаj\alpha_j, мы могли бы также проанализировать алгоритм SMO в предыдущей статье после окончательной оптимизацииальфа2new\alpha_2^{new}:

альфа2new=y2(E1E2)н+альфа2old\alpha_2^{new}=\frac{y_2(E_1-E_2)}{\eta}+\alpha_2^{old}

мы можем узнатьальфа2\alpha_2В основном он оптимизируется путем обновления итераций, в то время какальфа2old\alpha_2^{old}известно, мы не имеем права выбирать, ноy2(E1E2)н\frac{y_2(E_1-E_2)}{\eta}Значение этой части можно контролировать, то есть мы должны выбрать соответствующийальфаj\alpha_jЧтобы сделать значение последней части как можно больше, чтобы добиться быстрой модификацииальфа\alphaНазначение вектора — более быстрое достижение тренировочного насыщения.

Проще говоряальфа2new\alpha_2^{new}изменения зависят отE1E2|E_1-E_2|, когда абсолютное значение больше,альфа2\alpha_2тем больше изменение. Это,E1E_1Когда он положительный, мы хотим выбрать наименьший возможныйE2E_2,E1E_1Когда оно отрицательное, мы должны выбрать максимально возможноеE2E_2. Согласно этой идее, мы можем сделать эту "маленькую пару" идеальной парой, такой красивой~~

во-первыхальфаi\alpha_iВыбор основного кода выглядит следующим образом, т. е. нашвнутренняя петлятребуемый выборальфаj\alpha_jсодержание:

def select_appropriate_j(self, i, data_struct, E_i):
	max_k, max_delta_E, E_j = -1, 0, 0
	data_struct.E_cache[i] = [1, E_i]
	valid_E_cache_list = np.nonzero(data_struct.E_cache[:, 0].A)[0]
	if (len(valid_E_cache_list) > 1):
		for k in valid_E_cache_list:
			if k == i: continue
			E_k = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, k)
			delta_E = abs(E_i - E_k)
			if (delta_E > max_delta_E): max_k, max_delta_E, E_j = k, delta_E, E_k
		return max_k, E_j
	else: 
		j = self.random_select_alpha_j(i, data_struct.m)
		E_j = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, j)
	return j, E_j

Чтобы облегчить нам использование некоторых общих ресурсов о наборах данных и моделях и удобно с ними работать, нам необходимо инкапсулировать отдельную структуру данных (конечно, без инкапсуляции нет проблем), Объясняются соответствующие свойства структуры данных следующее:

  1. х_данные:etablish_dataСлучайным образом сгенерируйте матрицу атрибутов в наборе данных
  2. у_метка:etablish_dataПроизвольное создание меток в наборе данных
  3. C: параметр штрафа
  4. toler: уровень отказоустойчивости
  5. m: количество выборок данных
  6. альфа: что нужно для обучения алгоритму SMOальфа\alphaвектор
  7. b: Что нужно для обучения алгоритму SMObbпараметр
  8. E_cache: используется для сохранения ошибки, первый столбец — бит действительного флага, а второй столбец — ошибка E, соответствующая индексу выборки.

Кроме того, чтобы улучшить масштабируемость и гибкость кода, метод также извлекается отдельно.update_E_k, в основном для обновленияdata_structв объектеE_cacheАтрибуты:

def update_E_k(self, data_struct, k):
	E_k = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, k)                                        #计算Ek
	data_struct.E_cache[k] = [1,E_k]

Полный код:

import numpy as np
import pylab as pl
from matplotlib import pyplot as plt

class DataStruct:
	def __init__(self, x_data, y_label, C, toler):
		self.x_data = x_data
		self.y_label = y_label
		self.C = C
		self.toler = toler
		self.m = x_data.shape[0]
		self.alphas = np.mat(np.zeros((self.m, 1)))
		self.b = 0
		self.E_cache = np.mat(np.zeros((self.m, 2)))

class OptimizeLinearSVM:
	def __init__(self):
		pass

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 用于生成训练数据集
	    Parameters:
	        data_number: 样本数据数目
	    Return:
	        x_data: 数据样本的属性矩阵
	        y_label: 样本属性所对应的标签
	"""
	def etablish_data(self, data_number):
		np.random.seed(38)
		x_data = np.concatenate((np.add(np.random.randn(data_number, 2), [3, 3]),       
	                             np.subtract(np.random.randn(data_number, 2), [3, 3])),
	                             axis = 0)      # random随机生成数据,+ -3达到不同类别数据分隔的目的 
		temp_data = np.zeros([data_number])
		temp_data.fill(-1)
		y_label = np.concatenate((temp_data, np.ones([data_number])), axis = 0)
		return x_data, y_label

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 随机选取alpha_j
	    Parameters:
	        alpha_i_index: 第一个alpha的索引
	        alpha_number: alpha总数目
	    Return:
	        alpha_j_index: 第二个alpha的索引
	"""
	def random_select_alpha_j(self, alpha_i_index, alpha_number):
		alpha_j_index = alpha_i_index
		while alpha_j_index == alpha_i_index:
			alpha_j_index = np.random.randint(0, alpha_number)
		return alpha_j_index

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 使得alpha_j在[L, R]区间之内
	    Parameters:
	        alpha_j: 原始alpha_j
	        L: 左边界值
	        R: 右边界值
	    Return:
	        L,R,alpha_j: 修改之后的alpha_j
	"""
	def modify_alpha(self, alpha_j, L, R):
		if alpha_j < L: return L
		if alpha_j > R: return R
		return alpha_j

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 计算误差并返回
	"""
	def calc_E(self, alphas, y_label, x_data, b, i):
		f_x_i = float(np.dot(np.multiply(alphas, y_label).T, x_data * x_data[i, :].T)) + b
		return f_x_i - float(y_label[i])

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 计算eta并返回
	"""
	def calc_eta(self, x_data, i, j):
		eta = 2.0 * x_data[i, :] * x_data[j, :].T \
	            - x_data[i, :] * x_data[i, :].T \
	            - x_data[j, :] * x_data[j,:].T
		return eta

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 计算b1, b2并返回
	"""
	def calc_b(self, b, x_data, y_label, alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j):
		b1 = b - E_i \
	         - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[i, :].T \
	         - y_label[j] * (alphas[j] - alpha_j_old) * x_data[i, :] * x_data[j, :].T
		b2 = b - E_j \
	         - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[j, :].T \
	         - y_label[j] * (alphas[j] - alpha_j_old) * x_data[j, :] * x_data[j, :].T
		return b1, b2

	def select_appropriate_j(self, i, data_struct, E_i):
		max_k, max_delta_E, E_j = -1, 0, 0
		data_struct.E_cache[i] = [1, E_i]
		valid_E_cache_list = np.nonzero(data_struct.E_cache[:, 0].A)[0]
		if (len(valid_E_cache_list) > 1):
			for k in valid_E_cache_list:
				if k == i: continue
				E_k = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, k)
				delta_E = abs(E_i - E_k)
				if (delta_E > max_delta_E): max_k, max_delta_E, E_j = k, delta_E, E_k
			return max_k, E_j
		else: 
			j = self.random_select_alpha_j(i, data_struct.m)
			E_j = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, j)
		return j, E_j

	def update_E_k(self, data_struct, k):
		E_k = self.calc_E(data_struct.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, k)                                        #计算Ek
		data_struct.E_cache[k] = [1,E_k]
	
	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: smo内层
	"""
	def inner_smo(self, i, data_strcut):
		E_i = self.calc_E(data_strcut.alphas, data_struct.y_label, data_struct.x_data, data_struct.b, i)      # 调用calc_E方法计算样本i的误差
		if ((data_struct.y_label[i] * E_i < -data_struct.toler) and (data_struct.alphas[i] < data_struct.C)) or ((data_struct.y_label[i] * E_i > data_struct.toler) and (data_struct.alphas[i] > 0)):
			j, E_j = self.select_appropriate_j(i, data_strcut, E_i)              # 选取一个恰当的j
			alpha_i_old, alpha_j_old = data_struct.alphas[i].copy(), data_struct.alphas[j].copy()
			if (data_struct.y_label[i] != data_struct.y_label[j]):               # 确保alphas在[L, R]区间内
				L, R = max(0, data_struct.alphas[j] - data_struct.alphas[i]), min(data_struct.C, data_struct.C + data_struct.alphas[j] - data_struct.alphas[i])
			else:
				L, R = max(0, data_struct.alphas[j] + data_struct.alphas[i] - data_struct.C), min(data_struct.C, data_struct.alphas[j] + data_struct.alphas[i])
			if L == R: print("L==R"); return 0          # L==R时选取下一个样本
			eta = self.calc_eta(data_struct.x_data, i, j)                  # 计算eta值
			if eta >= 0: print("eta>=0"); return 0
			data_struct.alphas[j] -= data_struct.y_label[j] * (E_i - E_j) / eta
			data_struct.alphas[j] = self.modify_alpha(data_struct.alphas[j], L, R)     # 修改alpha[j]
			self.update_E_k(data_strcut, j)
			if (abs(data_strcut.alphas[j] - alpha_j_old) < 0.000001): print("alpha_j修改太小了"); return 0
			data_struct.alphas[i] += data_strcut.y_label[j] * data_strcut.y_label[i] * (alpha_j_old - data_strcut.alphas[j])
			self.update_E_k(data_strcut, i)
			b1, b2= self.calc_b(data_struct.b, data_struct.x_data, data_struct.y_label, data_struct.alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j)    # 计算b值
			if (0 < data_struct.alphas[i]) and (data_struct.C > data_struct.alphas[i]): data_struct.b = b1
			elif (0 < data_struct.alphas[j]) and (data_struct.C > data_struct.alphas[j]): data_struct.b = b2
			else: data_struct.b = (b1 + b2)/2.0
			return 1
		else: return 0

	"""
	    Author:Taoye
	    微信公众号:玩世不恭的Coder
	    Explain:外层循环,选取第一个合适alpha
	    Parameters:
	        x_data: 样本属性特征矩阵
	        y_label: 属性特征对应的标签
	        C:惩罚参数
	        toler:容错率
	        max_iter:迭代次数
	    Return:
	        b: 决策面的参数b
	        alphas:获取决策面参数w所需要的alphas
	"""
	def outer_smo(self, data_struct, x_data, y_label, C, toler, max_iter):
		iter_num, ergodic_flag, alpha_optimization_num = 0, True, 0
		while (iter_num < max_iter) and ((alpha_optimization_num > 0) or (ergodic_flag)):
			alpha_optimization_num = 0
			if ergodic_flag:
				for i in range(data_struct.m):
					alpha_optimization_num += self.inner_smo(i, data_struct)
					print("遍历所有样本数据:第%d次迭代,样本为:%d,alpha优化的次数:%d" % (iter_num, i, alpha_optimization_num))
				iter_num += 1
			else:
				no_zero_index = np.nonzero((data_struct.alphas.A > 0) * (data_struct.alphas.A < C))[0]
				for i in no_zero_index:
					alpha_optimization_num += self.inner_smo(i, data_struct)
					print("非边界遍历样本数据:第%d次迭代,样本为:%d,alpha优化的次数:%d" % (iter_num, i, alpha_optimization_num))
				iter_num += 1
			if ergodic_flag: ergodic_flag = False
			elif alpha_optimization_num == 0: ergodic_flag = True
			print("迭代次数:%d" % iter_num)
		return data_struct.b, data_struct.alphas

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 根据公式计算出w权值向量
	    Parameters:
	        x_data: 样本属性特征矩阵
	        y_label: 属性特征对应的标签
	        alphas:linear_smo方法所返回的alphas向量
	    Return:
	        w: 决策面的参数w
	"""
	def calc_w(self, x_data, y_label, alphas):
		x_data, y_label, alphas = np.array(x_data), np.array(y_label), np.array(alphas)
		return np.dot((np.tile(y_label.reshape(1, -1).T, (1, 2)) * x_data).T, alphas).tolist()

	"""
	    Author: Taoye
	    微信公众号: 玩世不恭的Coder
	    Explain: 绘制出分类结果
	    Parameters:
	        x_data: 样本属性特征矩阵
	        y_label: 属性特征对应的标签
	        w:决策面的w参数
	        b:决策面的参数b
	"""
	def plot_result(self, x_data, y_label, w, b):
		data_number, _ = x_data.shape; middle = int(data_number / 2)
		plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = pl.cm.Paired)
		x1, x2 = np.max(x_data), np.min(x_data)
		w1, w2 = w[0][0], w[1][0]
		y1, y2 = (-b - w1 * x1) / w2, (-b - w1 * x2) / w2
		plt.plot([float(x1), float(x2)], [float(y1), float(y2)])    # 绘制决策面
		for index, alpha in enumerate(alphas):
			if alpha > 0:
				b_temp = - w1 * x_data[index][0] - w2 * x_data[index][1]
				y1_temp, y2_temp = (-b_temp - w1 * x1) / w2, (-b_temp - w1 * x2) / w2
				plt.plot([float(x1), float(x2)], [float(y1_temp), float(y2_temp)], "k--")    # 绘制支持向量
				plt.scatter(x_data[index][0], x_data[index][1], s=150, c='none', alpha=0.7, linewidth=2, edgecolor='red')   # 圈出支持向量
		plt.show()

if __name__ == '__main__':
	optimize_linear_svm = OptimizeLinearSVM()
	x_data, y_label = optimize_linear_svm.etablish_data(50)
	data_struct = DataStruct(np.mat(x_data), np.mat(y_label).T, 0.8, 0.00001)
	b, alphas = optimize_linear_svm.outer_smo(data_struct, x_data, y_label, data_struct.C, data_struct.toler, 10)
	w = optimize_linear_svm.calc_w(x_data, y_label, alphas)
	optimize_linear_svm.plot_result(x_data, y_label, w, b)

Результаты оптимизированной классификации:

Содержание этого выпуска не так много, в основном для оптимизации алгоритма SMO в содержании предыдущего выпуска, тем самым в определенной степени повышая эффективность обучения модели.Поскольку алгоритм линейного SVM реализуется вручную, модель может не достичь этих встроенных платформ.Производительность, заинтересованные читатели могут постепенно оптимизировать самостоятельно.

Линейный SVM должен быть временно записан здесь, а нелинейный связанный контент должен быть обновлен позже.

Я Taoye, я люблю учиться, делиться и люблю различные технологии. В свободное время я люблю играть в шахматы, слушать музыку и говорить об анимации. Я надеюсь использовать это для записи моего собственного процесса роста и жизни. Я также надеюсь, что смогу завести больше друзей-единомышленников в кругу, и приглашаю посетить WeChat Princess для получения большего количества контента:Циничный кодер

Использованная литература:

[1] «Машинное обучение на практике»: издательство Питера Харрингтона «Народная почта и телекоммуникации». [2] «Статистические методы обучения»: Li Hang, второе издание, издательство Университета Цинхуа.

Рекомендуемое чтение

«Машинное обучение в действии» — анализ машин опорных векторов, разрыв линейного SVM одной рукой print("Привет, NumPy!") Что ты не можешь сделать, сначала поешь Таойе проникла в штаб-квартиру черной платформы, и правда, стоящая за этим, была чрезвычайно ужасающей. «База данных Dahua» — когда выполняется оператор SQL, какие небольшие действия выполняет нижний уровень? В те годы Git, в который мы играли, действительно ароматный Создание среды глубокого обучения на основе блокнота Ubuntu+Python+Tensorflow+Jupyter Причудливый синтаксический анализ веб-страницы Рука об руку, чтобы помочь вам понять технологию контейнеров Docker Подробное объяснение сайта Hexo+Github Xiaobai. Правильный способ открытия ElasticSearch, kibana, logstash