我写了一个简单的程序来分类一组线性可分的2D随机点。我使用了一个感知器,我用fit方法训练它。现在我想一次训练感知器一个点,每次使用更新的权重绘制超平面(在这种情况下是一条线)。我想要获得的是一个动画,它显示了线条如何变得越来越精确。 拟合方法需要整个训练集,partial_fit怎么样?我可以创建一个循环,每次使用一对新的输入/输出来提供方法,并连续读取coef_和intercept_?
我在这里阅读了文档http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html,但我对如何实现它有一些疑问。
感谢Vivek Kumar,我在我的代码中实现了partial_fit方法。该程序创建2组坐标,并且对于每对耦合产生一个输出,如果该点在一条线上则为1,如果在该线下则为-1。代码使用fit方法,但是这个版本给出了数据形状的一些问题。我尝试使用reashape来获取X数据而没有任何改进。
import numpy as np
import matplotlib.pyplot as plt
def createLinearSet(nCamp, mTest, qTest):
y_ = []
X_ = np.random.rand(nCamp, 2)*20-10
for n in range(nCamp):
if X_[n][1] >= mTest*X_[n][0]+qTest :
y_.append(1)
else:
y_.append(-1)
return X_, y_
########################################################################
# VARIABLES
iterazioni = 100
eta = 0.6
y = []
error = []
########################################################################
# CREATING DATA SET
m_test = -2
q_test = 3
n_camp = 100
X, y = createLinearSet(n_camp, m_test, q_test)
########################################################################
# 70 % training data and 30 % test data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 0)
########################################################################
# Data normalization
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(X_train) # Calcola la media dei campioni e la deviazione standard
X_train_std = sc.transform(X_train) # Normalizza i dati di test e di addestramento
X_test_std = sc.transform(X_test) # NB. uso media e deviazione dei dati di add. per entrambi,
# così sono confrontabili
########################################################################
# Perceptron initialization
from sklearn.linear_model import Perceptron
ppn = Perceptron(n_iter = iterazioni, eta0 = eta, random_state = 0)
########################################################################
# Online training
num_samples = X_train_std.shape[0]
classes_y = np.unique(y_train)
X_train_std = X_train_std.reshape(-1, 2)
for i in range(num_samples):
ppn.partial_fit(X_train_std[i], y_train[i], classes = classes_y )
########################################################################
# Using test data for evaluation
y_pred = ppn.predict(X_test_std)
########################################################################
# Previsions accuracy
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test, y_pred) * 100
print("Accuracy: {} %".format(round(accuracy,2)))
print(ppn.coef_, ppn.intercept_)
如您所见,问题出在“在线培训”部分。错误是:
/usr/local/lib/python3.5/dist-packages/sklearn/utils/validation.py:395: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample.
从文档中,X必须是: X:{array-like,sparse matrix},shape(n_samples,n_features)
如果我打印X的单个样本,则输出为: [-0.25547959 -1.4763508]
错误在哪里?
将行X_train_std[i].reshape(1,-1)
放在循环中会给我这样的信息:
Traceback (most recent call last):
File "Perceptron_Retta_Online.py", line 57, in <module>
ppn.partial_fit(X_train_std[i].reshape(1,-1), y_train[i], classes = classes_y )
File "/usr/local/lib/python3.5/dist-packages/sklearn/linear_model/stochastic_gradient.py", line 512, in partial_fit
coef_init=None, intercept_init=None)
File "/usr/local/lib/python3.5/dist-packages/sklearn/linear_model/stochastic_gradient.py", line 344, in _partial_fit
X, y = check_X_y(X, y, 'csr', dtype=np.float64, order="C")
File "/usr/local/lib/python3.5/dist-packages/sklearn/utils/validation.py", line 526, in check_X_y
y = column_or_1d(y, warn=True)
File "/usr/local/lib/python3.5/dist-packages/sklearn/utils/validation.py", line 562, in column_or_1d
raise ValueError("bad input shape {0}".format(shape))
ValueError: bad input shape ()
答案 0 :(得分:1)
大多数scikit估算器同时处理完整数据,即。当您调用fit()
方法时,较旧的训练(权重,系数等)将丢失,并且模型仅适用于新数据。
所以要像你说的那样实现它,你是正确的&#34;我做了一个循环,我每次用一对新的输入/输出提供方法,并连续读取coef_和intercept _&#34; ,但略有变化。您需要提供所有先前的值和新的单个值,而不是输入新的单个输入/输出。
为了说明我的观点,你可以做的是(这有点伪编码,所以请沿着评论阅读):
X = your_input
y = your_output
num_samples = X.shape[0]
for i in range(num_samples):
# 1) This is necessary to initialize a new estimator everytime
numpy.random.seed
# 2) This is necessary to initialize a new estimator everytime
estimator = MLPClassifier() OR SGDClassifier() OR ...
# 3) Call fit on data from 0 to current index i
estimator.fit(X[:i+1], y[:i+1])
# Read the following values and do what you want
estimator.coeff_ OR estimator.intercept_
<强>解释强>: 1)在循环内设置随机种子参数,因此在所有循环中将权重初始化为相同(相同的值)。见第2点。
2)每次初始化新对象,而不是使用相同的对象(从循环中初始化),以便分配给它的初始权重是随机的(并且由于点1而固定)。
3)使用从0到当前索引的所有值到学习是你想要的。对于第一个循环,它只有第一个值(索引0),第二个循环是第一个和第二个值,依此类推......
这种方法适用于所有scikit-estimators,但由于重复训练相同的数据点,因此需要花费大量时间(如果数据非常大)。
<强> ALTERNATIVE 强>: 当您链接SGDClassifier时,我假设您可能对在线学习或核心外学习感兴趣,这完全符合您的要求。但并非所有的评估者都能做到这一点。只有listed in the official documentation的估算器才能执行此操作。
他们实现了partial_fit()
方法,这就是你想要的。所以对于他们来说,代码将是这样的:
X = your_input
y = your_output
num_samples = X.shape[0]
estimator = SGDClassifier() OR ... (which implements partial_fit())
for i in range(num_samples):
estimator.fit(X[i], y[i])
estimator.coeff_ OR estimator.intercept_
希望它能够清除并为您提供一种方法。随意询问是否需要帮助。