核逻辑回归预测错误求助:提升迭代次数仍无效
核逻辑回归实现问题排查
问题概述
实现核逻辑回归函数时,无法得到预期的正确预测结果,存在指数溢出警告(已临时抑制),即使将迭代次数提升至4000,问题仍未解决。
实现代码
import numpy as np import warnings warnings.filterwarnings('ignore') def monomial_kernel(d): def k(x, y, d=d): phi_x_y = 0 prod_xy = np.dot(x.T,y) for n in range(d+1): phi_x_y += (prod_xy ** n) return phi_x_y return k def rbf_kernel(sigma): def k(x, y, sigma=sigma): numerator = np.linalg.norm(x - y) **2 denominator = 2 * (sigma ** 2) return np.exp(-numerator / denominator) return k def sigmoid(z): if type(z) == np.ndarray: z = z[0] try: return 1 / (1 + np.exp(-z)) except: print(z) def logistic_regression_with_kernel(X, y, k, alpha, iterations): n_samples, _ = X.shape bias = 0 kernel_matrix = np.zeros((n_samples, n_samples)) beta = np.zeros(n_samples) #create kernel matrix for i in range(n_samples): for j in range(n_samples): kernel_matrix[i][j] = k(X[i], X[j]) for _ in range(iterations): for i in range(n_samples): total = 0 for j in range(n_samples): total += beta[j] * kernel_matrix[i][j] total += bias sigmoid_value = sigmoid(total) t = y[i] beta += kernel_matrix[i] * alpha * (t - sigmoid_value) bias += (alpha * (t - (sigmoid_value))) def model(x, beta=beta, bias=bias, k=k, ref=X): z = sum([k(ref[i], x) * beta[i] for i in range(ref.shape[0])]) + bias sig = sigmoid(z) # print(sig) return round(sig) return model
测试用例
def test4(): f = lambda x, y, z, w: int(x*y*z - y**2*z*w/4 + x**4*w**3/8- y*w/2 >= 0) training_examples = [ ([0.254, 0.782, 0.254, 0.569], 0), ([0.237, 0.026, 0.237, 0.638], 0), ([0.814, 0.18, 0.814, 0.707], 1), ([0.855, 0.117, 0.855, 0.669], 1), ([0.776, 0.643, 0.776, 0.628], 1), ([0.701, 0.71, 0.701, 0.982], 0), ([0.443, 0.039, 0.443, 0.356], 1), ([0.278, 0.105, 0.278, 0.158], 0), ([0.394, 0.203, 0.394, 0.909], 0), ([0.83, 0.197, 0.83, 0.779], 1), ([0.277, 0.415, 0.277, 0.357], 0), ([0.683, 0.117, 0.683, 0.455], 1), ([0.421, 0.631, 0.421, 0.015], 1) ] X, y = map(np.array, zip(*training_examples)) h = logistic_regression_with_kernel(X, y, monomial_kernel(10), 0.01, 500) test_examples = [ ([0.157, 0.715, 0.787, 0.644], 0), ([0.79, 0.279, 0.761, 0.886], 1), ([0.903, 0.544, 0.138, 0.925], 0), ([0.129, 0.01, 0.493, 0.658], 0), ([0.673, 0.526, 0.672, 0.489], 1), ([0.703, 0.716, 0.088, 0.674], 0), ([0.276, 0.174, 0.69, 0.358], 1), ([0.199, 0.812, 0.825, 0.653], 0), ([0.332, 0.721, 0.148, 0.541], 0), ([0.51, 0.956, 0.023, 0.249], 0) ] print(f"{'x' : ^30}{'prediction' : ^11}{'true' : ^6}") for x, y in test_examples: print(f"{str(x) : ^30}{int(h(x)) : ^11}{y : ^6}") # x prediction true # [0.157, 0.715, 0.787, 0.644] 0 0 # [0.79, 0.279, 0.761, 0.886] 1 1 # [0.903, 0.544, 0.138, 0.925] 0 0 # [0.129, 0.01, 0.493, 0.658] 0 0 # [0.673, 0.526, 0.672, 0.489] 1 1 # [0.703, 0.716, 0.088, 0.674] 0 0 # [0.276, 0.174, 0.69, 0.358] 1 1 # [0.199, 0.812, 0.825, 0.653] 0 0 # [0.332, 0.721, 0.148, 0.541] 0 0 # [0.51, 0.956, 0.023, 0.249] 0 0
问题排查与修复
1. 多项式核函数实现错误
当前monomial_kernel的实现是对x·y的0到d次方求和,这和标准多项式核完全不符。标准d阶多项式核的形式为K(x,y) = (x·y + c)^d(c为常数,通常取1),它对应将特征映射到所有d阶单项式的组合空间,而原实现仅对x·y的幂次求和,无法捕捉特征间的交叉项,导致模型无法拟合测试用例中的4次多项式决策边界。
修复后的多项式核函数:
def monomial_kernel(d, c=1): def k(x, y, d=d, c=c): prod_xy = np.dot(x, y) return (prod_xy + c) ** d return k
如果需要齐次多项式核(无常数项),将c设为0即可。
2. Sigmoid函数数值不稳定
原实现未处理大数值溢出问题,且对数组的处理逻辑错误(仅取数组第一个元素),导致计算结果失真或溢出警告。使用数值稳定的实现可以避免这个问题:
修复后的Sigmoid函数:
def sigmoid(z): z = np.asarray(z) # 分情况计算避免指数溢出 return np.where(z >= 0, 1 / (1 + np.exp(-z)), np.exp(z) / (1 + np.exp(z)))
3. 模型拟合参数调整
- 核函数阶数:测试用例中的决策函数最高为4次多项式,选择
d=4的多项式核即可满足拟合需求,过高的阶数(如d=10)容易导致过拟合。 - 学习率与迭代次数:可尝试将学习率调整为0.005,迭代次数设为1000,同时添加L2正则化防止过拟合(可选):
添加正则化的梯度更新代码:
# 定义正则化系数 lambda_ = 0.001 for _ in range(iterations): for i in range(n_samples): total = np.dot(beta, kernel_matrix[i]) + bias sigmoid_value = sigmoid(total) t = y[i] # 添加L2正则化 beta += kernel_matrix[i] * alpha * (t - sigmoid_value) - alpha * lambda_ * beta bias += alpha * (t - sigmoid_value)
4. 预测函数优化
原model函数中的sum可以用np.dot替换,提升计算效率:
def model(x, beta=beta, bias=bias, k=k, ref=X): kernel_vec = np.array([k(ref[i], x) for i in range(ref.shape[0])]) z = np.dot(beta, kernel_vec) + bias sig = sigmoid(z) return round(sig)
修复后测试
使用修复后的代码,调用测试用例时替换核函数为:
h = logistic_regression_with_kernel(X, y, monomial_kernel(4), 0.005, 1000)
此时模型应该能输出符合预期的预测结果。
内容的提问来源于stack exchange,提问作者StrawberryCookie
相关产品推荐
相关产品推荐

