李航《統計學習方法》第2版 第2章課後習題答案

徐福仁發表於2020-11-09

習題2.1

題目:Minsky與Papert指出:感知機因為是線性模型,所以不能表示複雜的函式,如異或(XOR),驗證感知機為什麼不能表示異或。
在這裡插入圖片描述

習題2.2

題目:模仿例題2.1,構建從訓練資料集求解感知機模型的例子。
解:這裡用python程式碼分別實現一下感知機學習演算法的原始形式與對偶形式

原始形式:

"""
	感知機(原始形式):實現書本P40頁 例題2.1
"""
import numpy as np
import matplotlib.pyplot as plt

class MyPerceptron():
	def __init__(self):
		# 因為w的維度與x一致,所以先不定義為固定維度
		self.w = None
		self.b = 0
		self.lr = 1
	def fit(self, x_train, y_train):
		self.w = np.zeros(x_train.shape[1])
		i=0
		while i < x_train.shape[0]:
			x = x_train[i]
			y = y_train[i]

			#若為誤分類點則更新引數,重新遍歷樣本集
			if y*(np.dot(self.w,x) + self.b) <= 0:
				self.w = self.w + self.lr * np.dot(y,x)
				self.b = self.b + self.lr * y
				i=0
			else:
				i += 1

def draw(X, w, b):
	# 生產分離超平面上的兩點
	X_new = np.array([0,6])
	y_predict  = -(b + w[0] * X_new) / w[1]
	# 繪製訓練資料集的散點圖
	plt.plot(X[:2, 0], X[:2, 1], "g*", label="1")
	plt.plot(X[2:, 0], X[2:, 1], "rx", label="-1")
	# 繪製分離超平面
	plt.plot(X_new, y_predict, "b-")
	# 設定兩座標軸起止值
	plt.axis([0, 6, 0, 6])
	plt.xlabel('x1')
	plt.ylabel('x2')
	plt.legend()
	plt.show()

def main():
	x_train = np.array([[3, 3], [4, 3], [1, 1]])
	y = np.array([1, 1, -1])
	Perceptron = MyPerceptron()
	Perceptron.fit(x_train, y)
	draw(x_train, Perceptron.w, Perceptron.b)

if __name__ == "__main__":
	main()

結果:
在這裡插入圖片描述

對偶形式:

"""
	感知機(對偶形式):實現書本P40頁 例題2.1
"""

import numpy as np
import matplotlib.pyplot as plt

class MyPerceptron():
	def __init__(self):
		# 因為w的維度與x一致,所以先不定義為固定維度
		self.a = None
		self.w = None
		self.b = 0
		self.lr = 1

	def fit(self, x_train, y_train, Gram_Matrix):
		self.a = np.zeros(x_train.shape[0])
		i=0
		while i < x_train.shape[0]:
			x = x_train[i]
			y = y_train[i]
			#若為誤分類點則更新引數,重新遍歷樣本集
			if y*(np.sum(self.a*y_train*Gram_Matrix[:,i])+self.b) <= 0:
				self.a[i] = self.a[i] + self.lr
				self.b = self.b + self.lr*y
				i = 0
			else:
				i += 1

		#因為看公式可以知道y_train與self.a是對應位置相乘,他們與x_train是矩陣乘法
		#所以將x_train轉換為矩陣(array中的*代表對應位置相乘,而mat中的*為矩陣乘法)
		self.w = y_train * self.a * np.mat(x_train)

		#這裡修改下w維度,為了和原始形式程式中的draw函式統一
		self.w = np.squeeze(np.array(self.w))

def draw(X, w, b):
	# 生產分離超平面上的兩點
	X_new = np.array([0,6])
	y_predict  = -(b + w[0] * X_new) / w[1]
	# 繪製訓練資料集的散點圖
	plt.plot(X[:2, 0], X[:2, 1], "g*", label="1")
	plt.plot(X[2:, 0], X[2:, 1], "rx", label="-1")
	# 繪製分離超平面
	plt.plot(X_new, y_predict, "b-")
	# 設定兩座標軸起止值
	plt.axis([0, 6, 0, 6])
	plt.xlabel('x1')
	plt.ylabel('x2')
	plt.legend()
	plt.show()


def main():
	x_train = np.array([[3, 3], [4, 3], [1, 1]])
	y = np.array([1, 1, -1])
	#生成Gram矩陣
	Gram_Matrix = np.zeros(shape=(3,3))
	for i in range(3):
		for j in range(3):
			Gram_Matrix[i][j] = np.dot(x_train[i], x_train[j].T)

	Perceptron = MyPerceptron()
	Perceptron.fit(x_train, y, Gram_Matrix)
	draw(x_train, Perceptron.w, Perceptron.b)

if __name__ == "__main__":
	main()

結果:
在這裡插入圖片描述
(感知機學習演算法存在無窮多個解,這些解既依賴於初值的選擇,也依賴於迭代過程中誤分類點的選擇順序。)

習題2.3

題目:證明以下定理:樣本集線性可分的充分必要條件是正例項點集所構成的凸殼與負例項點集所構成的凸殼互不相交。
在這裡插入圖片描述

新手一枚,如果有錯,評論區幫忙指正謝謝大佬們,thanks~

相關文章