Python 为什么我的数组值没有得到更新?线性回归
我需要在不使用scikit的情况下用python创建一个线性回归模型。 您可以忽略涉及输入的部分,因为该部分是根据提供给我的文件进行的。我已经添加了我的全部代码,以防我做错了什么Python 为什么我的数组值没有得到更新?线性回归,python,pandas,numpy,machine-learning,linear-regression,Python,Pandas,Numpy,Machine Learning,Linear Regression,我需要在不使用scikit的情况下用python创建一个线性回归模型。 您可以忽略涉及输入的部分,因为该部分是根据提供给我的文件进行的。我已经添加了我的全部代码,以防我做错了什么 import pandas as pd import numpy as np import matplotlib.pyplot as mlt from sklearn.cross_validation import train_test_split data = pd.read_csv("housing.csv",
import pandas as pd
import numpy as np
import matplotlib.pyplot as mlt
from sklearn.cross_validation import train_test_split
data = pd.read_csv("housing.csv", delimiter = ' ', skipinitialspace = True, names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV'])
df_x = data.drop('MEDV', axis = 1)
df_y = data['MEDV']
x_train, x_test, y_train, y_test = train_test_split(df_x.values, df_y.values, test_size = 0.2, random_state = 4)
theta = np.zeros((1, 13))
在上面的代码中,我刚刚获取了输入并创建了一个名为θ的参数数组
def costfn(x, y, theta):
j = np.sum(x.dot(theta.T) - y) ** 2 / (2 * len(y))
return j
def gradient(x, y, theta, alpha, iterations):
cost_history = [0] * iterations
for i in range(iterations):
h = theta.dot(x.T) #hypothesis
loss = h - y
#print(loss)
g = loss.dot(x) / len(y)
#print(g)
theta = theta - alpha * g
cost_history[i] = costfn(x, y, theta)
#print(theta)
return theta, cost_history
theta, cost_history = gradient(x_train, y_train, theta, 0.001, 1000)
#print(theta)
我所评论的所有行都以适当大小的nan输出
我使用了一种与所用逻辑相似的逻辑
如果我错了,一定要告诉我。我认为您的代码总体上是有效的。你观察到的很可能与你的阿尔法设置有关。它似乎太高了,所以θ发散。在某个点上,它得到
inf
或-inf
,然后在下一次迭代中得到NaN
s。我认识到了同样的问题
您可以使用一个简单的设置来验证:
# output theta in your function
def gradient(x, y, theta, alpha, iterations):
cost_history = [0] * iterations
for i in range(iterations):
h = theta.dot(x.T) #hypothesis
#print('h:', h)
loss = h - y
#print('loss:', loss)
g = loss.dot(x) / len(y)
#print('g:', g)
theta = theta - alpha * g
print('theta:', theta)
cost_history[i] = costfn(x, y, theta)
#print(theta)
return theta, cost_history
# set up example data with a simple linear relationship
# where we can play around with different numbers of parameters
# conveniently
# with some noise
num_params= 2 # how many params do you want to estimate (up to 5)
# take some fixed params (we only take num_params of them)
real_params= [2.3, -0.1, 8.5, -1.8, 3.2]
# now generate the data for the number of parameters chosen
x_train= np.random.randint(-100, 100, size=(80, num_params))
x_noise= np.random.randint(-100, 100, size=(80, num_params)) * 0.001
y_train= (x_train + x_noise).dot(np.array(real_params[:num_params]))
theta= np.zeros(num_params)
现在以高学习率尝试
theta, cost_history = gradient(x_train, y_train, theta, 0.1, 1000)
您很可能会观察到,θ值的指数越来越高,直到它们最终达到inf
或-inf
。之后,您将获得NaN
值
但是,如果将其设置为低值(如0.00001),则会看到它收敛:
theta: [ 0.07734451 -0.00357339]
theta: [ 0.15208803 -0.007018 ]
theta: [ 0.22431803 -0.01033852]
theta: [ 0.29411905 -0.01353942]
theta: [ 0.36157275 -0.01662507]
theta: [ 0.42675808 -0.01959962]
theta: [ 0.48975132 -0.02246712]
theta: [ 0.55062617 -0.02523144]
...
theta: [ 2.29993382 -0.09981407]
theta: [ 2.29993382 -0.09981407]
theta: [ 2.29993382 -0.09981407]
theta: [ 2.29993382 -0.09981407]
这非常接近实际参数2.3
和-0.1
因此,您可以使用代码进行实验,以适应学习速度,从而使值更快地收敛,并且发散的风险更低。您还可以实现一些类似于提前停止的功能,这样,如果错误没有改变或者改变低于阈值,它就会停止对样本的迭代
例如,您可以对功能进行以下修改:
def gradient(
x,
y,
theta=None,
alpha=0.1,
alpha_factor=0.1 ** (1/5),
change_threshold=1e-10,
max_iterations=500,
verbose=False):
cost_history = list()
if theta is None:
# theta was not passed explicitely
# so initialize it
theta= np.zeros(x.shape[1])
last_loss_sum= float('inf')
len_y= len(y)
for i in range(1, max_iterations+1):
h = theta.dot(x.T) #hypothesis
loss = h - y
loss_sum= np.sum(np.abs(loss))
if last_loss_sum <= loss_sum:
# the loss didn't decrease
# so decrease alpha
alpha= alpha * alpha_factor
if verbose:
print(f'pass: {i:4d} loss: {loss_sum:.8f} / alpha: {alpha}')
theta_old= theta
g= loss.dot(x) / len_y
if loss_sum <= last_loss_sum and last_loss_sum < float('inf'):
# only apply the change if the loss is
# finite to avoid infinite entries in theta
theta = theta - alpha * g
theta_change= np.sum(np.abs(theta_old - theta))
if theta_change < change_threshold:
# Maybe this seems a bit awkward, but
# the comparison of change_threshold
# takes the relationship between theta and g
# into account. Note that g will not have
# an effect if theta is orders of magnitude
# larger than g, even if g itself is large.
# (I mean if you consider g and theta elementwise)
cost_history.append(costfn(x, y, theta))
break
cost_history.append(costfn(x, y, theta))
last_loss_sum= loss_sum
return theta, cost_history
def梯度(
x,,
Y
θ=无,
α=0.1,
阿尔法系数=0.1**(1/5),
改变阈值=1e-10,
最大迭代次数=500次,
详细=错误):
成本\历史记录=列表()
如果θ为无:
#θ没有明确通过
#所以初始化它
θ=np.零(x.形[1])
上次损失总和=浮动('inf')
len_y=len(y)
对于范围内的i(1,最大迭代次数+1):
h=θ点(x.T)#假设
损耗=h-y
损失总额=净总额(净资产净值(损失))
如果最后一笔损失,谢谢你的回复。我不太确定我是否完全理解你的代码。但是我没有得到我需要的输出。事实上,它已经开始了。通过减少迭代次数(在我发布的代码片段中),我注意到每次迭代后损失都在增加,这不应该发生在正确的情况下?我使用的是波士顿住房数据集,如果这有用的话。是的,你是对的,损失正在分散。这是因为alpha
太高,因此theta
的每次更改都超出了最佳值。因此,如果你喜欢这张图片,你的变化会沿着depest点的“损失谷”往下走,然后爬到另一边,最后落在比开始时更高的地方。您的结果显示在theta
中。这就是函数学习的内容。但是θ不是精确值,而是预测值。你知道的,对吧?顺便说一句,你说的“它来的太远了”是什么意思?我真的建议您尝试我添加的代码,以试验您的函数。如果您了解它对不同参数的反应,以及如何从评估的θ
中获得预测,您还将知道如何将其应用于更复杂的场景,如波士顿住房示例,并且它将帮助您更多,就像您刚刚接管现有代码一样(否则,您可以从scikit学习中获取线性模型)。