我知道这个question,但是它是针对过时的功能。
假设我正在尝试根据某人已经访问过的国家和他们的收入来预测一个人是否会访问“X”国。
我在pandas DataFrame中有一个训练数据集,格式如下。
该列为二进制(如果他们访问过该国家,则为1;如果是
他们没有)。
因此,基本上,如果我的数据集中有100,000个人,那么我的数据框的大小为
100,000 x 12
。我希望能够使用tensorflow将其正确传递到线性分类器中。但是甚至不确定如何解决这个问题。我正在尝试将数据传递到此function
estimator = LinearClassifier(
n_classes=n_classes, feature_columns=[sparse_column_a,
sparse_feature_a_x_sparse_feature_b], label_keys=label_keys)
(如果对使用哪种估算器有更好的建议,我可以尝试使用它。)我将数据传递为:
df = pd.DataFrame(np.random.randint(0,2,size=(100, 12)), columns=list('ABCDEFGHIJKL'))
tf_val = tf.estimator.inputs.pandas_input_fn(X.iloc[:, 0:9], X.iloc[:, 11], shuffle=True)
但是,我不确定如何获取此输出并将其正确传递到分类器中。我可以正确设置问题了吗?我不是来自数据科学领域,因此任何指导都将非常有帮助!关注
(赏金所需的工作代码)
最佳答案
线性支持向量机
SVM是最大边距分类器,即它使正类与负类分开的宽度或余量最大化。下面给出了二进制分类情况下线性SVM的损失函数。
它可以从下面显示的更广义的多类线性SVM损耗(也称为铰链损耗)中得出(Δ= 1)。
注意:在上述所有等式中,权重向量w
包括偏差b
到底有人是怎么想出这种损失的? 让我们深入。
上图显示了通过分离的超平面(显示为实线)将属于正类的数据点与属于负类的数据点分开。但是,可以有许多这样的分离超平面。 SVM找到分离的超平面,以使超平面到最近的正数据点和最近的负数据点的距离最大(显示为虚线)。
从数学上讲,SVM找到权重向量w
(包括偏差),使得
如果+ ve类和-ve类的标签(y
)分别是+1
和-1
,则SVM会找到w
,从而
•如果数据点在超平面的正确一侧(正确分类),则
•如果数据点位于错误的一侧(未分类),则
因此,作为未命中分类的量度的数据点损失可以写成
正则化
如果权重向量w
正确分类了数据(X
),则这些权重向量λw
的任意倍数,其中λ>1
也将正确分类数据(零损失)。这是因为转换λW
拉伸(stretch)了所有得分幅度,因此也拉伸(stretch)了它们的绝对差。 L2正则化通过将正则化损失添加到铰链损失中来惩罚较大的权重。
例如,如果x=[1,1,1,1]
和两个权重向量w1=[1,0,0,0]
,w2=[0.25,0.25,0.25,0.25]
。然后dot(W1,x) =dot(w2,x) =1
,即两个权重向量都导致相同的点积并因此导致相同的铰链损耗。但是w1
的L2惩罚是1.0
,而w2
的L2惩罚只是0.25
。因此,L2正则化首选w2
而不是w1
。鼓励分类器将所有输入维度都考虑在内,而不是非常严格地考虑一些输入维度。这改善了模型的通用性,并减少了过度拟合。
L2损失导致SVM中的最大 margin 属性。如果将SVM表示为优化问题,则约束二次优化问题的广义Lagrangian形式如下
既然我们知道了线性SVM的损失函数,我们就可以使用梯度体面(或其他优化器)来找到将损失最小化的权重向量。
代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
# Load Data
iris = datasets.load_iris()
X = iris.data[:, :2][iris.target != 2]
y = iris.target[iris.target != 2]
# Change labels to +1 and -1
y = np.where(y==1, y, -1)
# Linear Model with L2 regularization
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1, activation='linear', kernel_regularizer=tf.keras.regularizers.l2()))
# Hinge loss
def hinge_loss(y_true, y_pred):
return tf.maximum(0., 1- y_true*y_pred)
# Train the model
model.compile(optimizer='adam', loss=hinge_loss)
model.fit(X, y, epochs=50000, verbose=False)
# Plot the learned decision boundary
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
np.arange(y_min, y_max, 0.01))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.show()
SVM也可以表示为约束二次优化问题。这种表述的优点是我们可以使用内核技巧对非线性可分离数据进行分类(使用不同的内核)。 LIBSVM为内核化支持向量机(SVM)实现了序列最小优化(SMO)算法。
代码
from sklearn.svm import SVC
# SVM with linear kernel
clf = SVC(kernel='linear')
clf.fit(X, y)
# Plot the learned decision boundary
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
np.arange(y_min, y_max, 0.01))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.show()
最后
您可以将tf用于问题陈述的线性SVM模型是
# Prepare Data
# 10 Binary features
df = pd.DataFrame(np.random.randint(0,2,size=(1000, 10)))
# 1 floating value feature
df[11] = np.random.uniform(0,100000, size=(1000))
# True Label
df[12] = pd.DataFrame(np.random.randint(0, 2, size=(1000)))
# Convert data to zero mean unit variance
scalar = StandardScaler().fit(df[df.columns.drop(12)])
X = scalar.transform(df[df.columns.drop(12)])
y = np.array(df[12])
# convert label to +1 and -1. Needed for hinge loss
y = np.where(y==1, +1, -1)
# Model
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1, activation='linear',
kernel_regularizer=tf.keras.regularizers.l2()))
# Hinge Loss
def my_loss(y_true, y_pred):
return tf.maximum(0., 1- y_true*y_pred)
# Train model
model.compile(optimizer='adam', loss=my_loss)
model.fit(X, y, epochs=100, verbose=True)
K折交叉验证和做出预测
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import KFold
from sklearn.metrics import roc_curve, auc
# Load Data
iris = datasets.load_iris()
X = iris.data[:, :2][iris.target != 2]
y_ = iris.target[iris.target != 2]
# Change labels to +1 and -1
y = np.where(y_==1, +1, -1)
# Hinge loss
def hinge_loss(y_true, y_pred):
return tf.maximum(0., 1- y_true*y_pred)
def get_model():
# Linear Model with L2 regularization
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1, activation='linear', kernel_regularizer=tf.keras.regularizers.l2()))
model.compile(optimizer='adam', loss=hinge_loss)
return model
def sigmoid(x):
return 1 / (1 + np.exp(-x))
predict = lambda model, x : sigmoid(model.predict(x).reshape(-1))
predict_class = lambda model, x : np.where(predict(model, x)>0.5, 1, 0)
kf = KFold(n_splits=2, shuffle=True)
# K Fold cross validation
best = (None, -1)
for i, (train_index, test_index) in enumerate(kf.split(X)):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model = get_model()
model.fit(X_train, y_train, epochs=5000, verbose=False, batch_size=128)
y_pred = model.predict_classes(X_test)
val = roc_auc_score(y_test, y_pred)
print ("CV Fold {0}: AUC: {1}".format(i+1, auc))
if best[1] < val:
best = (model, val)
# ROC Curve using the best model
y_score = predict(best[0], X)
fpr, tpr, _ = roc_curve(y_, y_score)
roc_auc = auc(fpr, tpr)
print (roc_auc)
# Plot ROC
plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange',
lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
plt.show()
# Make predictions
y_score = predict_class(best[0], X)
做出预测
由于模型的输出是线性的,因此我们必须将其归一化为预测的概率。如果是二进制分类,则可以使用
sigmoid
;如果它是多分类,则可以使用softmax
。以下代码用于二进制分类predict = lambda model, x : sigmoid(model.predict(x).reshape(-1))
predict_class = lambda model, x : np.where(predict(model, x)>0.5, 1, 0)
引用
更新1:
为了使代码与tf 2.0兼容,
y
的数据类型应与X
相同。为此,请在y = np.where(.....
行之后添加y = y.astype(np.float64)
行。
关于python - 使用Tensorflow的LinearClassifier和Panda的数据框构建SVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55424906/