预测泰坦尼克号乘客的生存
在这篇博文中,我将介绍在著名的 Titanic 数据集上创建机器学习模型的整个过程,这个数据集被世界各地的许多人使用。它提供了泰坦尼克号上乘客的命运信息,按照经济地位(阶级)、性别、年龄和存活率进行汇总。
我最初在 kaggle.com 上写这篇文章,作为“泰坦尼克号:从灾难中学习的机器”竞赛的一部分。在这个挑战中,我们被要求预测泰坦尼克号上的一名乘客是否会生还。
皇家邮轮泰坦尼克号
皇家邮轮泰坦尼克号是一艘英国客轮,1912 年 4 月 15 日凌晨在从南安普敦到纽约市的处女航中与冰山相撞后沉没在北大西洋。据估计,船上有 2224 名乘客和船员,超过 1500 人死亡,这是现代史上最致命的和平时期商业海上灾难之一。皇家邮轮泰坦尼克号是当时最大的水上船只,也是白星航运公司运营的三艘奥运级远洋客轮中的第二艘。泰坦尼克号由贝尔法斯特的哈兰和沃尔夫造船厂建造。她的建筑师托马斯·安德鲁斯死于这场灾难。
导入库
*# linear algebra*
**import** **numpy** **as** **np**
*# data processing*
**import** **pandas** **as** **pd**
*# data visualization*
**import** **seaborn** **as** **sns**
%matplotlib inline
**from** **matplotlib** **import** pyplot **as** plt
**from** **matplotlib** **import** style
*# Algorithms*
**from** **sklearn** **import** linear_model
**from** **sklearn.linear_model** **import** LogisticRegression
**from** **sklearn.ensemble** **import** RandomForestClassifier
**from** **sklearn.linear_model** **import** Perceptron
**from** **sklearn.linear_model** **import** SGDClassifier
**from** **sklearn.tree** **import** DecisionTreeClassifier
**from** **sklearn.neighbors** **import** KNeighborsClassifier
**from** **sklearn.svm** **import** SVC, LinearSVC
**from** **sklearn.naive_bayes** **import** GaussianNB
获取数据
test_df = pd.read_csv("test.csv")
train_df = pd.read_csv("train.csv")
数据探索/分析
train_df.info()
训练集有 891 个样本,11 个特征+目标变量(存活)。其中 2 个特性是浮点数,5 个是整数,5 个是对象。下面我列出了这些特性并做了简短的描述:
survival: Survival
PassengerId: Unique Id of a passenger.
pclass: Ticket class
sex: Sex
Age: Age in years
sibsp: # of siblings / spouses aboard the Titanic
parch: # of parents / children aboard the Titanic
ticket: Ticket number
fare: Passenger fare
cabin: Cabin number
embarked: Port of Embarkationtrain_df.describe()
从上面我们可以看到 38%的训练组成员在泰坦尼克号中幸存。我们还可以看到乘客年龄从 0.4 岁到 80 岁不等。除此之外,我们已经可以检测到一些包含缺失值的特征,比如“年龄”特征。
train_df.head(8)
从上表中,我们可以注意到一些事情。首先,我们需要稍后将大量特征转换为数字特征,以便机器学习算法可以处理它们。此外,我们可以看到特性具有非常不同的范围,我们需要将其转换成大致相同的比例。我们还可以发现更多的包含缺失值(NaN =非数字)的特性,我们需要处理这些特性。
让我们更详细地看看实际上缺少什么数据:
total = train_df.isnull().sum().sort_values(ascending=**False**)
percent_1 = train_df.isnull().sum()/train_df.isnull().count()*100
percent_2 = (round(percent_1, 1)).sort_values(ascending=**False**)
missing_data = pd.concat([total, percent_2], axis=1, keys=['Total', '%'])
missing_data.head(5)
已装载特征只有两个缺失值,可以很容易地填充。处理“年龄”特性要复杂得多,它缺少 177 个值。“小屋”功能需要进一步调查,但看起来我们可能要从数据集中删除它,因为它的 77 %丢失了。
train_df.columns.values
上面你可以看到 11 个特征+目标变量(幸存)。哪些特征有助于提高存活率?
对我来说,如果除了“乘客 Id”、“车票”和“姓名”之外的一切都与高存活率相关联,那就说得通了。
1。年龄性别:
survived = 'survived'
not_survived = 'not survived'
fig, axes = plt.subplots(nrows=1, ncols=2,figsize=(10, 4))
women = train_df[train_df['Sex']=='female']
men = train_df[train_df['Sex']=='male']
ax = sns.distplot(women[women['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[0], kde =**False**)
ax = sns.distplot(women[women['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[0], kde =**False**)
ax.legend()
ax.set_title('Female')
ax = sns.distplot(men[men['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[1], kde = **False**)
ax = sns.distplot(men[men['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[1], kde = **False**)
ax.legend()
_ = ax.set_title('Male')
你可以看到男性在 18 岁到 30 岁之间存活的概率很大,女性也是一点点但不完全对。对于 14 至 40 岁的女性来说,存活的几率更高。
对于男性来说,在 5 岁到 18 岁之间存活的概率非常低,但对于女性来说并非如此。另一件要注意的事情是,婴儿也有更高的存活率。
由于似乎有特定的年龄,这增加了生存的几率,并且因为我希望每个特征都大致在相同的范围内,我将稍后创建年龄组。
3。登船,Pclass 和 Sex:
FacetGrid = sns.FacetGrid(train_df, row='Embarked', size=4.5, aspect=1.6)
FacetGrid.map(sns.pointplot, 'Pclass', 'Survived', 'Sex', palette=**None**, order=**None**, hue_order=**None** )
FacetGrid.add_legend()
上船似乎与生存相关,取决于性别。
Q 端口和 S 端口的女性生存几率更高。反之亦然,如果他们在港口 C。男人有很高的生存概率,如果他们在港口 C,但低概率,如果他们在港口 Q 或 s。
Pclass 似乎也与存活率相关。我们将在下面生成另一个图。
4。Pclass:
sns.barplot(x='Pclass', y='Survived', data=train_df)
这里我们清楚地看到,Pclass 增加了一个人的生存机会,特别是如果这个人在 1 类。我们将在下面创建另一个 pclass 图。
grid = sns.FacetGrid(train_df, col='Survived', row='Pclass', size=2.2, aspect=1.6)
grid.map(plt.hist, 'Age', alpha=.5, bins=20)
grid.add_legend();
上面的图证实了我们对 pclass 1 的假设,但我们也可以发现 pclass 3 中的人很有可能无法存活。
5。SibSp 和 Parch:
SibSp 和 Parch 作为一个组合特征更有意义,它显示了一个人在泰坦尼克号上的亲属总数。我将在下面创建它,也是一个如果有人不孤单时播种的特征。
data = [train_df, test_df]
**for** dataset **in** data:
dataset['relatives'] = dataset['SibSp'] + dataset['Parch']
dataset.loc[dataset['relatives'] > 0, 'not_alone'] = 0
dataset.loc[dataset['relatives'] == 0, 'not_alone'] = 1
dataset['not_alone'] = dataset['not_alone'].astype(int)train_df['not_alone'].value_counts()
axes = sns.factorplot('relatives','Survived',
data=train_df, aspect = 2.5, )
在这里我们可以看到,你有 1 到 3 个亲属的存活概率很高,但如果你的亲属少于 1 个或多于 3 个,存活概率就较低(除了一些有 6 个亲属的情况)。
数据预处理
首先,我将从训练集中删除“PassengerId ”,因为它对一个人的生存概率没有贡献。我不会把它从测试集中删除,因为提交时需要它。
train_df = train_df.drop(['PassengerId'], axis=1)
缺失数据:
小屋: 提醒一下,我们要处理小屋(687)、登船(2)和年龄(177)。首先我想,我们必须删除“小屋”变量,但后来我发现了一些有趣的东西。一个舱号看起来像‘C123’,字母指的是甲板。因此,我们将提取这些并创建一个新的功能,其中包含一个人的甲板。我们将把这个特征转换成一个数字变量。缺少的值将被转换为零。在下面的图片中,你可以看到泰坦尼克号的实际甲板,从 A 到 g。
**import** **re**
deck = {"A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6, "G": 7, "U": 8}
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Cabin'] = dataset['Cabin'].fillna("U0")
dataset['Deck'] = dataset['Cabin'].map(**lambda** x: re.compile("([a-zA-Z]+)").search(x).group())
dataset['Deck'] = dataset['Deck'].map(deck)
dataset['Deck'] = dataset['Deck'].fillna(0)
dataset['Deck'] = dataset['Deck'].astype(int)*# we can now drop the cabin feature*
train_df = train_df.drop(['Cabin'], axis=1)
test_df = test_df.drop(['Cabin'], axis=1)
Age: 现在我们可以解决 Age 特性缺少值的问题。我将创建一个包含随机数的数组,这些随机数是根据平均年龄值计算的,与标准偏差和 is_null 有关。
data = [train_df, test_df]
**for** dataset **in** data:
mean = train_df["Age"].mean()
std = test_df["Age"].std()
is_null = dataset["Age"].isnull().sum()
*# compute random numbers between the mean, std and is_null*
rand_age = np.random.randint(mean - std, mean + std, size = is_null)
*# fill NaN values in Age column with random values generated*
age_slice = dataset["Age"].copy()
age_slice[np.isnan(age_slice)] = rand_age
dataset["Age"] = age_slice
dataset["Age"] = train_df["Age"].astype(int)train_df["Age"].isnull().sum()
着手进行:
由于已装载特征只有两个缺失值,我们将只使用最常见的值来填充它们。
train_df['Embarked'].describe()
common_value = 'S'
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Embarked'] = dataset['Embarked'].fillna(common_value)
转换功能:
train_df.info()
上面你可以看到“票价”是一个浮动,我们必须处理 4 个分类特征:姓名、性别、车票和上船。让我们一个接一个地调查和转换。
Fare: 使用 pandas 提供的函数“astype()”将“Fare”从 float 转换为 int64:
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Fare'] = dataset['Fare'].fillna(0)
dataset['Fare'] = dataset['Fare'].astype(int)
Name: 我们将使用 Name 特性从名称中提取标题,这样我们就可以从中构建一个新的特性。
data = [train_df, test_df]
titles = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
**for** dataset **in** data:
*# extract titles*
dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=**False**)
*# replace titles with a more common title or as Rare*
dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr',\
'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
*# convert titles into numbers*
dataset['Title'] = dataset['Title'].map(titles)
*# filling NaN with 0, to get safe*
dataset['Title'] = dataset['Title'].fillna(0)train_df = train_df.drop(['Name'], axis=1)
test_df = test_df.drop(['Name'], axis=1)
性别: 将‘性别’特征转换为数值。
genders = {"male": 0, "female": 1}
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Sex'] = dataset['Sex'].map(genders)
票:
train_df['Ticket'].describe()
由于门票属性有 681 个独特的门票,这将是一个有点棘手的转换成有用的类别。所以我们将把它从数据集中删除。
train_df = train_df.drop(['Ticket'], axis=1)
test_df = test_df.drop(['Ticket'], axis=1)
已装船: 将‘已装船’特征转换成数值。
ports = {"S": 0, "C": 1, "Q": 2}
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Embarked'] = dataset['Embarked'].map(ports)
创建类别:
我们现在将在以下功能中创建类别:
年龄: 现在我们需要转换‘年龄’特性。首先我们将把它从浮点数转换成整数。然后,我们将创建新的“年龄组”变量,将每个年龄分为一组。请注意,关注如何组成这些组是很重要的,因为您不希望 80%的数据归入组 1。
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Age'] = dataset['Age'].astype(int)
dataset.loc[ dataset['Age'] <= 11, 'Age'] = 0
dataset.loc[(dataset['Age'] > 11) & (dataset['Age'] <= 18), 'Age'] = 1
dataset.loc[(dataset['Age'] > 18) & (dataset['Age'] <= 22), 'Age'] = 2
dataset.loc[(dataset['Age'] > 22) & (dataset['Age'] <= 27), 'Age'] = 3
dataset.loc[(dataset['Age'] > 27) & (dataset['Age'] <= 33), 'Age'] = 4
dataset.loc[(dataset['Age'] > 33) & (dataset['Age'] <= 40), 'Age'] = 5
dataset.loc[(dataset['Age'] > 40) & (dataset['Age'] <= 66), 'Age'] = 6
dataset.loc[ dataset['Age'] > 66, 'Age'] = 6
*# let's see how it's distributed* train_df['Age'].value_counts()
Fare: 对于‘Fare’特性,我们需要做与‘Age’特性相同的事情。但这并不容易,因为如果我们将票价值的范围分成几个同样大的类别,80%的值将属于第一类。幸运的是,我们可以使用 sklearn 的“qcut()”函数,我们可以使用它来查看我们如何形成类别。
train_df.head(10)
data = [train_df, test_df]
**for** dataset **in** data:
dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2
dataset.loc[(dataset['Fare'] > 31) & (dataset['Fare'] <= 99), 'Fare'] = 3
dataset.loc[(dataset['Fare'] > 99) & (dataset['Fare'] <= 250), 'Fare'] = 4
dataset.loc[ dataset['Fare'] > 250, 'Fare'] = 5
dataset['Fare'] = dataset['Fare'].astype(int)
创建新功能
我将向数据集中添加两个新要素,这两个新要素是从其他要素中计算出来的。
1。时代时代班
data = [train_df, test_df]
**for** dataset **in** data:
dataset['Age_Class']= dataset['Age']* dataset['Pclass']
2。每人票价
**for** dataset **in** data:
dataset['Fare_Per_Person'] = dataset['Fare']/(dataset['relatives']+1)
dataset['Fare_Per_Person'] = dataset['Fare_Per_Person'].astype(int)*# Let's take a last look at the training set, before we start training the models.*
train_df.head(10)
构建机器学习模型
现在我们将训练几个机器学习模型,并比较它们的结果。请注意,因为数据集没有为它们的测试集提供标签,所以我们需要使用训练集的预测来相互比较算法。稍后,我们将使用交叉验证。
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test = test_df.drop("PassengerId", axis=1).copy()
随机梯度下降(SGD):
sgd = linear_model.SGDClassifier(max_iter=5, tol=**None**)
sgd.fit(X_train, Y_train)
Y_pred = sgd.predict(X_test)
sgd.score(X_train, Y_train)
acc_sgd = round(sgd.score(X_train, Y_train) * 100, 2)
随机森林:
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
Y_prediction = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
逻辑回归:
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)
Y_pred = logreg.predict(X_test)
acc_log = round(logreg.score(X_train, Y_train) * 100, 2)
K 最近邻:
*# KNN* knn = KNeighborsClassifier(n_neighbors = 3) knn.fit(X_train, Y_train) Y_pred = knn.predict(X_test) acc_knn = round(knn.score(X_train, Y_train) * 100, 2)
高斯朴素贝叶斯:
gaussian = GaussianNB() gaussian.fit(X_train, Y_train) Y_pred = gaussian.predict(X_test) acc_gaussian = round(gaussian.score(X_train, Y_train) * 100, 2)
感知器:
perceptron = Perceptron(max_iter=5)
perceptron.fit(X_train, Y_train)
Y_pred = perceptron.predict(X_test)
acc_perceptron = round(perceptron.score(X_train, Y_train) * 100, 2)
线性支持向量机:
linear_svc = LinearSVC()
linear_svc.fit(X_train, Y_train)
Y_pred = linear_svc.predict(X_test)
acc_linear_svc = round(linear_svc.score(X_train, Y_train) * 100, 2)
决策树
decision_tree = DecisionTreeClassifier() decision_tree.fit(X_train, Y_train) Y_pred = decision_tree.predict(X_test) acc_decision_tree = round(decision_tree.score(X_train, Y_train) * 100, 2)
哪个是最好的型号?
results = pd.DataFrame({
'Model': ['Support Vector Machines', 'KNN', 'Logistic Regression',
'Random Forest', 'Naive Bayes', 'Perceptron',
'Stochastic Gradient Decent',
'Decision Tree'],
'Score': [acc_linear_svc, acc_knn, acc_log,
acc_random_forest, acc_gaussian, acc_perceptron,
acc_sgd, acc_decision_tree]})
result_df = results.sort_values(by='Score', ascending=**False**)
result_df = result_df.set_index('Score')
result_df.head(9)
正如我们所看到的,随机森林分类器放在第一位。但是首先,让我们检查一下,当我们使用交叉验证时,random-forest 是如何执行的。
k 倍交叉验证:
K-Fold 交叉验证将训练数据随机分成称为折叠的 K 个子集**。假设我们将数据分成 4 份(K = 4)。我们的随机森林模型将被训练和评估 4 次,每次使用不同的折叠进行评估,而它将在剩余的 3 个折叠上被训练。**
下图显示了这个过程,使用了 4 次折叠(K = 4)。每行代表一个培训+评估过程。在第一行中,模型 get 在第一、第二和第三子集上被训练,并且在第四子集上被评估。在第二行中,模型 get 在第二、第三和第四个子集上训练,并在第一个子集上评估。K-Fold 交叉验证重复这个过程,直到每个折叠作为一个评估折叠进行一次。
我们的 K-Fold 交叉验证示例的结果将是包含 4 个不同分数的数组。然后我们需要计算这些分数的平均值和标准差。
下面的代码对我们的随机森林模型执行 K-Fold 交叉验证,使用 10 个折叠(K = 10)。因此,它输出一个有 10 个不同分数的数组。
**from** **sklearn.model_selection** **import** cross_val_score
rf = RandomForestClassifier(n_estimators=100)
scores = cross_val_score(rf, X_train, Y_train, cv=10, scoring = "accuracy")print("Scores:", scores)
print("Mean:", scores.mean())
print("Standard Deviation:", scores.std())
这看起来比以前真实多了。我们的模型平均准确率为 82%,标准偏差为 4 %。标准差告诉我们,估计值有多精确。
这意味着在我们的例子中,我们的模型的精度可以相差 + — 4%。
我认为准确性仍然很好,因为随机森林是一个易于使用的模型,我们将在下一节中尝试进一步提高它的性能。
随机森林
什么是随机森林?
随机森林是一种监督学习算法。就像你已经从它的名字中看到的,它创造了一个森林,使它变得随机。它构建的“森林”是决策树的集合,大部分时间是用“打包”方法训练的。bagging 方法的一般思想是学习模型的组合增加了整体结果。
用简单的话来说:随机森林构建多个决策树,将它们合并在一起,得到一个更加准确稳定的预测。
随机森林的一个很大的优点是,它可以用于分类和回归问题,这构成了当前机器学习系统的大多数。除了少数例外,随机森林分类器具有决策树分类器的所有超参数以及 bagging 分类器的所有超参数,以控制整体本身。
随机森林算法在生长树时给模型带来了额外的随机性。它不是在分割节点时搜索最佳特征,而是在随机特征子集中搜索最佳特征。这个过程产生了广泛的多样性,这通常会产生一个更好的模型。因此,当您在随机森林中种植树时,只考虑要素的随机子集来分割节点。您甚至可以通过在每个特征的基础上使用随机阈值,而不是像普通决策树那样搜索最佳阈值,来使树更加随机。
下面你可以看到有两棵树的随机森林的样子:
特征重要性
随机森林的另一个优点是,它使得测量每个特征的相对重要性变得非常容易。Sklearn 通过查看使用该特征的树节点平均减少杂质的程度(跨越森林中的所有树)来测量特征的重要性。它会在训练后自动计算每个特征的分数,并对结果进行缩放,使所有重要度之和等于 1。我们将在下面讨论这个问题:
importances = pd.DataFrame({'feature':X_train.columns,'importance':np.round(random_forest.feature_importances_,3)})
importances = importances.sort_values('importance',ascending=**False**).set_index('feature')importances.head(15)
importances.plot.bar()
结论:
not_alone 和 Parch 在我们的随机森林分类器预测过程中不起重要作用。因此,我将把它们从数据集中删除,并再次训练分类器。我们也可以删除更多或更少的特性,但是这需要更详细地研究特性对我们模型的影响。但是我觉得只单独取出炒一下就可以了。
train_df = train_df.drop("not_alone", axis=1)
test_df = test_df.drop("not_alone", axis=1)
train_df = train_df.drop("Parch", axis=1)
test_df = test_df.drop("Parch", axis=1)
再次训练随机森林:
*# Random Forest*
random_forest = RandomForestClassifier(n_estimators=100, oob_score = **True**)
random_forest.fit(X_train, Y_train)
Y_prediction = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
print(round(acc_random_forest,2,), "%")
92.82%
我们的随机森林模型预测和以前一样好。一般来说,你拥有的功能越多,你的模型就越有可能过度拟合,反之亦然。但我认为我们的数据目前看起来不错,没有太多特征。
还有另一种方法来评估随机森林分类器,这可能比我们之前使用的分数更准确。我说的是出袋样本估计泛化精度。我不会在这里详细介绍它是如何工作的。只需注意,使用与训练集大小相同的测试集,可以获得非常准确的估计。因此,使用袋外误差估计消除了对预留测试集的需要。
print("oob score:", round(random_forest.oob_score_, 4)*100, "%")
oob 分数:81.82 %
现在我们可以开始调整随机森林的超参数了。
超参数调谐
下面您可以看到参数标准的超参数调整代码,min_samples_leaf、min_samples_split 和 n_estimators。
我将这段代码放在 markdown 单元格中,而不是 code 单元格中,因为运行它需要很长时间。在它的正下方,我放了一个 gridsearch 输出的截图。
param_grid = { "criterion" : ["gini", "entropy"], "min_samples_leaf" : [1, 5, 10, 25, 50, 70], "min_samples_split" : [2, 4, 10, 12, 16, 18, 25, 35], "n_estimators": [100, 400, 700, 1000, 1500]}from sklearn.model_selection import GridSearchCV, cross_val_scorerf = RandomForestClassifier(n_estimators=100, max_features='auto', oob_score=True, random_state=1, n_jobs=-1)clf = GridSearchCV(estimator=rf, param_grid=param_grid, n_jobs=-1)clf.fit(X_train, Y_train)clf.best*params*
测试新参数:
*# Random Forest*
random_forest = RandomForestClassifier(criterion = "gini",
min_samples_leaf = 1,
min_samples_split = 10,
n_estimators=100,
max_features='auto',
oob_score=**True**,
random_state=1,
n_jobs=-1)
random_forest.fit(X_train, Y_train)
Y_prediction = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
print("oob score:", round(random_forest.oob_score_, 4)*100, "%")
oob 分数:83.05 %
现在我们有了一个合适的模型,我们可以开始以更准确的方式评估它的性能。以前我们只使用准确性和 oob 分数,这只是准确性的另一种形式。问题是,评估一个分类模型比评估一个回归模型更复杂。我们将在下一节中讨论这一点。
进一步评估
混淆矩阵:
**from** **sklearn.model_selection** **import** cross_val_predict
**from** **sklearn.metrics** **import** confusion_matrix
predictions = cross_val_predict(random_forest, X_train, Y_train, cv=3)
confusion_matrix(Y_train, predictions)
第一行是关于未幸存的预测: 493 名乘客被正确分类为未幸存(称为真阴性) 56 名乘客被错误分类为未幸存(假阳性)。
第二行是关于幸存预测: 93 名乘客被错误地分类为幸存(假阴性),而 249 名乘客被正确地分类为幸存(真阳性)。
混淆矩阵给了你很多关于你的模型表现如何的信息,但是有一种方法可以得到更多,比如计算分类器的精度。
精确度和召回率:
**from** **sklearn.metrics** **import** precision_score, recall_score
print("Precision:", precision_score(Y_train, predictions))
print("Recall:",recall_score(Y_train, predictions))
精度:0.801948051948
召回:0.8000000001
我们的模型预测 81%的时间,一个乘客生存正确(精度)。这份回忆告诉我们,它预测了 73 %的幸存者。
f 分数
你可以把精确度和召回率结合成一个分数,叫做 F 分数。F 分数是用精确度和召回率的调和平均值来计算的。请注意,它将更多的权重分配给低值。因此,如果召回率和精确度都很高,分类器将只获得高 F 值。
**from** **sklearn.metrics** **import** f1_score
f1_score(Y_train, predictions)
0.7599999999999
好了,77 %的 F 分。分数没有那么高,因为我们的召回率是 73%。但不幸的是,F-score 并不完美,因为它倾向于具有相似精度和召回率的分类器。这是一个问题,因为你有时想要高精度,有时想要高召回率。事实是,精确度的增加,有时会导致回忆的减少,反之亦然(取决于阈值)。这被称为精确度/召回率的权衡。我们将在下一节讨论这一点。
精确召回曲线
对于随机森林算法必须分类的每个人,它基于函数计算概率,并将该人分类为幸存(当分数大于阈值时)或未幸存(当分数小于阈值时)。这就是为什么门槛很重要。
我们将使用 matplotlib 绘制精度和召回与阈值的关系:
**from** **sklearn.metrics** **import** precision_recall_curve
*# getting the probabilities of our predictions*
y_scores = random_forest.predict_proba(X_train)
y_scores = y_scores[:,1]
precision, recall, threshold = precision_recall_curve(Y_train, y_scores)**def** plot_precision_and_recall(precision, recall, threshold):
plt.plot(threshold, precision[:-1], "r-", label="precision", linewidth=5)
plt.plot(threshold, recall[:-1], "b", label="recall", linewidth=5)
plt.xlabel("threshold", fontsize=19)
plt.legend(loc="upper right", fontsize=19)
plt.ylim([0, 1])
plt.figure(figsize=(14, 7))
plot_precision_and_recall(precision, recall, threshold)
plt.show()
从上图可以清楚地看到,召回率正在迅速下降,大约在 85%左右。因此,在此之前,您可能希望选择精度/召回率之间的权衡——可能在 75 %左右。
您现在可以选择一个阈值,为您当前的机器学习问题提供最佳的精确度/召回率权衡。例如,如果您想要 80%的精度,您可以很容易地查看这些图,并看到您将需要 0.4 左右的阈值。然后你就可以用这个阈值训练一个模型,并得到你想要的精确度。
另一种方法是将精确度和召回率相互对比:
**def** plot_precision_vs_recall(precision, recall):
plt.plot(recall, precision, "g--", linewidth=2.5)
plt.ylabel("recall", fontsize=19)
plt.xlabel("precision", fontsize=19)
plt.axis([0, 1.5, 0, 1.5])
plt.figure(figsize=(14, 7))
plot_precision_vs_recall(precision, recall)
plt.show()
ROC AUC 曲线
ROC AUC 曲线提供了评估和比较二元分类器的另一种方法。该曲线绘制了真阳性率(也称为召回率)对假阳性率(错误分类的阴性实例的比率),而不是绘制了精度对召回率。
**from** **sklearn.metrics** **import** roc_curve
*# compute true positive rate and false positive rate*
false_positive_rate, true_positive_rate, thresholds = roc_curve(Y_train, y_scores)*# plotting them against each other*
**def** plot_roc_curve(false_positive_rate, true_positive_rate, label=**None**):
plt.plot(false_positive_rate, true_positive_rate, linewidth=2, label=label)
plt.plot([0, 1], [0, 1], 'r', linewidth=4)
plt.axis([0, 1, 0, 1])
plt.xlabel('False Positive Rate (FPR)', fontsize=16)
plt.ylabel('True Positive Rate (TPR)', fontsize=16)
plt.figure(figsize=(14, 7))
plot_roc_curve(false_positive_rate, true_positive_rate)
plt.show()
中间的红线代表一个纯粹随机的分类器(例如抛硬币),因此你的分类器应该尽可能远离它。我们的随机森林模型似乎做得很好。
当然,我们在这里也有一个权衡,因为分类器产生的假阳性越多,真阳性率就越高。
ROC AUC 得分
ROC AUC 得分是 ROC AUC 曲线的相应得分。它只是通过测量曲线下的面积来计算,该面积称为 AUC。
100%正确的分类器的 ROC AUC 得分为 1,完全随机的分类器的得分为 0.5。
**from** **sklearn.metrics** **import** roc_auc_score
r_a_score = roc_auc_score(Y_train, y_scores)
print("ROC-AUC-Score:", r_a_score)
ROC_AUC_SCORE: 0.945067587
不错!我认为这个分数足以将测试集的预测提交给 Kaggle 排行榜。
摘要
我们从数据探索开始,对数据集有所了解,检查缺失的数据,了解哪些特征是重要的。在这个过程中,我们使用 seaborn 和 matplotlib 来做可视化。在数据预处理部分,我们计算缺失值,将特征转换为数值,将值分组并创建一些新特征。之后,我们开始训练 8 个不同的机器学习模型,选择其中一个(随机森林)并对其进行交叉验证。然后我们讨论了随机森林是如何工作的,看看它对不同特性的重要性,并通过优化它的超参数值来调整它的性能。最后,我们查看了它的混淆矩阵,并计算了模型的精度、召回率和 f 值。
下面您可以看到“train_df”数据帧的前后图片:
当然,仍有改进的空间,如通过相互比较和绘制特征并识别和去除有噪声的特征,进行更广泛的特征工程。另一个可以改善 kaggle 排行榜整体结果的事情是对几个机器学习模型进行更广泛的超参数调整。你也可以做一些整体学习。
基于范围预测任务持续时间
使用机器学习进行项目评估。
在之前的条目之一中,我们已经建立了一个统计模型,用于根据估计预测实际项目时间和成本。我们讨论过,我们可以将评估(敏捷项目和瀑布项目)拟合到对数正态分布,这保证了积极的支持。正如我们在另一篇文章的中所讨论的那样,使用统计方法进行估算使我们能够给出具有所需置信水平的预测,并预测货币收益、成本和风险。
我被问到的一件事是,当一个估计值被作为一个范围给出时,这个模型如何推广。事实上,这是每个人都教导我们的:不要给出一个单一的数字,而是范围。一种方法是继续使用我们的统计模型,并在中间输入一个数字,即两个值的平均值。
这样,该模型无需修改即可使用。
这种方法有两个问题:
- 取一个高低的平均值是任意的。它将给出的信息减少了一半。最好有一个算法来学习我们需要在低边界和高边界之间的区间内的什么地方设置变量 x
- 通过给我们一系列的数据,开发者试图向我们传达一个非常重要的信息:评估的不确定性程度。正确的模型应该使用这些信息。
为了简化过程,我们将对所有的估计值和实际值取自然对数。由于我们使用对数正态分布对估计值建模,我们的新变量y
、l
、h
将分别是实际天数、低估计值和高估计值的对数。在这种情况下我们可以使用正态分布!我们将使用线性回归对y
建模:
在 θh 和 θl 相等的情况下,我们会遇到与之前讨论的完全相同的问题。
在这种情况下,单个数据的似然函数可以写成如下形式(在和之后)。
如前所述,通过给出一个范围,开发人员希望向我们传达评估的不确定性。我们应该将这种不确定性包括在我们对 σ 的估计中。直观上,范围与标准偏差成比例,我们可以通过将 σ 建模为:
如果我们也使用精度参数 τ 代替 σ 0:
那么我们的可能性函数将是:
τ 和 θ 的先验传统上分别为伽玛分布和正态分布;
这里 α , β , λ 为超参数。
为 ζ 选择先验比较困难。对于我们选择的这种似然函数,没有共轭先验存在。现在我们可以选择正态分布。这种分布的零均值意味着我们先验地不信任范围(我们知道许多顾问的范围总是 20%并且不传达任何信息)。先验分布的高均值意味着我们更加关注估计的不确定性程度。
为简单起见,我们将平均值设为零。
负对数后验函数为:
在这个博客里我会找到参数,对应最大后验概率。为了避免在微分中出错,我们将使用张量流。我们将按照这个例子来构建我们的代码
import numpy as np
import pandas as pd
import tensorflow as tf
此处的数据代表预计和实际天数。我们看到开发人员喜欢在他的预算中增加 25%作为缓冲。然而,对于一些故事,他增加了更多的缓冲,也许是为了表明更多的不确定性。
seed=1389
tf.reset_default_graph()
task_data = pd.DataFrame({'low':[4,14,4,3,4,3,4,9,6,27,20,23,11],
'high':[5,18,5,4,5,7,5,10,8,30,25,29,14],
'actual':[17,8,5,3,5,4,9,9,4,27,16,15,7,]})%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax = plt.subplots(figsize=(11.7, 8.27))
task_data['story_id'] = task_data.index
data_for_plot = pd.melt(task_data, id_vars="story_id", var_name="type", value_name="days")
task_data.drop(columns=['story_id'], inplace=True)
sns.barplot(x='story_id', y='days', hue='type', data=data_for_plot,ax=ax);
定义变量时,我们用 τ 代替另一个变量 ρ :
这是为了避免优化器选择负的 τ
#Taking the log of data
log_data = np.log(task_data.values)
N = log_data.shape[0]#Defining variables
theta_h = tf.Variable(name='theta_h', initial_value=0.5)
theta_l = tf.Variable(name='theta_l', initial_value=0.5)
zeta = tf.Variable(name='zeta', initial_value=0.01)
rho = tf.Variable(name='rho', initial_value=0.01)
由于不想调太多超参数,我们就把 α 和 β 设为一。两个 λ 参数都作为正则化参数,所以我们必须调整它们
#Set the hyperparameters
alpha = tf.constant(name='alpha', value=1.0)
beta = tf.constant(name='beta', value=1.0)
lambda1 = tf.constant(name='lambda1', value=1e-4)
lambda2 = tf.constant(name='lambda2', value=1e-4)def loss(l, h, y):
return tf.log(1+zeta**2*(h-l)) + \
rho**2/2/(1+zeta**2*(h-l))**2 * (y - theta_l*l - theta_h*h)**2cummulative_loss = tf.reduce_sum(list(np.apply_along_axis(lambda x: loss(*x), axis=1, arr=log_data )))
cost = cummulative_loss - (N+1-2*alpha)/2*tf.log(rho**2) + beta*rho**2 + \
rho**2*lambda1/2*(theta_h**2+theta_l**2) + rho**2*lambda2/2*zeta**2learning_rate = 1e-4
optimizer = tf.train.AdamOptimizer(learning_rate)
train_op = optimizer.minimize(cost)import math
init = tf.global_variables_initializer()
n_epochs = int(1e5) with tf.Session() as sess:
sess.run(init) for epoch in range(n_epochs):
if epoch % 1e4 == 0:
print("Epoch", epoch, "Cost =", cost.eval())
print(f'Parameters: {theta_l.eval()}, {theta_h.eval()}, {rho.eval()}, {zeta.eval()}')
sess.run(train_op)
best_theta_l = theta_l.eval()
best_theta_h = theta_h.eval()
best_sigma = 1/math.sqrt(rho.eval())Epoch 0 Cost = 55.26268
Parameters: 0.5, 0.5, 0.009999999776482582, 0.009999999776482582
Epoch 10000 Cost = 6.5892615
Parameters: 0.24855799973011017, 0.6630115509033203, 0.6332486271858215, 1.1534561276317736e-35
Epoch 20000 Cost = 1.39517
Parameters: 0.2485545128583908, 0.6630078554153442, 1.3754394054412842, 1.1534561276317736e-35
Epoch 30000 Cost = 1.3396643
Parameters: 0.24855604767799377, 0.6630094647407532, 1.4745615720748901, 1.1534561276317736e-35
Epoch 40000 Cost = 1.3396641
Parameters: 0.24855272471904755, 0.6630063056945801, 1.4745622873306274, 1.1534561276317736e-35
Epoch 50000 Cost = 1.3396646
Parameters: 0.2485586702823639, 0.6630119681358337, 1.4745632410049438, 1.1534561276317736e-35
Epoch 60000 Cost = 1.3396648
Parameters: 0.2485581487417221, 0.6630115509033203, 1.4745649099349976, 1.1534561276317736e-35
Epoch 70000 Cost = 1.3396643
Parameters: 0.2485586702823639, 0.6630122065544128, 1.4745644330978394, 1.1534561276317736e-35
Epoch 80000 Cost = 1.3396643
Parameters: 0.24855820834636688, 0.6630116701126099, 1.4745631217956543, 1.1534561276317736e-35
Epoch 90000 Cost = 1.3396646
Parameters: 0.248562291264534, 0.663015604019165, 1.474563717842102, 1.1534561276317736e-35
这里有意思的是 ζ 为零。这意味着我们不能相信开发者给我们的不确定性估计。这也意味着我们可以只使用由学习参数 θl 和 θh 指定的平均值周围的对数正态分布。比方说,同一个开发人员估计一项新任务需要 10-15 天。代入我们看到的公式:
mu = best_theta_l*math.log(10)+best_theta_h*math.log(15)
most_likely_prediction = math.exp(mu)
most_likely_prediction10.67385532327305
我们还可以通过将这些值直接代入对数正态分布来获得 95%的置信度:
from scipy.stats import lognorm
distribution = lognorm(s=best_sigma, scale=most_likely_prediction, loc=0)
print(f'95% confidence: {distribution.ppf(0.95)}')95% confidence: 41.3614192940211
如我们所见,如果我们想要 95%的置信度,我们必须给出 41 天的估计,而不是 50%置信度的 11 天。如果你看到开发人员在过去没有很好地完成任务评估,这就很容易解释了。
您可以从 github 访问笔记本。
预测风险投资的前景
介绍
市场将走向何方?资金会放缓还是会激增?哪些行业正在崛起或陷入困境?
生活在旧金山,初创企业会淡出人们的讨论,也会活跃起来,就像它们在新闻和市场上一样。作为湾区的大多数居民,我搬到这里是为了实现梦想,成为硅谷崛起的变革浪潮中的一员。从我早期对创业公司的迷恋,我感到有动力更好地了解创业公司,并从资金开始。
行动纲要
通过使用机器学习,我能够相对自信地预测整个风险资本市场的趋势以及哪些领域最有前途。利用 2013 年的 Crunchbase 数据,我能够预测 2014 年初的资金数额。此外,我预测当时最有希望的行业是生物技术,最差的行业是社会服务。如果给定 Crunchbase 当前的专有数据,我可以很容易地预测 2017 年剩余时间的资金。
数据收集
Crunchbase 保存了关于初创公司的信息,包括这些公司何时得到了资助,由谁资助,属于哪个行业,以及创始人有什么样的公司背景。Crunchbase 始于 2007 年,由用户贡献的内容运营,这些内容在被列入网站之前会经过审查。Crunchbase 以 MySQL 格式免费提供他们的一些数据,提供他们所有的信息,直到 2013 年底。为了获得访问权,一个人必须注册成为研究员。然而,一个人必须注册成为一家企业,并每年支付大约 6000 美元来访问他们当前的数据。因此,我的研究范围将是免费获取的信息,以收集过去的见解,如果有最新的数据,这些见解可以很容易地复制。
数据本身
非常方便的是,我能够在 11 个文件中通过一系列 MySQL 查询轻松地提取和研究数据。在对所有文件进行了大量研究之后,我使用了一些连接来处理一个数据集:funding。有一次,在一个数据帧中,我重新组织了结构,把它放入一个时间序列中。所以我的变量是 2005-2013 年的月度时间序列数据。
Crunchbase began in 2007 and has a significant amount of information for 2005 and onward.
我限制范围的选择是基于观察每年独特投资数量的直方图。值得注意的是,用户可以贡献过去的信息,这个直方图有目的地缩小,因为投资条目可以追溯到 20 世纪 70 年代。
Y Combinator, Techstars and SV Angel are the top three. Andreessen Horowitz rests in the middle with 76 commitments.
SV Angel, First Round Capital and Sequoia Capital. Although not shown, Sequoia Capital leads for the most number of commitments for Series B and in third for Series C.
以上两个图表显示了所有投资者至少有 50 个承诺。顶级投资者因融资阶段而异。Y Combinator 在种子期融资方面领先,而 SV Angel 在首轮融资中排名第一,在种子期融资中排名第三。
型号选择
我想从两个角度来看初创企业的状况。一个视角是观察整个创业市场的表现,另一个视角是进一步观察行业水平。
整体市场(ARMA)
“市场观点”分析了从 2005 年初到 2013 年底每个月的融资总额。由于这是一个简单的时间序列,我认为自回归-移动平均(ARMA)模型将是合适的。ARMA 结合了两个模型,其中每个值都根据其过去的值进行回归,并将以前的误差项作为输入,并根据与以前预测的偏差来预测下一个值。误差项是预测值和实际值之间的差异。ARMA 模型是分析时间序列数据的标准工具。
Total Funding as reported from Crunchbase. The blue line is the monthly raw data in billions of inflation-adjusted USD and the red line shows the market trend (or the annual average).
该图显示了 2009 年前后融资额的下降,这在大萧条时期是有道理的。然后,资金稳步增加,直至 2013 年底。
即使我每个月都有资金,建立 ARMA 模型的第一步是诱导平稳性。将数据转换为平稳时间序列背后的理论是通过与相关时间进行差分来合并数据的内在相关结构。也就是说,一次资金稍微依赖去年,稍微依赖上月。( 2
Each point is the difference while taking into account last month’s change (t-1) and last year’s change (t-12) and last year’s last month change (t-13) for each time (t).
上图是一个平稳的时间序列,能够模拟和预测未来的资金。该序列的平均值非常接近于零,并且大多具有恒定的方差,这是平稳性的两个要求。所示的两次跳跃将限制我的预测的可信度,然而在给定稍微麻烦的数据的情况下,预测仍然是可能的。在我讨论整体市场的结果之前,我们先来关注一下板块层面。
个别部门(LSTM)
Crunchbase 有 42 个预定义的行业标签(如硬件、旅游、体育)。为了保持一致性,我将每个行业放入 2005 年至 2013 年的时间序列中。对于这种类型的数据,我认为长短期记忆(LSTM)递归神经网络(RNN)会工作得很好。LSTM 是专门为长时间“记忆”信息而设计的。一个简单的 RNN 接受一个输入,并通过一组权重(一个层)创建一个输出,同时还通过这些输入进行循环,然后更新权重。除了图层有四个相互关联的更新之外,LSTM 的操作方式与此相同。这四个中最重要的部分是遗忘之门,过去的信息要么被保留,要么被丢弃。另外三个交互创建输入的过滤版本作为输出。( 3 这整个过程是一个历元,其中训练数据在一个迭代周期内更新权重。
Trends of the biotech, the software and the finance industry. The finance sector shows significant increase after the financial crisis signaling increased skepticism of current financial institutions.
2009 年后,软件行业的融资出现下滑,而 2010 年后,金融行业的融资大幅增加。生物技术在这整个时期增长了三倍。对所有这些不同的扇区使用 LSTM 的一个很大的优点是,由于神经网络可以学习数据的潜在依赖性,因此不需要进行差分。
结果
对于整个市场来说,我最好的 ARMA 模型的 R 平方统计值是 0.452。R 平方统计值的范围从 0 到 1,表示模型捕捉到的数据方差。ARMA 模型做了下降的工作,但似乎不能完全解释两个方向的大峰值。它似乎捕捉到了某种形式的跳跃,但在预测上保持保守。
就单个行业而言,我的 LSTM 模型在训练数据和测试数据上的 R 平方值分别为 0.604 和 0.382。训练集由 2005 年到 2012 年组成,测试集是 2013 年的全部。两张图中的蓝线分别是测试集的 R 平方统计值和损失函数值。损失函数应最小化,因为这是预测值和实际值之间偏差的度量。R 平方(r2)图显示了 LSTM 模型如何快速学习,然后在大约 400 个历元处稳定下来,并略有改善。“损失”图显示了训练集和测试集如何收敛。
For both graphs, the x-axis is the number of epochs.
R 平方的红色十字准线显示了我的模型在哪里以及在什么值下性能最好。我可以运行这个模型更多的时期;但是,测试集开始增加其方差,表明模型开始过度拟合训练数据,因此不会很好地推广到预测。
解释
整体市场在 2012 年后稳步增长,我的模型预测这种情况将持续到 2014 年初。根据 Crunchbase 的数据,初创企业已经从 2008 年的金融危机中迅速复苏。
预计数亿美元将流入生物技术、清洁技术、软件、企业、电子商务、移动和医疗部门。生物技术、清洁技术和医疗尤其令人感兴趣,因为它们在这段时间内增长最快。软件、企业、电子商务和移动是资金最多、资金流最可靠的行业。
另一方面,公共关系、非营利、法律、地方和政府部门是最没有前途的部门,预计所有这些部门每月基本上都没有资金。围绕这些部门的共同线索是,它们属于一个更大的社会服务类别。然而,这是否意味着创新在这里是不可能的?我坚信这些行业不需要更多的创新;然而,这些行业的盈利能力可能很低。
结论
2012 年后,随着资金的稳定流入,市场保持了增长。在此期间,生物技术部门成为最有前途的部门,而社会服务部门缺乏创新的代表性。
接下来,我打算将我的关注点进一步缩小到个别公司及其投资者,以更好地理解创业精神,并衡量某些投资者是否对结果有重大影响。最重要的是,我计划体验一下企业家的生活,了解市场动向对一个人的公司有重大价值。
用机器学习预测 NCAA 锦标赛的冷门
更新:看看这个的后续,我在这里讨论了 3 个额外的不安信号。
疯狂即将来临!一年一度的男子大学篮球锦标赛将于 3 月 15 日开始,很快数百万球迷将填写他们的括号。
对我们大多数人来说,冷门是锦标赛中最精彩的部分。在体育运动中,很少有球迷的经历能比得上看到实时爆冷的兴奋感,以及处于劣势的球队赢得胜利时的纯粹喜悦:
唯一比看着疯狂的冷门下跌更好的事情是把冷门选秀权钉在你的支架上。说起来容易做起来难:在最近的一次全国在线括号比赛中,平均只有 19%的括号选择了不满意。冷门还会让一些种子选手提前回家。例证:2016 年 62%的 ESPN 挑战赛排名密歇根州立大学进入了四强,斯巴达队获得了第二多的冠军。但疯狂随之而来:汤姆伊佐的球队在第一轮就被拥有 15 个种子的田纳西中部州立大学淘汰了。
正确挑选冷门可以区分你的括号,给你一个竞争优势。我试图通过使用数据和机器学习来预测 NCAA 锦标赛中的冷门,从而战胜困难。
使用团队种子定义意外事件
每年,64 个符合条件的团队被分成四组,每组 16 个(“地区”),每个团队都被分配一个“种子”,排名从 1(最好)到 16(最差),就像 2016 年的中西部地区一样。一个队在几乎每场比赛中都有技术优势,但人们不会对 9 号种子击败 8 号种子,甚至 10 号种子击败 7 号种子感到震惊。这些比赛基本上都是“胜负难分”的。我对预测更令人震惊和意想不到的沮丧感兴趣。
我把一场失利定义为一个比对手低至少 4 位的种子队的胜利,比如 1 号种子输给 5 号种子或更低,2 号种子输给 6 号种子或更低,等等。因为锦标赛每年都使用相同的结构,所以种子赛是一种快速、简单的方法来识别和研究冷门。
数据准备和探索
数据
我获得了自 2003 年以来每支锦标赛球队在常规赛和锦标赛中球队和球员表现的数据。该数据包括 584 场有“潜在冷门”的锦标赛,这意味着这些球队的种子差距至少为 4。
特征工程
我为每个团队创建了一个包含 82 个特征的数据集,包括整个赛季的团队表现、团队效率指标、教练比武经验/成功以及团队旅行。因为目标是预测,所有特征都是在每场锦标赛游戏的之前可用的特征。然后,我做了一些数据探索,以确定可能预测冷门的趋势。
冷门和种子比赛
下面的图表显示了每年的冷门次数,以及每年的平均值。不要疯狂地挑太多的冷门;平均每年只有 9 起。
On average only 9 upsets occur in each tournament
哪些比赛最有可能导致冷门?事实证明,在第 1 轮和第 2 轮中出现的 14 个常见种子配对占所有“潜在冷门”游戏的 85%。下面显示了这些比赛,以及它们的“冷门率”(导致冷门的比赛比例)的热图。
Heat map of upset rates for the most common seed pairings
该图基于种子匹配确定了一些好的不规则候选:
- 在第一轮中,关注 12 对 5 和 11 对 6。12 号种子选手和 11 号种子选手赢得这些比赛的几率约为 40%。
- 如果你觉得大胆,在第一轮中拿一个 13 号种子胜过一个 4 号种子。13 号种子队赢得了 20%的比赛。
- 2 粒种子很少在第一轮中失败(7%),但在第二轮中,他们令人惊讶地容易被 7 粒种子(33%)和 10 粒种子(37%)打乱。
- 这些 10 粒种子和 7 粒种子比 8 粒种子和 9 粒种子更适合 16 粒种子,后者很少在第二轮中击败 1 粒种子(12-13%)。
- 考虑在甜蜜的 16 强中放一个 11 号种子:在第二轮中,11 号种子赢得了三分之一的比赛。
发现灰姑娘和后进生
除了种子赛,赢的失败者和输的热门有什么特征?
团队效率边际
从肯·波默罗伊优秀的高级篮球分析网站,一个球队的调整后的效率边际是一个单一的数字,它表明了比赛的整体实力。本质上,它代表了在给定 100 分的情况下,一个球队相对于一个普通对手的预期胜率。下面我画出了我的数据集中每场比赛的失败者和最受欢迎者的效率边际,数据点显示了比赛是否导致了冷门。
Upsets involve underdogs with higher efficiency and favorites with lower efficiency
大多数冷门都发生在差幅超过 10 的劣势方对差幅低于 25 的热门方的时候。事实上,符合这些标准的游戏有 35%的时间会导致不愉快,而不符合这些标准的游戏只有 13%。作为挑选冷门的简单经验法则,你当然可以做得更糟!
赚取额外的财富——篮板和失误
在篮球比赛中,球队在投篮不中或得分后交换控球权,但球队也可以通过反弹自己的失误(产生额外的投篮机会)和迫使失误(夺走对手的机会)来获得“额外”的控球权。为了计算“进攻篮板和失误率”,我计算了整个赛季中每支球队平均每场比赛的进攻篮板和失误优势。
Winning underdogs have better offensive rebounding and turnover margins
在左边,我显示了在非冷门(左)和冷门(右)比赛中的冷门选手和热门选手的平均差距。
在没有冷门的情况下,热门比冷门有更高的利润,但是在冷门的情况下,情况正好相反。如果处于劣势的一方比他们的对手更擅长获得进攻篮板和失误,那么这场比赛就是一场逆转。
用于镦粗预测的机器学习
与其逐个检查 82 个特征,不如让算法发挥作用。我将游戏分成训练集(80%)和测试集(20%),并训练每个算法进行预测。
训练分类算法
我将冷门预测作为一个分类问题,目标是将每场比赛归类为“冷门”与否。我选择了 5 种分类算法进行训练:
- 逻辑回归
- 神经网络
- 支持向量机
- 随机森林
- 梯度树提升分类器
使用 python 的 scikit-learn 包,我使每个算法适合训练数据,并使用 5 重交叉验证来调整模型超参数(影响模型拟合的设置)。为了确定每个算法的最佳设置,我使用了交叉验证 F1 分数。这里, F1 分数是扰乱精度(最小化不正确的扰乱预测)和召回(预测大多数实际扰乱)的平衡。关于 F1 的更多信息,请参见此处。
我也应该承认冷门在这些数据中是“不平衡”的,只有 22%的游戏是冷门。这些算法通常最适用于接近对半分割的示例。不涉及太多细节,我会注意到训练数据被重采样以在扰乱和非扰乱之间创建平衡(在这里阅读关于不平衡数据和重采样的更多信息)。
测试模型性能
对于每种算法,在保留的测试集上评估来自训练的最佳模型。5 个模型的 ROC 曲线如下所示:
该图显示,对于每个分类器,随着真阳性率的增加,假阳性率也增加。大多数分类问题都是如此;随着更多的真实情况被预测,更多的虚假情况也被预测。我还注意到,这些算法在 ROC 曲线的不同点上最大化了真正的阳性率,因此将它们组合在一起可能会产生更好的结果。
“未来”对决分类
为了评估一个更“真实世界的场景”,我想预测单个锦标赛的冷门。我使用逻辑回归模型预测了 2017 年的 42 场潜在冷门比赛,这些比赛是我在之前的训练和测试中推出的。
Matrix showing prediction results for 2017
该矩阵将预测细分为正确的非镦粗(左上)、正确的镦粗预测(右下)、不正确的非镦粗预测(左下)和不正确的镦粗预测(右上)。
该模型预测了 2017 年的 15 次颠覆。在 2017 年的 10 次实际冷门中,有 8 次被模型识别出来,但模型也做出了 7 次“假阳性”的冷门预测。该模型在预测冷门时有点过于激进,但对于这些难以预测的游戏来说,它仍然是正确的。
更仔细地观察预测,可以更深入地了解模型在哪些方面表现良好,以及在哪些方面需要改进:
Upset predictions are most accurate for Round 1
模型真的很擅长预测第一轮,23/24 场比赛预测正确。对于所有其他回合,该模型去 10/18。我希望模型在整个比赛中更加精确,但第一轮也是最令人失望的时候。大多数括号池玩家可以通过在第一轮中采取模型预测的冷门来获得优势。我还计算出,在这些令人沮丧的预测上下注,将获得 21%的净回报。
结论
我有几个改进模型预测的想法,包括添加更多的数据来创建更多的特征,对团队最近的表现进行加权,以及尝试其他算法或算法组合。我还想尝试对比赛分数而不是最终结果进行建模,并研究其他 NCAA 锦标赛预测问题,如识别被高估的球队提前回家的特征,以及“灰姑娘”失败者准备深入锦标赛的特征。
我将在 Twitter 上宣布未来的工作,所以如果你喜欢,请给我一个关注!
预测维基百科的网络流量
现场 Kaggle 比赛
这是我在 Kaggle 上参加 WTF 比赛的文档,这是网络流量预测的简称!一个月不稳定的管道建设,一些令人沮丧的周末,40 次提交和 22 次提交后,我仍然没有达到我的期望。虽然学到了很多,但这份报告是试图组织学习。
也就是说,一个警告——这个博客会稍微有点技术性:)
这是一场现场比赛,由 Kaggle 主办,由 Google 发布 145K 维基百科页面的网络流量将在 2017 年 9 月至 11 月期间进行预测,这意味着,我们提交的准确性将实时计算——取决于未来如何发展!训练数据由过去两年中维基页面上每天的查看次数组成。
听起来像一个非常标准的时间序列问题,对吗?大错特错。
我的方法——Github
在我的脑海中有一个面向 xgboost 的策略并不总是很好,这个竞争让我离开了我的舒适区!很自然地,我查阅了关于 ARIMA 模型表现的讨论/内核——显然,自回归模型不能很好地推广到目标变量的未知范围(这是我们问题中非常可能出现的情况)。
一对夫妇的方法脱颖而出:
- 将时间序列问题建模为回归问题,每个页面-日期对被视为一行。
- 使用脸书的预言家,他们的新预测工具。
在一些顶级 kagglers 的建议下,我决定采用回归模型——将基于时间序列的数据框架融合到传统的每行页面日期特征数据框架中。运行 xgb,并在类似熔化的测试数据帧上进行预测。
特征工程
总体平均值/中值 —一个简单的常量提交,包含过去 8 周的平均值/中值,在第一阶段很难被超越。包括在内。
滚动方式和滚动中间值——这些是我想到的一些最明显的特性,然而它们实现起来并不简单。我同意,在预测今天的流量时,过去 7 天的滚动平均值将是一个重要的特征,但挑战是要求我们预测未来三个月的流量数据。
当当前日期是 9 月 14 日时,如何找到 11 月 1 日的周滚动平均值?
因此,像滚动平均这样的功能在验证中表现非常好,但在公共排行榜上却不是这样。最后,我继续使用过去 30 天和 60 天的滚动平均值和中间值。对于我无法计算这些特征的日期,我继续使用时间序列中最后一个可用的计算特征的代理。
后来,我包括了更多的功能,如滚动标准开发,滚动最小/最大等。
基于工作日的平均值/中值 —这些特性被证明是最重要的特性之一!很明显,很多维基百科的点击是工作日/周末相关的——我试图通过过去六个月的工作日累计平均值和中值来捕捉这一点。
语言和来源——我试图整合来自页面语言或来源(爬虫、蜘蛛等)的统计数据,但这些并没有让我在一个普通的 xgboost 上得到提升。为了简单起见,把它们去掉了。
最后一天的访问——像最后一天的访问这样的特性在进行验证运行时非常有用。测试数据并非如此,因为竞争是实时的。我必须提交对未来两个月所有页面的预测——显然,使用最后一天的访问量是愚蠢的!
流水线作业
构建一个抽象的模块化管道占用了我大部分的带宽!我必须将宽格式的数据帧转换成长格式的数据帧,并对每个页面-日期对进行滚动统计。计算每个滚动统计的函数有可选参数,如“last _ n _ days”——30 天的滚动平均值,以及“rows _ to _ consider”——我们希望返回多少个日期。
在大量阅读内核和论坛之后,我坚持许多顶级 kagglers 的策略:
- 在所有页面上训练一个 Xgboost 模型。这将帮助我们确定整个维基百科的总体趋势。
- 在网页的所有未来日期上测试模型。
另一种方法是在每个页面上单独训练一个 xgboost,使算法个性化。这非常耗时,并且可能无法很好地推广。
型号
XGBoost 是爱,XGBoost 是命!
我继续与香草 xgb,再一次。首先,xgboost 在几个月的讨论中得到了很好的反馈。这是我第一次使用自定义损失函数( SMAPE )作为 xgboost 参数(feval),这是一个有争议的损失函数选择——不可微且不对称!
我面临的一个主要问题是,基于树的模型不能很好地推广到未知的范围,在我添加更多功能之前,与 xgboost 的常量预测斗争了一段时间!解决这个问题的方法是将目标变量的差异视为目标变量,从而限制范围。这需要以类似的方式改变特性,我没有走这条路。
挑战&失误
- XGBoost 不能很好地推广到未知范围,如前所述。
- 由于我将数据帧分解为长格式,如果我只考虑最近六个月的数据,那么行数达到了 2600 万!这是其中的一个权衡,放弃旧数据而不是 RAM 限制。
- 正如我前面提到的,在测试数据集中计算未来几天的滚动统计是不可能的。我试着把它们设为 NA,但这大大夸大了预测(因为模型在训练中没有看到 NA)。最后,我坚持向前填充滚动统计数据。
- 建了一个复杂的管道,调试简直是一场噩梦!我还是想不出更简单的方法,权衡:)
- 我的 noob 错误——将数据帧的浅层副本视为深层副本。我怎么也想不出这个 bug!
学习成果&结论
我从这次比赛中得到的主要收获是:
- 花更多的时间在 kaggle 讨论上,并且经常参与。这将建立一个循环——工作、讨论。讨论,工作。
- 应该从一开始就抽象我的功能。重构一点都不好玩!
- 我想我已经刷爆了我的功能,现在要看看别人提交的内容了!
- 既然我擅长流水线和特性工程,我应该更加关注模型调优和集成。
- 不要害怕时间序列问题。在一天结束时,它的好 ol '回归!
总的来说,这是一场有趣的比赛——现在想起来,可能更令人沮丧而不是有趣!学到了很多,对我将来的比赛很有帮助。
到下一个:)
这篇文章最初发表在我的 博客 上。每周一篇博客
预测工程:如何设置你的机器学习问题
用机器学习解决问题的第一步的解释和实现
这是关于我们如何在功能实验室进行机器学习的四部分系列中的第二部分。这套物品是:
这些文章将涵盖应用于预测客户流失的概念和完整实现。project Jupyter 笔记本在 GitHub 上都有。(完全披露:我在 Feature Labs 工作,这是一家初创公司开发工具,包括 Featuretools ,用于解决机器学习的问题。这里记录的所有工作都是用开源工具和数据完成的。)
预测工程概念
当在机器学习任务中使用真实世界的数据时,*我们定义问题,这意味着我们必须开发自己的标签——*我们想要预测的历史示例——来训练监督模型。制作我们自己的标签的想法最初可能对数据科学家(包括我自己)来说是陌生的,他们从 Kaggle 竞赛或教科书数据集开始,其中已经包含了答案。
预测工程背后的概念——制作标签来训练有监督的机器学习模型——并不新鲜。然而,它目前还不是一个标准化的流程,而是由数据科学家在按需完成。这意味着,对于每一个新问题,即使是相同的数据集,也必须开发一个新的脚本来完成这项任务,导致解决方案无法适应不同的预测问题。
更好的解决方案是编写能够灵活改变业务参数的函数,允许我们为许多问题快速生成标签。这是数据科学可以从软件工程中学到的一个领域:解决方案应该是可重用的,并接受不断变化的输入。在本文中,我们将看到如何实现一种可重用的方法来解决机器学习问题的第一步——预测工程。
预测工程的过程
预测工程既需要从业务的角度得到指导,以找出要解决的正确问题,也需要从数据科学家的角度得到指导,以确定如何将业务需求转化为机器学习问题。预测工程的输入是定义业务需求预测问题的参数,以及寻找我们想要预测的例子的历史数据集。
Process of prediction engineering.
预测工程的输出是一个标签时间表:一组标签,其中包含从过去数据中获得的负面和正面示例,以及相关的截止时间,指示我们何时必须停止使用数据来为该标签创建特征(稍后将详细介绍)。
对于我们将在本系列中完成的用例——客户流失——我们将业务问题定义为通过降低流失率来增加每月活跃用户。机器学习问题是建立一个模型,利用历史数据预测哪些客户会流失。这项任务的第一步是制作一组过去客户流失案例的标签。
构成客户流失的参数以及我们希望进行预测的频率将根据业务需求而有所不同,但在本例中,假设我们希望在每个月的第一天进行预测,客户将在预测后的一个月内流失。流失将被定义为超过 31 天没有活跃会员。
重要的是要记住,这只是与一个业务问题相对应的客户流失的一种定义。当我们编写函数来制作标签时,它们应该接受参数,这样它们就可以快速地改变为不同的预测问题。
我们预测工程的目标是如下的标签时间表:
Example of label times table
根据历史数据,这些标签对应于客户是否有过交易。每个客户都被多次用作训练示例,因为他们有几个月的数据。即使我们没有多次使用客户,因为这是一个与时间相关的问题,我们也要正确地实现截止时间的概念。
截止时间:如何确保要素有效
没有截止时间标签就不完整,截止时间代表当我们不得不停止使用数据为标签制作特征时。因为我们在每个月的第一天预测客户流失,我们不能使用第一个之后的任何数据来制作那个标签的特征。因此,我们的截止时间都在每月的第一天,如上面的标签时间表所示。
每个标签的所有特征必须使用该时间之前的数据,以防止数据泄露的问题。截止时间是对时间序列问题建立成功解决方案的关键部分,许多公司没有考虑到这一点。使用无效数据来制作特性会导致模型在开发中表现良好,但在部署中失败。
想象一下,我们没有将我们的特征限制在每个标签的月 1 日之前发生的数据上。我们的模型会计算出在该月有付费交易的客户不可能在该月有交易,因此会记录较高的指标。然而,当需要部署模型并对未来一个月进行预测时,我们无法访问未来的交易,我们的模型将表现不佳。这就像一个学生在家庭作业上做得很好,因为她有答案,但在考试中却没有相同的信息。
客户流失数据集
现在我们有了概念,让我们来研究一下细节。 KKBOX 是亚洲领先的音乐流媒体服务,为超过 1000 万会员提供免费和按月付费的订阅选项。KKBOX 提供了一个数据集用于预测客户流失。有 3 个略超过 30 GB 的数据表,由下面的模式表示:
Relational diagram of data.
这三个表格包括:
- 客户:背景信息,如年龄和城市(msno 是客户 id):
- 交易:每个客户每次付款的交易数据:
- 活动日志:客户倾听行为的日志:
这是订阅业务的典型数据集,是结构化关系数据的一个示例:行中的观察值、列中的特性以及通过主键和外键连接在一起的表:客户 id。
查找历史标签
使预测工程适应不同问题的关键是遵循从数据集中提取训练标签的可重复过程。概括来说,这一点概括如下:
- 根据关键业务参数定义正面和负面标签
- 搜索过去的数据,寻找正面和负面的例子
- 制作一个截止时间表,并将每个截止时间与一个标签相关联
对于客户流失,参数是
- 预测日期(截止时间):我们做出预测的时间点,也是我们停止使用数据为标签制作特征的时间点
- 用户被视为流失前没有订阅的天数
- 提前期:我们希望预测的未来天数或月数
- 预测窗口:我们想要预测的时间段
下图显示了每一个概念,同时用我们将要研究的问题定义来填充细节。
Parameters defining the customer churn prediction problem.
在这种情况下,客户在一月份已经有 30 多天没有订阅了。因为我们的提前期是一个月,预测窗口也是一个月,所以流失的标签与 12 月 1 日的截止时间相关联。对于这个问题,我们因此教导我们的模型提前一个月预测客户流失*,以给客户满意度团队足够的时间与客户接触。*
对于一个给定的数据集,我们可以从中做出无数的预测问题。我们可能希望预测不同日期或频率的流失,例如每两周一次,提前两个月,或者将流失定义为没有活动成员的较短持续时间。此外,我们可以用这个数据集解决其他与流失无关的问题:预测客户下个月会听多少首歌;预测客户群的增长率;或者,根据聆听习惯将客户划分为不同的群体,以定制更加个性化的体验。
当我们开发用于创建标签的函数时,我们将输入作为参数,这样我们就可以从数据集中快速生成多组标签。
如果我们开发一个拥有参数而不是硬编码值的管道,我们可以很快地采用它来解决不同的问题。当我们想要改变客户流失的定义时,我们需要做的就是改变管道的参数输入并重新运行它。
标签实施
为了制作标签,我们开发了 2 个功能(全部代码在笔记本中):
label_customer(customer_transactions, prediction_date = "first of month", days_to_churn = 31, lead_time = "1 month", prediction_window = "1 month") make_labels(all_transactions, prediction_date = "first of month", days_to_churn = 31, lead_time = "1 month", prediction_window = "1 month")
label_customer
函数接收客户的交易和指定的参数,并返回一个标签时间表。该表包含一组预测时间(截止时间)和对应于单个客户的每个截止时间的预测窗口中的标签。
例如,我们的客户标签如下所示:
Label times for one customer.
然后,make_labels
函数接收所有客户的交易和参数,并返回一个表,其中包含每个客户的截止时间和标签。
后续步骤
当正确实现时,预测工程的最终结果是一个可以通过改变输入参数为多个预测问题创建标签时间的函数。这些标注时间(截止时间和关联标注)是下一阶段的输入,在该阶段中,我们为每个标注创建要素。本系列的下一篇文章描述了特征工程如何工作。
结论
我们还没有发明预测工程的过程,只是给它起了个名字,并为管道中的第一部分定义了一个可重用的方法。
预测工程的过程分为三个步骤:
- 确定可以用可用数据解决的业务需求
- 将业务需求转化为有监督的机器学习问题
- 根据历史数据创建标注时间
获得正确的预测工程至关重要,需要业务和数据科学两方面的投入。通过编写预测工程的代码来接受不同的参数,如果我们公司的需求发生变化,我们可以快速地改变预测问题。
更一般地说,我们解决机器学习问题的方法在标准化每个输入和输出的同时,将流水线的不同部分分段。正如我们将看到的,最终结果是我们可以在预测工程阶段快速改变预测问题,而不需要重写后续步骤。在本文中,我们已经开发了一个框架的第一步,该框架可用于解决机器学习的许多问题。
如果构建有意义的、高性能的预测模型是你所关心的事情,那么请通过功能实验室与我们联系。虽然这个项目是用开源的 Featuretools 完成的,但商业产品为创建机器学习解决方案提供了额外的工具和支持。
自动驾驶汽车中的预测——你需要知道的一切
想象一个场景,你在一条双车道的路上驾驶一辆车,向前行驶,你想右转,但是第二车道上有一辆车从相反的方向驶来,现在你会怎么做?
自动驾驶汽车的预测是关于我们的自动驾驶汽车如何预测另一辆汽车的轨迹或路径,并采取行动避免碰撞。
我是 Udacity 自动驾驶汽车纳米学位项目的第三期学生,在这里我将分享我在预测方面的知识,这是自动驾驶汽车轨迹规划的一个重要部分。
这是怎么做到的?
预测的输入来自传感器融合和定位。传感器融合就是结合来自多个传感器(如雷达、激光雷达等)的数据(使用卡尔曼滤波器)。)让我们的汽车了解它的环境,而汽车使用定位来精确地知道它在哪里。
一旦我们有了输入,就可以通过以下方法来预测车辆的轨迹:
1.基于模型的方法
2.数据驱动方法
这些方法可以单独使用,也可以混合使用,以做出更好的预测。
让我们一次看一种方法
1。基于模型的方法:
这种方法识别车辆的常见行为(变道、左转、右转、确定最大转弯速度等。) .
在这种方法中,我们为车辆可能行驶的每个可能轨迹创建一个模型,并将其与汽车的行为一起发送给多模态估计算法 (现在假设它是一个黑盒)。该算法将概率分配给轨迹模型,最终选择概率最高的模型。
Modal Based Approach
在我们深入研究基于模型的方法之前,让我们先来看看 Frenet 坐标系。
弗雷诺坐标系
在 FCS 中,我们使用s’和d’符号来确定物体的位置,其中s’是道路上的距离,而 d 确定距离车道中心的距离,这与我们使用 x,y 坐标来表示道路上的位置的笛卡尔坐标系不同。FCS 是表示道路上物体位置的更好的方法,因为使用笛卡尔坐标实现曲线道路的方程会困难得多。
基于模型的方法中使用的步骤:
Steps used in Model Based Approach
*第一步:*确定汽车的共同行为
步骤 2: 为每个被识别的行为创建过程模型
*第三步:*计算每个过程模型的概率
让我们通过一个简单的例子来理解每个步骤:
Image Source: Udacity Nano Degree Program
假设我们的自动驾驶汽车(绿色汽车)必须在高速公路上行驶。为此,它必须预测蓝色汽车的行为。
第一步:
蓝色汽车的行为如下:
- 它会忽略我们
- 它会减速,让我们的车先行,这是一个礼貌的司机
- 它会加速并超过我们的车
- 它会变道并以同样的速度继续行驶
等等…
我们必须用数学描述来描述这些行为。为此,我们将转到步骤 2。
第二步:
过程模型为确定的行为提供了数学描述。
这些模型的复杂程度可以从非常简单的数学描述到非常复杂的数学描述不等
- 请注意,流程模型数量取决于所识别行为的数量。它可能随着行为的数量而变化。
预测状态 x 在时间 k 的过程模型的一般状态形式如下:
state vector
第三步:
在这一步中,我们将通过为每个行为创建的流程模型分配概率,来确定汽车中的驾驶员将执行什么操作。这是通过多模态估计算法完成的。该算法最简单的方法是自主多模态(AMM)算法。
自主多模态(AMM)算法。
在 AMM,我们首先观察车辆在时间 k-1 和时间 k 的状态
然后,我们计算 k-1 时刻的流程模型,并得到 k 时刻的预期状态。
然后将比较期望状态和观察状态的可能性。并使用以下公式获得模型在时间 k 的概率:
模型(I)在时间 k 的概率
其中:
M: 多个不同的流程模型
U: 模型的概率。
L: 模型的观测的可能性
k: 时间戳
最后选择概率最高的模型。
2。数据驱动方法
在数据驱动方法中,我们将采用一个黑盒,并使用大量训练数据对其进行训练。一旦它得到训练,我们将符合观察到的行为,并得到预测。
这有助于确定车辆的具体模式,否则可能会被遗漏。
数据驱动方法分两个阶段完成:
- 离线培训(模型培训)
- 在线预测(使用模型预测轨迹)
Data Based Approach
离线培训
数据驱动方法中使用的步骤:
*第一步:*获取大量轨迹数据
*第二步:*清除数据
步骤 3: 选择一个度量来执行相似性
步骤 4: 使用机器学习算法执行轨迹的无监督聚类,如谱聚类或凝聚聚类
步骤 5 :为每个集群定义一个轨迹模式
按照这些步骤,我们将得到模式和轨迹群
在线预测
步骤 1: 观察车辆局部轨迹
第二步:将它与原型轨迹进行比较
*第三步:*预测轨迹
重复在线预测步骤,直到我们找到原型轨迹之一与车辆轨迹相似的最大可能性。
所以到现在为止,你们一定对预测轨迹的两种不同方法有很好的理解。
混合方法
所以现在的问题是使用哪种方法…?
为什么不利用这两种方法的优点呢?这就是混合方法发挥作用的地方。😃
Hybrid Approach
为了实现混合方法,我们将用机器学习代替基于运动的方法的多重运动估计器。为此,我们需要一个分类器。一个这样的分类器是朴素贝叶斯分类器
朴素贝叶斯分类器:
处理连续数据时的一个典型假设是,与每个类相关联的连续值按照高斯分布分布。
例如,假设训练数据包含一个连续属性 x。我们首先按类对该数据进行分段,然后计算每个类的平均值和标准偏差。假设我们有类的第 k 段,即 x 的 C_k,u_k 是平均值,_ square _ k 是标准偏差,那么给定一个类 C_k,v 的概率分布可以通过将 v 代入方程来计算
这就是我们需要知道的关于我们的自动驾驶车辆如何预测其他车辆的轨迹。请记住,在这篇博客中,我们已经通过一次一个对象的方式介绍了预测,而在现实世界的场景中,可能会有许多对象必须同时进行预测,这使得预测过程更加复杂。幸运的是,我们到目前为止所学的知识可以很好地预测公路上车辆的轨迹。
你可以通过阅读这篇关于 T2 多模型算法的论文来了解更多关于预测的知识,作者是 T4 的瑞安·r·皮特里·维斯林·p·吉尔科夫·x·李蓉。
如有任何疑问,请通过 LinkedIn联系我或写下私人笔记。
预测分析、区块链、大数据人工智能和机器学习是塑造新商业世界的技术。
世界开展业务的方式正在快速变化,世界已经从传统的广告、营销和销售时代跃升到几乎每个数字数据都具有强大媒体元素的时代,包括枯燥的办公生产力工具。今天最重要的成分是数据,而在谁控制了世界上大多数数据的竞赛中,GAFAs(谷歌、亚马逊、脸书和苹果)及其同类似乎已经获胜。与此同时,关于谁将最大限度地利用世界以惊人的速度产生的庞大数据,仍存在一场巨大的权力斗争。在目前的情况下,比拥有这些数据更重要的是能够释放这些数据的潜力。实时数据分析甚至可以预测未来的结果和趋势,即使只有几分钟的时间,也可能是一个与众不同的因素,这是大多数企业正在运营和将要运营的方式。
目前,不同类型的企业使用预测分析,如金融服务,这是他们的主要生命力。电子商务商店和在线视频流媒体服务等其他业务已经享受到了预测分析的甜蜜力量。
预测分析是一种现代营销工具。如果不能从大量数据中翻译出重要的意义,预测就会变得困难。
有趣的是,许多软件公司开始想出有趣的方法来让这些技术变得有趣,让它们变得非常互动和用户友好,这正在改变我们销售、做生意甚至塑造品牌的方式。
大数据技术是与拥有无限数据集和信息的大多数企业相关的新现象。数据可以很容易地生成,当事情进展顺利时,它们可以以量子速率增长,如果组织不当,很快就会变得一团糟。然而,由于数据增长,有趣而美丽的解决方案不断涌现,迫使科学家们提出更出色的算法;企业家更具突破性的解决方案。随着数据创建和消费的增长,这只能表明未来会有更多的数据演变。
区块链是支撑比特币的底层技术。最近,它已经分别成为网络安全、IOT、数字总账和其他数据技术的前沿。大量的研究和投资投入到区块链技术的发展中,因为它提供了巨大的潜力和无数的应用。好消息是,区块链距离成为大规模营销工具还有几年时间。许多人也认为区块链是自互联网发明以来最重要的技术突破,在未来几年,它将成为许多企业的重要组成部分。
人工智能和机器学习听起来相当超前和怪异,但它是所有看到机器人如何以病毒方式接管网络空间的人中最友好的。这项技术的威力毋庸置疑。人工智能正在获得实际应用,并变得与日常生活活动密不可分,在银行、卫生、交通国防等几乎所有部门都有关联。随着各种各样几乎无穷无尽的人工智能应用的出现,我们无疑正处于自动化世界的黎明。
因此,无论是区块链、大数据、预测分析、人工智能还是机器学习,这些技术都有如此多的共同点,因为它们都依赖于其他技术来获得有效的解决方案。对于大多数人来说,当你听到这些术语时,脑海中浮现的是机器人或先进技术,“是的,它们非常先进”,但应该浮现的是这项技术在所有商业领域的变革力量,如营销、销售、客户服务、增长黑客等。鉴于人工智能对人类的明显好处,我们必须考虑人工智能的任何解决方案。从最近的趋势来看,很容易理解为什么人类会因为方便而更多地与采用 AI 解决方案的企业互动。
商业竞争越来越激烈,技术含量越来越高,因此新一代的销售人员能够借助技术进行有效的销售。
对未来的模糊看法胜过完全的黑暗。既然几乎所有的电子设备都变得智能了,为什么企业不能呢?我对智能企业的定义是能够提供智能服务,这可以转化为指数增长。
营销预测分析:它能做什么,为什么你应该使用它
Photo by Jamie Templeton on Unsplash
预测智能并不新鲜。事实上,几年来,企业已经使用先进的分析工具来检测欺诈、评估风险,甚至预测飞机的维护需求,以减少航班延误。
然而,理解预测分析的结果并将数据转化为洞察力并不总是容易的,通常需要高级技能。由于有限的计算能力和难以访问的复杂软件,预测技术从未成为主流营销策略。
直到现在。
今天,人工智能驱动的(AI 驱动的)营销工具——聊天机器人、内容策展人、动态定价模型等。—易于访问且价格合理,为更多企业创造了从世界一流的分析中获益的机会,即使是在预算有限的情况下。
强大、先进、预测性的分析是“时尚”,精明的营销人员不仅回顾数字,还展望未来。让我们探讨一下营销预测分析——它是什么,它能做什么,以及为什么您应该使用它。
什么是营销预测分析?
根据 SAS 的说法,预测分析是“基于历史数据,使用数据、统计算法和机器学习技术来识别未来结果的可能性。我们的目标是超越对已经发生的事情的了解,提供对未来将会发生的事情的最佳评估。”
Salesforce 解释了营销联系:“预测营销使用数据科学来准确预测哪些营销行动和策略最有可能成功。简而言之,预测智能推动营销决策。”
听起来不错。那么,预测分析如何为您的营销决策增加更多洞察力和清晰度呢?
大数据分析如何帮助企业实现价值?
着眼于未来的企业意识到,他们想知道的不仅仅是过去发生的事情;他们想用他们的数据来预测未来。预测分析通过帮助您更好地了解关系以做出更明智的决策,使您已经拥有的当前和历史数据更有价值。
如今,“91%的顶级营销人员要么完全致力于,要么已经在实施预测营销。”这是他们正在做的。
他们更准确地预测客户行为。 对于营销人员来说,客户情报就是游戏的名字。你越了解你的客户——他们想要什么,他们什么时候想要,如何想要——就越容易在正确的时间通过正确的渠道向他们传达正确的信息。
使用由机器学习和人工智能指导的预测技术,预测建模通过识别数据中变量之间的模式和相似性来帮助评估未来的客户行为。例如,回归分析确定客户过去购买行为之间的相关性,以确定未来购买的可能性。
预测模型还可以帮助你根除有可能失去的不满意客户,以及识别可能准备购买的兴奋客户。通过预测模型运行客户数据可以帮助您更好地预测行为,从而更好地制定营销策略。
他们正在识别并优先考虑合格的销售线索。 不合格的潜在客户——那些没有购买意愿的客户——最终会耗费公司的时间和金钱。借助预测分析,一种算法可以根据已知潜在客户和客户采取行动的可能性对其进行优先排序,从而帮助确定潜在客户。识别模型发现与现有买家有相似之处的潜在客户,最大化新销售的机会。
更好的是,来自预测分析的见解可以帮助您的销售团队专注于培养您最有利可图的客户。找到最有潜力的潜在客户,你就能给你的销售团队提供有价值的见解,让他们知道下一个该和谁谈,哪些潜在客户最有可能达成交易。
如果您的企业资金有限,预测分析是一个强大的工具,有助于确保在正确的时间使用正确的资源,同时预测最有可能购买的高价值客户,以优化营销支出。
他们正在钉个性化的消息。 个性化事项。然而,当涉及到为客户提供定制信息时,品牌却举步维艰。要么他们没有准确的数据,要么他们没有足够的数据,要么他们就是不能足够快地获得洞察力。
对其他人来说,个性化做得好的回报是超出预期的非凡客户体验。然而,个性化的手动方法是不可持续的,企业正在转向机器学习和预测技术作为下一个逻辑步骤。
预测分析推动个性化信息的自动细分,这意味着您可以在追加销售、交叉销售或推荐产品时更好地瞄准特定群体或个人,以独特的实时共鸣信息接触客户。
为什么预测分析对您很重要?
今天,数据是新的石油,企业正在“在存储和基础设施上的支出估计为 360 亿美元”——这一数字预计到 2020 年将翻一番。随着更多的数据、改进的计算能力和对供应商工具的轻松访问,用于营销的预测分析不仅是智能的,而且是业务的必要条件!
预测模型可以根据过去的营销活动预测营销绩效,发现改进的机会,以便您可以更好地了解客户的行为,提供更有意义的内容,并创建令人惊叹的定制体验。
好消息是什么?部署预测分析解决方案既不复杂,也不需要单独在内部完成。事实上,无论是大公司还是小公司,都有大量令人惊叹的解决方案可供选择——甚至对于在分析方面缺乏成熟度的企业也是如此。
Blue Fountain Media 的业务开发副总裁 Brian Byer 有一些的至理名言要与大家分享:“使用正确的工具,使您能够利用数据……比试图将解决方案逆向工程到传统技术堆栈中要容易得多。计划取得成功,这将使整合预测分析和其他新技术变得更加容易。”
总之
随着技术格局的快速变化,成功的公司将使他们的团队能够使用技术优先的解决方案来更好地服务于他们的客户。他们将采用新工具,在采用新技术时避免分析瘫痪,并将变化作为新的机遇进行规划。敏捷商业方法着眼于未来,是 2019 年及以后取得成功的必备条件。
准确而及时的商业智能将是未来的一大优势。虽然使用预测分析的原因有很多,但最有说服力的也是最简单的:超越学习发生了什么及其原因,发现对未来的见解,你今天就能更好地服务于你的客户。
基于机器学习的制造业预测性和规范性维护
利用机器学习监控机器健康状况并优化制造产量
作者:帕萨·德卡和罗希特·米塔尔
今天的人工智能(AI)趋势和制造业自动化水平的提高允许企业通过数据驱动的见解灵活地连接资产和提高生产率,这在以前是不可能的。随着制造业越来越多地采用自动化,处理维护问题所需的响应速度将会越来越快,从经济角度来看什么是最佳选择的自动化决策也变得越来越复杂。
规定性维护:
规范维护是一种范式转变,它促进从严格依赖计划事件转向能够从实际事件中采取实时行动。规范维护利用高级软件来确定识别点,以明确诊断根本原因问题,然后指示精确而及时的措施,以便及时改变结果。工业企业正在使用规定的维护和分析软件来减少或消除计划外停机时间,并最大限度地提高盈利能力和设备可靠性。人工智能支持的说明性维护的独特之处在于,它不仅仅预测即将发生的故障,而是努力通过分析产生以结果为中心的运营和维护建议。
提高生产力:
生产率是制造商追求的三个基本要素之一,另外两个是成本和质量。今天,估计有价值 5000 亿美元的机床在帮助企业管理他们的工业设备。然而,现代公司正在寻求超越预防性维护,以实现规范的维护系统。例如,减少停机时间对于工业设备和机器来说非常重要,有助于提高生产率和设备的整体运行效率。OEE 黄金标准仅为 80%左右。事实证明,如果没有人工或成本高昂的流程,很难超越这些效率水平。
数字核心:
实施规定维护和分析的一个关键方面是纳入下一代数字核心技术,包括人工智能、机器学习、物联网连接、协作和高级分析。这些工具必须灵活、可扩展,并且易于集成到遗留的 IT 基础设施中。它们允许组织将来自后台系统的业务流程和事务数据与来自各种来源的大量结构化和非结构化数据集成在一起。然后,高级分析可以跨数字核心及时嵌入数据,使组织能够获得新的见解,如预测结果或提出新的行动。
工业化人工智能:
人工智能元素需要在确定的基础上嵌入并同步到整个数字核心的数据中,使公司能够获得新的见解,例如预测结果和自动采取行动以确保优化结果。
高级分析:
AI/ML 系统是规定维护平台的大脑。生产机器的 ML 模型被设计用来检测生产过程中的异常行为。训练数据有助于为单个配方步骤或特定设备类型开发特定模型。通过在一些连续的基础上确定数据点是否落在这些界限之外,及时的检测和规定被完成,它被标记为异常并被报告。培训新模型和按需部署的能力是关键。通过这样做,模型能够随着时间的推移不断学习和适应
虚拟协作:
大量数据的可视化对于支持管理分析和快速决策至关重要,以便进行持续监控和说明性维护和分析。可视化工具必须综合多维的、通常是融合的数据和信息,以便支持评估、规划和预测。该工具需要是开放的、动态的、实时的,并对所有参与者可用,以便能够与所有参与者协作,在不同的抽象和网络连接级别访问数据。
案例分析
为了保持我们工作的机密性,我们在下面呈现一个抽象的用例:
问题陈述:
我们的组件制造经历了多个连续的步骤。我们的制造组件由多个移动部件组成,最显著的是运动平台和致动器。最难以捉摸的产量问题之一是随着时间的推移随机发生的间歇性电机故障。就时间、频率、组件、配方等而言,故障发生没有可识别的一致性。它们只是随机出现。关闭设备进行铁测试,直到人们能够幸运地捕捉到现场故障事件,这通常非常耗时,并对我们工厂的生产能力产生负面影响。另一方面,如果设备保持在线,则继续间歇性地制造故障产品,浪费下游工厂产能、耗材、劳动力和高额收入损失。我们以前依赖基于条件的手动监控解决方案和预防性维护计划,这限制了我们提高产量和生产率的能力。预测性和说明性维护最近已在重型制造业中采用。例如用于燃气轮机、真空泵、飞机发动机等的预测性维护。这些预测性维护解决方案在本质上是高度定制的,基于机器及其操作、领域等。此外,这些情况下使用的传感器适用于大型和重型机器,并针对大幅度的速度、加速度、旋转和倾斜进行调整。与重型机械行业的流程相比,我们的制造流程非常不同。不仅我们的制造领域和流程不同,而且数据采集的传感器要求也不同。在我们的组件制造中使用的电机尺寸小,它们的运动范围更短,不那么突然,以便处理精密和小型光学组件。目前可用的现成 IOT 传感器(用于重型制造业的运动检测)不适合我们的组件制造,因为它们体积太大,无法安装,或者不够精确和灵敏。例如,导致过度振动的运动可能会导致现有传感器无法检测到微小部件的未对准。
我们的解决方案:
我们通过广泛的解决方案需求文档提出了解决方案,详细说明了技术设计规格,如性能、可扩展性、模块化、安全性、高可用性、连接性、灵活的应用程序编程接口、CPU/内存/网络/硬盘使用规格、互操作性、可配置性、可靠性、可用性、延迟、ML / AI 算法、数据库性能、可视化、可扩展性、传感器要求。
例如:
我们与一家供应商合作,该供应商拥有满足我们所有解决方案设计规格的专业知识。通过与供应商合作,我们开发了一个预测性维护框架,该框架利用定制的机器学习技术、软件工程原理以及基于外形、功率和通信协议等选择的适当传感器。对我们的组件制造更加精确。总的来说,预测性维护框架能够执行实时检测、可视化、警报创建以及针对我们制造流程不同阶段的修复建议。这种独特的系统还使用最先进的机器学习技术和软件工程原理来抢先和自主地预测、检测、创建警报,并建议在组件制造过程中修复异常振动。该系统在制造过程的任何实际中断发生之前提醒个人并推荐修正估计。这使得我们能够对组件制造流程进行预测性和规范性的定期维护,减少突发和计划外的停机/中断,并优化我们的工厂产能、耗材、劳动力和成本。AI/ML 的平台集成是一个时间感知运行时系统和灵活的创作工具,可以更好地预测工艺和设备问题,并对我们的设备组件进行精确维护,避免突然和计划外的停机时间/避免间歇性故障制造,最大限度地减少收入损失。
我们实现的主要收益:
产量增加
提高工人生产力
减少计划外停机时间
优化盈利能力
快速实施
快速可扩展性
最大似然算法概述:
什么是异常检测? :
异常检测是关于发现模式(如离群值、异常、异常等)。)偏离数据集内的预期行为,因此它可以类似于噪声去除或新奇检测。检测到异常的模式实际上是感兴趣的,噪声检测可能略有不同,因为噪声检测的唯一目的是去除那些噪声。与大多数数据科学项目一样,异常检测的最终目标不仅仅是算法或工作模型。相反,它是关于异常/异常值所提供的洞察力的价值,即防止设备损坏所节省的业务资金。在制造领域,我们希望在异常检测实际损坏设备之前,利用异常检测主动实现预测性和规范性维护。这将预警并实现“定期维护”,避免通常会导致严重收入损失的突然停机
有人监督与无人监督:
有两种用于构建异常检测系统的主要架构:
监督异常检测—如果我们已经标记了数据集,并且知道每个数据点是否正常,就可以使用监督异常检测
无监督异常检测—数据集未标记,即每个数据点是否异常不可靠或未知
我们的 ML 管道:
我们最先进的 ML 软件框架从战略性地放置在我们制造装配各部分的传感器中执行实时传感器数据采集。所有这些都是实时的,我们的软件框架从采集的传感器信号中执行统计特征提取,导出主成分,并使用监督和非监督学习技术检测异常聚类(数据点),对传感器信号以及置信区间保护带执行时序抢先预测,并检测极端振动。以下是一个概述:
检测各种聚类的样本无监督算法:
均值漂移聚类旨在发现数据点的平滑密度中的聚类。这是一种基于质心的算法;它首先将每个数据点视为一个聚类中心。根据所提供的带宽参数,每个数据点构建一个假想的感兴趣的球体。然后,它使用球体中数据点的平均值更新球体的质心,然后围绕新平均值(新质心)构建新的感兴趣球体,然后再次使用该区域中数据点的平均值更新质心。这个过程反复进行,直到它收敛,直到质心不再移动。随后是过滤后处理阶段,以消除近似重复,从而形成最终的质心集。球体中汇聚到同一个质心的数据点被视为同一个聚类的成员
每种技术的最佳聚类数是通过优化轮廓系数来实现的。使用每个样本的平均组内距离(a)和平均最近组距离(b)计算轮廓系数。样本的轮廓系数为(b — a) / max (a,b)。为了澄清,b 是样本和该样本不属于的最近聚类之间的距离。最好的值是 1,最差的值是-1。接近 0 的值表示重叠的簇。负值通常表示样本被分配到错误的聚类,因为不同的聚类更相似
下图中,均值漂移聚类检测到我们的一个制造装配组件的各种振动阶段:
我们的软件架构:
我们有一个灵活的软件架构,可在边缘提供全部功能,并根据数据/ ML 计算需求等按需切换到基于混合边缘云的架构。我们的框架还提供了一个灵活的 API 来根据需要更新我们的 ML 模型。以下是我们的示例高级软件架构与树莓馅饼边缘计算机。我们利用了开放技术,如 MQTT(基于实时订阅的消息协议)、Influx db(用于实时分析的开源时间序列数据库)和 Grafana(用于实时可视化)
由于从实时数据处理到最大似然训练/预测的各种计算限制,我们采用了一种灵活的软件架构,可以无缝切换到混合形式。Edge-cloud 框架在滚动窗口中将数据持续归档到云中的历史归档数据库中,例如,在云数据库中维护到当前日期为止一周或一个月的历史数据,要归档的数据量可以根据使用情况而变化。该框架具有基于规则的模型健康监控系统,该系统定期(以及按需)检查 ML 模型的性能统计数据——性能统计数据可以基于但不限于用例的性质、ML 算法的性质等而变化。如果模型性能统计低于阈值(例如 f1 分数、受监督学习者的 R 平方、无监督学习者的轮廓系数等。这可以基于用例、算法等而变化。),一旦满足阈值标准,该框架触发 ML 训练管道(在线)并部署新训练的模型。以下是我们的混合架构示例:
规定性维护实时可视化平台:
我们构建了一个最先进、易于使用的智能监控平台,用于规范维护。操作人员可以监控异常情况,深入分析根本原因,并接收智能建议,以实时修复制造过程中的故障情况。基于 ML 的智能建议基于异常行为、传感器位置、传感器数据、发生时间、设备类型/属性等。有了这个平台,操作员还可以轻松查看和监控 CPU、内存、网络使用情况等。在各种制造装配服务器上。我们的可视化平台还提供自定义日期范围的回看选项。基于需求并使用回顾选项,模型健康监控系统可以指示异常检测算法在云中使用存档的历史来重新训练自身,以更好地预测未来。
总结&结论:
我们开发了一个基于机器学习的端到端可扩展、安全、模块化、可扩展、可互操作、可配置的规范维护平台。借助该平台,我们实现了组件制造流程产量的大幅提升。我们积极主动地检测故障,为我们的组件制造装配提出修复建议,从而大幅减少计划外停机时间和工厂产能、耗材、劳动力和运营成本。异常检测科学是不断变化的。我们的平台提供的灵活的 ML API 使我们能够根据需要更新我们的异常检测算法。
参考文献:
http://mqtt.org/
【https://www.influxdata.com/
http://ranger.uta.edu/~chqding/papers/KmeansPCA1.pdf
https://scikit-learn.org/stable/
预测性员工流动分析第一部分
Kaggle 上有一个名为人力资源分析的新数据集。(【https://www.kaggle.com/ludobenistant/hr-analytics)这可能是一个探索不同机器学习工具的好机会,看看它们在预测二元变量的能力方面有何不同。更重要的是,这是一个公司迟早会遇到的真实情况。把它作为一个真实的商业分析案例会很有见地。在 Tableau 的帮助下,很容易快速而深入地查看数据集,它可以进一步帮助我决定在以后的学习中使用哪些机器学习工具。第一次做,从机器学习开始,到 Tableau 结束。然而,理想的过程是以非常直接和直观的方式查看原始数据。所以我真的应该从 Tableau 开始,然后去统计。
对数据的快速浏览
好的,我们开始吧。整个数据集包含 14999 行和 10 列。“左”列是我们知道雇员是否已经离开的地方。除“销售”之外的所有其他栏目都直接或间接与员工的选择有关。从“销售”我们知道一个雇员属于哪个部门。
A first look at the data
我选择计算他们的相关矩阵作为第一步。在 R 和 Excel 中很容易做到这一点,这给人一种它们之间如何相互关联第一印象。因为我知道它们实际上是相互关联的,所以将它们全部包含在分析中是安全的。
Correlation matrix
用黄色突出显示的行包含与响应相关联的相关性。尽管一些数字非常小,低至 0.006567,但在统计上仍然是显著的。我将在这里省略卡方检验。下一步我会去 Tableau 看看故事背后有没有商业本能。
谁要离开公司?
Fraction of leaving in each department
这张图表让观众大致了解了这家公司的情况以及营业额的来源。深蓝色部分代表周转率,用数字记为 1,否则记为 0。总更替率为 0.238,各部门之间的比率与整体比率非常接近。销售、技术和支持是三个最大的部门,大部分人员流动都发生在那里。
主观感受和客观表现如何决定选择
我们将研究个人满意度和员工评价如何影响离职选择。
x 轴表示满意度,y 轴表示绩效。灰色圆点代表较小的周转率,红色越多,周转率越高。请注意,在此图中有三个红色的主要集群。第一个在左上角。它包含高绩效和不太满意的人。广义来说,满意度低于 0.11 的人离职的可能性很大。还要注意,当满意度低于 0.11 时,很少有人工作出色。这一群人在我的警报系统中被标记为“极有可能离开”,HR 可以用它来识别那些考虑明天不再回来的人。第二个星团在中部偏左的某个地方。他们的满意度介于 0.36 和 0.46 之间,评价介于 0.45 和 0.57 之间。很难找到一个理由来证明他们的动机。他们似乎无法与他们的邻居区分开来。另一件要注意的事情是,这个区域的点变得非常密集。这个问题需要进一步调查,因为我不知道它为什么会发生。从数据中得到的唯一线索是,这里的点变得更密集,但在它右边延伸到右上角的另一个更密集的部分没有显示出类似的模式。在这个大而密集的区域,有一个部分比它的周围有更高的周转概率。为什么即使他们对工作非常满意,他们也很努力,但他们还是想离开?尽管他们不像右边的人那样“完全”满意,但他们也不像左边的人。他们当然表现得很好,但是这个事实如何让他们的离开成真呢?也许这两个指标并不能完美地解释失误者的行为。我可能忽略了一个更大的画面。另一个要问的问题是为什么要有集群?我可以理解低满意度产生了离开的动力。但是当有一群人不如一个人满足和努力的时候,为什么他更倾向于离开?这不是一个容易回答的问题,所以我将把它留在这里。我会试着去不同的部门看看,以便对公司有更详细的了解。由于与上面的整体图相似的图表显示了不同的部门,我将只显示人力资源部门。
上图在很大程度上复制了这一模式。令人惊讶的是,在不同的部门,人们至少在离职方面有着相似的动机。有没有可能 it 或技术部门比销售和管理部门更喜欢久坐,因此他们的心态和看待彼此的方式会有所不同?数据没有告诉我们这一点。既然这是模拟数据,也许本身就有偏差。或者,可能有一些东西长期以来对人们隐藏着。使用数据的目的实际上是让我们能够发现未被充分重视的秘密。
工资和工作量如何影响选择
工作并获得报酬。这是一枚硬币的两面。是时候从这个角度看了。
由圆圈组成的三个长图形包含从低到高的工资信息。在每个图形上,绿色圆圈越多,换手率越高,圆圈越大,总换手率越高。每个圆圈代表一群每月工作相同时间的人。
首先,我们将讨论公司层面。每幅图都有两个讨论,一个是关于营业额的可能性,另一个是关于营业额的数量。
可能性。在低工资水平上,处于两端的人很可能会离开,这意味着工作过度或工作不足、收入微薄的人辞职的频率更高。在极端情况下,当人们疯狂地长时间工作(超过 290 小时/月)时,离职率可以达到 100%。当工资提高到中等水平时,同一批人也更倾向于离开。但这一次,与收入较低的同行相比,收入较低的人不太可能离开。然而,有一点需要注意,那些仍然长时间疯狂工作的人几乎肯定会离开公司。随着薪水越来越高,辞职的人越来越少,但还是可以看到同样的模式。
号。收入较低的人有助于提高员工流动率,部分原因是薪资结构应该像金字塔一样。
接下来我会下到部门级别。会计是第一个上来的。
这张图看起来很“绿色”,与公司图不同。只要有人离开,这个圈子的可能性就很大。中等收入的人辞职很多,而且几乎可以肯定。然后是 HR 部门。
另一个“绿色”和独特的图形。然后就来了。
一个更加丰富多彩但仍然不同的画面。在低工资水平下,只要员工工作不到一定的时间,就有可能辞职。但是当那个人挣得更多的时候,除非他/她疯狂地过度工作或者无所事事,辞职是不可能发生的。接下来是管理。
描述正在发生的事情是一件容易的事情,但是请注意不同之处。下一步,我想展示三张图来展示数据分析的一个非常重要和普遍的部分。
这三个部分依次是销售、支持和技术。它们看起来与上面的图表非常不同,但与公司级图表相似。这解释了为什么上面的图看起来不同,它们受到这三个的影响。请记住,在开始时我说过这三个部门是公司中最大的三个部门,当然它们在很大程度上决定了公司级图表的外观。如果我不深入研究,这个部门特有的模式将永远不会被发掘出来。数据分析器永远不会遗漏细节。
接下来的部分将集中讨论晋升如何影响离职的选择。首先是图表:
不辞职的决定与高达 2.6%的晋升可能性有关,而明显辞职的那组人的晋升可能性不到 0.6%。使用统计数据,我可以告诉如果保证金是显着的,我不会在这里这样做。上图只显示了相关关系,而不是因果关系。我没有忘记在部门一级做我的研究,但我不会在这里展示它。IT 和营销在这方面有很大的不同。
我也研究过工伤事故在这里扮演的角色,但我不会在本文中说明,因为它可以比作晋升。
使用 Tableau 进行了大量的预先研究,以找出营业额数据中隐藏的秘密。就我个人而言,我学到了很多关于如何使用 Tableau 的知识,至少在两个方面,它确实不同于简单地使用统计数据来做研究。第一,当我经常分解数据集时,Tableau 功能更强大,使用起来更快捷。很容易立即切换、添加、更改内容。第二,Tableau 以一种耸人听闻的方式将数据与我联系起来。有时候看起来挺可爱的。
在接下来的第二部分,我将使用 logit 回归,KNN 和决策树来建立一个更科学的设置,我应该如何看待数据。
具有人工智能和决策优化的预测性维修计划
如何通过在准确的时间安排维护来保持您的资产健康并降低维修成本
Photo by Jacek Dylag on Unsplash
什么是预测性维护?
计划外维护是许多资产密集型行业(如制造业、石油和天然气业以及运输业)的一个关键问题。由于长时间的生产停工期,成本可能非常高。它们不仅导致高度紧急的维修和新机器和零件的投资,而且意外的生产损失可能影响供应商的义务并迫使公司从其竞争对手那里购买产品,从而导致巨大的意外成本。根据 Automation.com(2016),每年因计划外维修造成的损失高达 200 亿美元。
预测性维护使用预测性分析和机器学习(ML)来确定机器的寿命以及机器在某一天发生故障的可能性。其理念是在设备出现故障之前,而不是在实际需要之前,利用这些信息来安排维护,从而避免与维修和生产损失相关的不必要成本(图 1)。根据行业的不同,资产的类型可以有所不同,从汽车和卡车到风力涡轮机、起重机和石油平台。
Figure 1: Predicting likelihood of failure helps determine the optimal time for machine maintenance
值得注意的是,与预防性维护相比,预测性维护具有真正的优势,预防性维护使用固定的更换和维修周期,通常基于供应商的规格。后者没有考虑机器的实际状态或机器运行的特定环境,例如生产水平或其他运行条件。因此,预防性维护通常是不准确的,并且由于修理计划太晚或太早而导致过高的成本。另一方面,预测性维护可以考虑历史数据,以便更准确地预测故障的可能性。
为什么预测故障是关键,但不足以解决维护计划的挑战?
机器学习模型可以考虑所有可用的信息,例如传感器数据、历史任务和订单、过去的故障历史和维护历史。因此,它可以根据每台机器的具体特征帮助确定最佳维护日(图 2)。
Figure 2: Predicting optimal maintenance day using ML (one machine at a time)
当我们一次考虑一台机器并且没有冲突优先级时,这种方法非常有效。然而,一旦我们开始引入一些复杂性、依赖性和有限的资源,确定最优的时间表就变得更加具有挑战性。例如,如果计划产量恰好在我们预测维护最佳的那一天达到最高(图 3),该怎么办?在这种情况下,提前一天安排维修可能会降低成本,因为这样我们可以避免高峰生产损失。
Figure 3: An “optimal” maintenance day may not be optimal if scheduled production numbers are high
更重要的是,我们如何处理有限的资源?如果我们的 ML 模型预测第 3 天是三台机器的最优维修日(图 4),但是只有两个维修组可用,我们该怎么办?
Figure 4: “Optimal” predicted maintenance day for each machine may not be feasible due to limited resources
决策优化有什么帮助(分三步)?
虽然机器学习可以考虑所有可用的数据和过去的历史来预测给定机器发生故障的可能性,但决策优化(DO)可以更进一步,生成一个对一组机器而言是最优的调度,该调度受到有限资源(例如,维护人员可用性)其他约束和依赖性(生产计划和维修成本)和优化指标(最小化总成本,最大化客户满意度/满足计划生产,最小化后期维护)。它不仅为我们提供了有价值的见解,而且还生成了一个可操作的时间表或计划(图 5)。
Figure 5: Combining the Power of Machine Learning & Decision Optimization for Maintenance Scheduling
与任何业务解决方案一样,仅仅创建一个模型是不够的。我们的最终目标应该是在业务用户和决策者手中交付一个解决方案。无论使用什么技术都是如此,方法也是相似的。在这里,作为一个例子,我们概述了 IBM Cloud Pak for Data (CPD),即 IBM 数据和人工智能平台,如何用于构建预测性维护计划解决方案。关键步骤如下(图 6):
Figure 6: Decision Optimization application development and deployment using IBM Cloud Pak for Data
步骤 0 :收集所有需要的数据,包括机器和故障率的历史信息。构建并部署一个机器学习模型来预测某一天发生故障的可能性。在 IBM Cloud Pak for Data 中,这可以通过多种方式完成,包括使用 AutoAI 自动选择和调整最佳模型,使用 scikit-learn 等开源包的 Python 或 R 中的模型,或者使用 SPSS Modeler 的图形用户界面。一旦模型被训练、验证和测试,它就可以被部署为在线模型,使用 REST APIs 进行访问。剩下的步骤集中在实现和部署优化模型和 web 应用程序上:
- 建立一个 DO 模型来安排维护。在 IBM Cloud Pak for Data 中,这可以使用 CPLEX Python API 来完成。DO 模型的输入将包括 ML 模型的输出,即机器故障预测。
- 配置可视化仪表板并执行假设分析,即并排创建和比较不同的场景。在 IBM Cloud Pak for Data 中,这可以使用决策优化仪表盘轻松完成,在仪表盘中,您可以通过更改输入、重新运行模型和可视化输出来创建和比较不同的场景。准备好之后,与业务用户共享仪表板,以获得关于模型和场景演示的反馈。
- 一旦业务用户有机会查看仪表板和测试场景,就可以通过 REST API 将优化模型部署为可执行的在线模型。现在,您可以简单地构建和部署一个 web 应用程序(例如 Node.js ),或者在现有的应用程序中嵌入服务,并通过访问 ML 和 DO 在线模型来生成您的维护计划。
让我们更详细地看一下前三个步骤。
步骤 1:建模业务需求
决策优化模型的关键要素是优化指标、约束和决策变量。
优化指标定义了我们优化的目标(最小化/最大化)。在预测性维护的情况下,这些指标可以是以下任何一个或组合:
- 最小化成本(维护、劳动力)
- 最大限度减少后期维护
- 最大化生产
- 最大限度提高客户满意度
优化模型需要考虑许多约束条件,包括:
- 机器故障的预测可能性(ML 模型的输出)
- 维护对生产的影响(我们可能希望避免在计划生产水平最高的日子进行维护)
- 维护人员的可用性
- 机器特性(维修成本、剩余部件寿命成本等)。)
最后,需要做出的决策(建模为决策变量)决定了每台机器计划维护的日期/时间。这些值不是我们输入数据的一部分,而是由优化引擎作为解决方案的一部分自动确定。
第二步:形象化并并排比较场景
决策优化仪表板显示我们 DO 模型的输入和输出。“输入”选项卡可能如下所示:
DO for Cloud Pak for Data Dashboard — scenario inputs
在这里,我们可以看到一些关于机器及其特性、每日计划生产水平、预测故障(ML 模型的输出)和维护成本的数据。特别令人感兴趣的是预测故障图,它可以提供一些线索,说明何时安排维护是有意义的。假设我们想使用一种启发式方法,并计划“就在它变得太红之前”,这意味着机器很可能发生故障的前一天。我们将此视为我们的“手动”场景,并将维护事件定义如下(勾号表示维护事件):
Using a heuristic to determine the optimal maintenance day for each machine
我们还定义了一个没有固定维护事件的“优化”场景,并让优化引擎自动确定时间表。解决这两个方案后,我们可以在仪表板的多方案选项卡中并排比较解决方案:
DO for Cloud Pak for Data Dashboard — compare manual vs optimized scenarios side-by-side
显然,优化的方案导致更低的总成本和更少的生产短缺。查看维护时间表,很容易发现最佳维护日期并不明显,因为在某些情况下,最好提前几天安排维护,而在其他情况下,甚至推迟一天(机器 6)。优化方案还更好地利用了资源——与“手动”方案中的两个维护组相比,只需要一个维护组。优化的好处显而易见,即使是在一个非常小的问题上(6 台机器,15 天,和少量的约束)。想象一下,当一个问题很大时(成百上千的机器和大量的约束条件),找到一个好的解决方案会有多难!
步骤 3:部署模型并将它们嵌入到您的应用程序中
一旦模型准备好,经过测试,业务决策者已经审查了场景,就可以在线部署了,剩下要做的就是开发和部署我们的 web 应用程序。我们的演示是使用简单的 Node.js 应用程序实现的。
如果需要,机器、生产水平和维护成本的最新数据将加载到单独的数据选项卡中以供参考:
在主“维护计划”选项卡下,我们连接到 ML 可执行服务以获得预测。每条曲线的顶部告诉我们每台机器最有可能出现故障的时间:
Connect to the executable ML service and obtain failure predictions
我们现在已经准备好调用优化服务,并通过单击按钮生成最佳维护计划*😗
Connect to the online DO model and obtain the optimal maintenance schedule in one click!
现在我们已经获得了最佳维护计划,我们可以通过创建新的场景并指定事件来轻松地手动修复一些维护事件(相当于上面讨论的 Cloud Pak for Data DO 控制面板中的“手动”场景):
再次求解该场景并将结果与原始结果进行比较,证实了最优解优于手动解(成本为 2,279 美元对 2,471 美元):
Solving the Manual scenario (using a simple heuristic to schedule maintenance) and comparing the results
当然,这只是一个使用 IBM Cloud Pak 实现数据、决策优化和 Node.js 的演示的简单示例。至于您可以做什么以及如何在自己的应用程序中呈现信息,可能性是无限的。
摘要
预测性维护计划是许多资产密集型行业的关键领域。创建最佳维护计划是一个具有挑战性的问题,最好使用机器学习和决策优化的组合能力来解决。虽然机器学习可以考虑所有可用的数据和过去的历史,以预测每台机器发生故障的可能性,但决策优化可以更进一步,根据有限的资源、其他约束和依赖性以及优化指标,生成对一组机器而言最优的时间表。优化不仅能提供有价值的见解,还能生成可行的时间表或计划。**
使用良好的预测性维护解决方案的好处是巨大的,包括但不限于:
- 更低的成本和更高的客户满意度
- 减少规划/调度时间和工作量
- 提高资产的可靠性和可用性
- 提高单个资产的运营效率
根据世界经济论坛和埃森哲的研究,预测性维护解决方案的商业价值是:
- -12%的调度成本
- -30%的维护费用
- -70%的非计划停机时间
如果您的公司正在寻找更好的方法来优化维护计划或解决其他预测和优化挑战,请不要犹豫,寻求帮助。IBM 数据科学精英团队的使命是帮助我们的客户在数据科学之旅中取得成功,作为这一使命的一部分,我们免费提供初始客户服务。我们很高兴在数据科学/人工智能相关项目上与您合作。更多信息请参考https://www . IBM . com/analytics/global elite/IBM-analytics-data-science-elite-team。
如果你对更多的技术细节感兴趣,请继续关注这篇博客的后续文章。在下一篇文章中,我们将揭开 ML 和 DO 模型的面纱,探索一些真正的魔法!
附加链接
“每年因计划外停机造成的损失高达 200 亿英镑”(Automation.com,2016)。使用预测的有效方法…
www.linkedin.com](https://www.linkedin.com/pulse/importance-predictive-maintenance-within-industrial-dani%C3%ABl-visser/) [## 付费项目:制造商如何实现顶级绩效
今天的工业组织承受着巨大的压力,不仅要保持竞争力,还要建立…
partners.wsj.com](https://partners.wsj.com/emerson/unlocking-performance/how-manufacturers-can-achieve-top-quartile-performance/) [## IBM 分析数据科学精英团队| IBM
编辑描述
www.ibm.com](https://www.ibm.com/analytics/globalelite/ibm-analytics-data-science-elite-team) [## IBM Cloud Pak for Data -概述
IBM Cloud Pak for Data 是一个数据平台,它统一并简化了数据的收集、组织和分析
www.ibm.com](https://www.ibm.com/products/cloud-pak-for-data) [## 智能维护加速器
查看所选文档的详细信息
community.ibm.com](https://community.ibm.com/community/user/cloudpakfordata/viewdocument/intelligent-maintenance-prediction?CommunityKey=c0c16ff2-10ef-4b50-ae4c-57d769937235&tab=librarydocuments)
爱荷华州白酒销售数据的预测模型
你好朋友们,
最近,我的任务是利用爱荷华州的大量酒类销售数据建立一个预测模型。
作为一个简短的背景,爱荷华州是一个酒精饮料控制州,这意味着该州在全州范围内保持着对酒类批发的垄断。实际上,私人零售商必须从州政府那里购买酒,然后才能卖给个人消费者。你可以在爱荷华酒精饮料部门的维基页面上了解更多。
The majestic Iowa flag
出于这个项目的目的,我利用了爱荷华州白酒销售数据的子集,这些数据可以在爱荷华州的州托管的开放数据门户上找到。虽然门户网站包含 2012 年以来的酒类销售,但我使用的数据集包含了 2015 年全年和 2016 年第一季度(1-3 月)的单个酒类销售。该项目的目标是使用 2015 年的销售数据建立一个模型,该模型可以根据 Q1 2016 年的数据预测 2016 年的总销售额。我使用 Python 中的 Pandas 库分析了数据。
简而言之,该数据集包含超过 270 万行数据。每项观察包含的信息包括:
- 购买日期(年/月/日)
- 进行购买的供应商的详细信息(例如,指定的商店编号、县和城市详细信息);
- 购买的酒的类型和品牌(例如,杰克丹尼尔的田纳西威士忌);
- 瓶子尺寸(例如 750 毫升)和购买的瓶子数量;
- 总销售额,包括国家和每瓶零售成本;和
- 出售的酒的总体积,单位为升和加仑
A snapshot of select columns in the original dataset. There are many additional data columns not pictured here.
初始数据清理和探索性分析
最初的数据清理和探索性分析包括以下步骤。
常规数据清理:
- 提高列名的清晰度,根据需要转换数据类型。
- 删除重复行
- 用真空值替换字符串“nan”值
- 对于成对的列(category_ID 和 category_name),如果一个列值没有相邻的对,我就填充它,如果可以的话,否则就把它改为 null
确保正确的计算:
- 确保瓶子尺寸(例如 750 毫升)x 售出的瓶子=售出的体积升数
- 确保瓶子的零售价值 x 售出的瓶子=销售额
- 我没有发现数学上的问题,但是检查一下还是很好的
准备模型构建
我知道,如果我能把大部分数据分成更简单的类别,分析会容易得多。因此,我创建了几个新的专栏,从长远来看,这会让我的生活变得更加轻松。
例如,我创建了一个列,将日期条目折叠到它们发生的季度和年份:
(我将我的数据帧命名为爱荷华酒精的 i_a)
#Generating column for quarter-year
i_a[“Quarter_Year”] = “-”i_a.ix[(i_a.Date > ‘2014–12–31’) & (i_a.Date < ‘2015–04–01’), “Quarter_Year”] = “Q1_2015”
i_a.ix[(i_a.Date > ‘2015–03–31’) & (i_a.Date < ‘2015–07–01’), “Quarter_Year”] = “Q2_2015”
i_a.ix[(i_a.Date > ‘2015–06–30’) & (i_a.Date < ‘2015–10–01’), “Quarter_Year”] = “Q3_2015”
i_a.ix[(i_a.Date > ‘2015–09–30’) & (i_a.Date < ‘2016–01–01’), “Quarter_Year”] = “Q4_2015”
i_a.ix[(i_a.Date > ‘2015–12–31’) & (i_a.Date < ‘2016–04–01’), “Quarter_Year”] = “Q1_2016”
我还创建了单独的列来计算每笔交易的总零售成本和州的总成本,以了解该州从其酒类销售中获得了多少利润。
当检查某些类别和 2015 年总销售额之间的关联时,我可以看到与其他不太受欢迎的选项相比,某些项目占总销售额的很大一部分。
例如,有 30 多种不同的瓶子尺寸(体积/毫升)。然而,绝大多数售出的瓶子要么是 750 毫升、1000 毫升,要么是 1750 毫升。为了使进一步的分析和模型构建更容易,我创建了一个列来指示所购买的酒的瓶子大小是 750 毫升、1000 毫升、1750 毫升还是其他。
i_a[“Consolidated_Bottle_ml”] = “”#After examining data, it made sense to consolidate bottle sizes into 750ml, 1000ml, 1750ml, and all others
i_a.ix[i_a.Bottle_Volume_ml == 750, “Consolidated_Bottle_ml”] = “750ml”
i_a.ix[i_a.Bottle_Volume_ml == 1000, “Consolidated_Bottle_ml”] = “1000ml”
i_a.ix[i_a.Bottle_Volume_ml == 1750, “Consolidated_Bottle_ml”] = “1750ml”
i_a.ix[i_a.Consolidated_Bottle_ml == “”, “Consolidated_Bottle_ml”] = “Other_ml”
当绘制与这些类别相关的相对总销售额时,可以清楚地看到这些瓶子尺寸在所有其他产品中的主导地位:
同样,我注意到酒类的大趋势表明,许多购买的要么是各种威士忌,要么是伏特加。为了解析这些,我对类别字符串进行了文本搜索,以表明所购买的酒是某种威士忌、伏特加还是其他什么:
#Creating “Is_” columns as booleans for each type in the list above
#After further analysis, only whiskey and vodka seem to warrant their own categories, with everything else in “Other”i_a[“Is_WHISK”] = i_a[‘Alcohol_Category_Name’].str.contains(“WHISK”)
i_a[“Is_VODKA”] = i_a[‘Alcohol_Category_Name’].str.contains(“VODKA”)#Creating new column to identify consolidated alcohol typei_a[“Consolidated_Category”] = “”#Assigning values as either Whiskey, Vodka, or Non-Whiskey-Vodka, depending on true values in "Is_" columns. If the category is neither whiskey, nor vodka, or is null, assigning it to this other category.i_a.ix[i_a.Is_WHISK == True, “Consolidated_Category”] = “WHISKEY”
i_a.ix[i_a.Is_VODKA == True, “Consolidated_Category”] = “VODKA”
i_a.ix[((i_a.Is_WHISK == False) & (i_a.Is_VODKA == False)) | (i_a.Alcohol_Category_Name.isnull()), “Consolidated_Category”] = “NON-WHISKEY-VODKA”
同样,你会注意到与所有其他烈性酒相比,威士忌和伏特加这两种酒是多么突出:
既然我可以看到大部分销售收入的分组,我觉得我有足够的信息来开始构建一个模型
转换数据集
为了构建我的模型,我知道我需要仅使用一个季度的销售数据来预测全年的销售。
为此,我想转换我的数据集,按商店编号对数据进行分组,然后构建一个模型,根据一个季度的数据预测每个商店的年总销售额。
我知道我希望将预测变量的数量保持在最小,所以我希望选择那些看起来能解释总销售额中最大差异的变量。
具体来说,我想根据与四个变量相关的 Q1 2015 年销售额来预测年总销售额:750 毫升瓶、1000 毫升瓶、1750 毫升瓶,以及非威士忌/非伏特加酒的购买量。
为了在 pandas 中实现这一点,我使用 groupby 语句创建了一系列独立的数据帧,然后将这些不同的数据帧连接在一起,以创建我的最终建模集。
我用多个变量分组,用“.unstack()"函数有助于将每个感兴趣的变量存储为自己的列,而不是分层嵌套结果。在开始这个过程之前,我还创建了一个单独的日期框架,仅包含 2015 年的数据(i_a_2015)。
(有几个额外的变量我没有包括在我的最终模型中,它们最初是为了好奇而添加的。)
#Use the data from 2015 to make a linear model using as many variables as you find useful to predict the yearly sales of all stores.#We don’t want to use ALL of the data from the variables of interest — we only want about 1/4 of it (as we’ll only have a quarter’s worth of data from 2016 when generating predictions for all of 2016.)#create dataframe grouped by store for 2015 that will be used for building regression model#We DO still keep ALL of the sales data from 2015 as the target variable, as we want to predict the final 2016 totals
#for all storesstore_sales_2015 = pd.DataFrame(i_a_2015.groupby(“Store_Number”).Sale_Dollars.sum())store_sales_2015.rename(columns={‘Sale_Dollars’:’Sale_Dollars_Total_2015'}, inplace=True) #Drawing out bottles_sold; keeping Q1 data and dropping Q2:Q4add_Q1_bottle_sold = pd.DataFrame(i_a_2015.groupby([“Store_Number”, “Quarter_Year”]).Bottles_Sold.sum().unstack())#alter Q1_2015 column name for easier interpretabilityadd_Q1_bottle_sold.rename(columns={‘Q1_2015’:’Bottles_Sold_Q1_2015'}, inplace=True)add_Q1_bottle_sold.drop([‘Q2_2015’, “Q3_2015”, “Q4_2015”], axis=1, inplace=True)#Finding the “mode” of the stores’ counties, which will be the only item associated with each storeadd_store_county = pd.DataFrame(i_a_2015.groupby(“Store_Number”).County.agg(lambda x:x.value_counts().index[0]))#Creating df of only Q1_2015 to make extracting of bottle sizes and other multi-variable columns easieri_a_Q1_2015 = i_a[i_a[“Quarter_Year”] == “Q1_2015”]#Drawing out bottles_sizes sales volume for 750ml, 1000ml, 1750ml, and other_ml for Q1_2015;add_Q1_bottle_sizes = pd.DataFrame(i_a_Q1_2015.groupby([“Store_Number”, “Consolidated_Bottle_ml”]).Sale_Dollars.sum().unstack())add_Q1_bottle_sizes.rename(columns={‘1000ml’:’1000ml_Sales_Q1_2015', ‘1750ml’:’1750ml_Sales_Q1_2015',’750ml’:’750ml_Sales_Q1_2015',’Other_ml’:’Other_ml_Sales_Q1_2015'}, inplace=True)#Drawing out consolidated_category sales volume for whiskey, vodka, and others for Q1_2015;add_Q1_consolidated_category = pd.DataFrame(i_a_Q1_2015.groupby([“Store_Number”, “Consolidated_Category”]).Sale_Dollars.sum().unstack())add_Q1_consolidated_category.rename(columns={‘NON-WHISKEY-VODKA’:’NON-WHISKEY-VODKA_Sales_Q1_2015', ‘VODKA’:’VODKA_Sales_Q1_2015',’WHISKEY’:’WHISKEY_Sales_Q1_2015'}, inplace=True) #saves changes#drawing out total Q1 sales from initial i_a_2015 df, dropping Q2, Q3, and Q4add_Q1_total_sales = pd.DataFrame(i_a_2015.groupby([“Store_Number”, “Quarter_Year”]).Sale_Dollars.sum().unstack())add_Q1_total_sales.rename(columns={‘Q1_2015’:’Q1_2015_total_sales’}, inplace=True) #saves changes add_Q1_total_sales.drop([‘Q2_2015’, “Q3_2015”, “Q4_2015”], axis=1, inplace=True)#creating final dataframe for modeling by concatenating all other dfsmodel_df = pd.concat([store_sales_2015, add_Q1_bottle_sold, add_store_county, add_Q1_bottle_sizes,
add_Q1_consolidated_category, add_Q1_total_sales], axis=1)#there are some NaN values where stores didn’t buy certain bottle sizes or liquor types — convert to zerosmodel_df.fillna(value=0, inplace=True)
完成所有这些后,我们有了 2015 年总销售额的数据框架,并选择了可用于预测的 Q1 销售变量。让我们快速浏览一下:
A snapshot of our dataframe used for modeling. The Index column on the far left is each store’s assigned number. Not all columns are pictured here.
检查我感兴趣的变量的关联热图,我可以看到这些变量之间有中等强度的关联,这并不完全令人惊讶(特别是考虑到非威士忌/非伏特加酒将固有地与瓶子大小重叠)。
构建预测模型
为了训练和测试我的模型,我对 2015 年的模型集进行了 70:30 的训练测试分割。这意味着我可以使用建模数据框架中 70%的数据来拟合我的模型,然后用拟合模型时没有使用的剩余 30%的数据来测试我的模型的准确性。
在下面的代码中:
X =仅使用上述热图中列出的变量的存储数据对数据框架进行建模
y =仅包含 2015 年商店总销售额的数据框架
from sklearn import linear_model
from sklearn.model_selection import train_test_split#Conducting 70:30 train-test split for purposes of building and testing model. Set random state = 1 for reproducibility.X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)#instantiate linear model for ease of coding belowlm = linear_model.LinearRegression() #generate fit of model base on training set
#fit method expects two arguments of x’s and y’smodel = lm.fit(X_train, y_train) #generate predicted values of y_test from X_test based off of training setpredictions = lm.predict(X_test)#plotting predicted ys against y values in test set plt.scatter(y_test, predictions)
plt.xlabel(“True 2015 Total Sales”)
plt.ylabel(“Predicted 2015 Total Sales”)
得到的模型的 R =.956,这意味着该模型解释了商场 2015 年年度销售额中约 95.6%的差异,这是根据我选择的变量中的 Q1 销售数据得出的。这是预测值与实际值的对比图:
我用交叉验证和正则化方法进一步检查了这个模型,但是这篇博文已经够长了,而且他们没有给已经不存在的模型增加太多东西。
对 2016 年进行预测
最后一步,是为我现有的 2016 年 Q1 再现一个类似的建模数据框架(按商店分类的信息),然后为每个商店的 2016 年总销售额生成预测。我使用了与上面巨大代码块非常相似的代码来生成 2016 预测集。
生成预测后,我将预测(LM_Predictions)附加到每个商店的行中,如下所示:
最终结果
我建立的线性模型预测 2016 年白酒总销售额为 2.92 亿美元,比 2015 年(2.84 亿美元)增长 3%。
其中,该州 2015 年的利润占总销售额的 33%(9500 万美元),该州 2016 年的预计利润为 9800 万美元。很酷,东西!
世界各地的饮料偏好
在啤酒、烈酒和葡萄酒消费方面,一些国家比其他国家更相似吗?
我使用了一个来自世卫组织的包含年度酒精消费量的数据集,对它应用了层次聚类,并将树分成 6 个聚类。结果很有趣。
地理位置相近的国家有相似的饮酒习惯,比如我们可以看到俄罗斯、白俄罗斯、斯洛伐克在一个群中,瑞士和卢森堡在一个群中,比利时、荷兰、奥地利在一个群中。潜在文化相似的国家也靠得很近,比如巴布亚新几内亚和密克罗尼西亚。
这是我的# 100 day 项目的第四天。完整代码在 github 上。
准备现场数据科学面试
从我的经历中得到的一些建议
Edited from: https://lifehacker.com/5975338/top-10-tips-for-acing-your-next-job-interview
我最近偶然看到Kristen ke hrer2018 年 4 月的文章“如何在数据科学面试中胜出”,这让我反思了自己的数据科学工作准备,以及几个月前与也在寻找类似工作的朋友们的讨论。这篇文章总结了我准备数据科学家面试的笔记。
免责声明:我和我的朋友都有博士学位和 2-3 年的学术经验背景,他们主要寻找自然语言处理方面的工作。因此,虽然我要写的大部分内容是通用的,希望对每个人都有用,但有些部分可能是特定于那个背景的。
一般来说,数据科学家职位的现场面试包括会见几个人:
- 不同经验水平的数据科学家同事
- 软件工程师、数据工程师等
- 数据科学经理和任何其他人员(例如,在初创公司中,这可能涉及 CTO 或 CEO)。
根据公司的不同,这通常需要大约半天的面试时间。除了这些,你还可能被要求做一个演讲/报告,这取决于你的角色。我只在申请以研究为重点的职位时做演讲——所以,在这篇文章中我不会深入探讨。
当我知道我要申请数据科学家的职位时,我开始了一个实时文档,添加了我在网上找到的问题,并做了自己的分类。虽然这种分类可能并不适用于所有人,但以下是我使用的分类:
- 与简历/过去工作相关的问题
- 编程和软件工程问题
- 机器学习/深度学习/NLP:概念问题
- 问题解决问题(大多与公司领域相关)
- 统计问题
- 行为问题
- 工作文化相关问题
- 我们可以/应该问面试官的问题
我浏览了各种网站,并开始在相应的部分列出我在 live 文档中发现的所有问题。虽然我没有准备好每个问题的答案,但只要一有时间,我就会试着给每个问题添加评论。在每次面试之前,我都会通读这份文件,如果我发现任何我认为与面试特别相关的未回答的问题,我会添加一个答案。每次面试后,如果我面对一个新问题,如果回家后我还记得,我会把它添加到我的文档的适当部分。像这样,那份文件现在已经增长到 30 多页了![本来真的应该更长,但我意识到我忘记了大多数被问到的问题!]
让我逐一讨论每一类问题:
简历和过往工作相关问题:
这些通常以“告诉我关于你自己的情况”开始,有时可能会有一些具体的问题,如:“你在 X 公司做什么?”、“你做 Y 用的什么库?”等等。在我看来,解决这些问题的最佳方式是:
- 练习持续 1-1.5 分钟的“自我介绍”
- 彻底检查你的简历
- 快速浏览您的公开资料(LinkedIn、Medium、Github 等)
与编程和软件工程实践相关的问题:
这些主要是工程师会问的问题,在某种程度上,也是你未来的同事数据科学家会问的问题。 一般都是做一些白板编码,讲一些典型的问题解决方法和算法等。当我说软件工程实践时,我指的是代码和模型版本控制、软件测试、代码审查等。以下是我为准备这类问题而做的一些事情:
- 在 HackerRank 上练习编码几天,每天 30-60 分钟 ,浏览 Gayle Laakmann McDowell 的《破解编码面试》。我在一所美国大学做全职助理教授,一大早我抽不出一个小时以上的时间。但是如果你完全生疏了,如果可以的话,多花点时间是有用的。
- 对于软件工程实践,由于我不是在面试一个传统的软件工程师职位,我没有花很多时间,除了列出几个问题,如果我是面试官 (例如,我什么时候使用笔记本?我在 Python 中使用类吗?如何对数据和模型进行版本控制?我如何看待数据科学的软件测试?等等。)
ML/DL/NLP:概念性问题
这些是团队中的数据科学家可能会问你的问题 。经理也可能会问这些问题来衡量你是否知道你在说什么,以及你是否能传达你所知道的。这里的 NLP 是因为我申请了这些工作,我有那方面的研究背景。但是,申请图像处理工作的人可能会有相关的问题。对于这些问题,我:
- 浏览典型的教科书内容,例如,这些学科的所有入门课程中教授的算法
- 最近的会议论文和博客文章,以了解最近的发展
- 重温了我以前为其他项目编写的一些代码,其中涉及到应用这些概念。
问题解决问题
这些都是与公司领域相关的问题。目标是看你是否能把概念上的知识应用到一个具体的问题上。 在我的采访中,这些问题通常来自一位经理,尽管有时,一位资深数据科学家也会问这些 。
一个例子可能是这样的:“我们是一个电子商务网站,我们有这个问题的假评论和假用户资料。你将如何运用你的 NLP 和 ML 知识来解决这个问题?”。根据你的回答,会有很多后续问题,比如:“你需要什么样的数据?你将如何得到它?需要什么清洁?处理此文本时,您可能会遇到什么潜在问题?”等等。
以下是我对这类问题的回答:
- 我经常看一些博客,比如的人工智能面试,在那里他们会发布一些公司特有的面试问题,这些问题集中在该公司做了什么。
- 除此之外,我还试图预测该公司领域的潜在问题,并对此有一些想法。例如,如果我们正在寻找,比方说,像 LinkedIn 这样的公司,一些潜在的 NLP 问题场景是什么?—从个人资料/工作描述中提取信息,向用户提供建议,显示与某个主题相关的不同帖子(例如,“人们现在在谈论什么?特征)等等。
统计问题
这些问题是关于一般的统计方法,他们的假设和东西。 这些通常来自数据科学家团队。 因为我没有统计学学位,所以我只关注基本问题(例如,线性回归的假设、1 型与 2 型误差、假设检验等)。有很多关于这些的在线资源,我尽可能多地梳理了这些资源,并在我的文档中列出了这些独特的问题,以及我在哪里知道它们或在网上找到它们的答案。
行为问题
行为问题主要侧重于了解我们对工作场所不同场景的反应,以及了解你的总体态度。根据我的经验,这些来自经理,以及团队/公司中的其他高级管理人员。
Gayle Laakmann McDowell 的书(包括《编码》和《产品经理》)列出了一堆行为问题。我发现这些非常详尽。另外,我还从网上搜集了一堆问题。比如“告诉我你做过的最具挑战性的项目”,“你将如何处理与老板的冲突”等等。,我们显然不会对所有这样的场景都有答案,但我试图从以前的工作经历中为尽可能多的问题准备具体的例子,以便到时候我可以根据快速回忆说话,而不是匆忙思考。虽然我的许多答案来自以前的专业经验,但也有一些来自学生时代和其他自愿(非技术)的经验。
文化契合度问题:
这些通常是任何一个面试官都会问你的问题 ,以评估你是否适合他们的团队,是否会成为一个好同事。我归类为文化适应问题的内容包括:
- 你如何与现场发生的事情保持联系?
- 你最近用过哪些工具包/库?
- 你最喜欢的算法是什么?
- 举一些数据科学中“最佳实践”的例子
- 你喜欢在小团队还是大团队工作还是自己一个人?
等等。再次,我从网上资源整理了很多问题,也加入了我作为面试官会问的问题。
问面试官的问题:
我认为面试是一个相互评估的过程。面试官在评估你的同时,你也在评估他们是否是聪明友好的同事,你是否能在那个职位上成长,以及公司的文化是否适合你。所以,我总是花时间思考该问我遇到的每个人什么。我也试着从招聘经理那里了解我到底会遇到谁,并尽可能在网上查找他们。
这些和之前的有一些共同的问题。例如,作为一名受访者,我还想了解上述文化适应问题。除此之外,我还想知道团队的长期愿景,人们现在正在做的项目,他们使用什么语言/平台,他们喜欢自己工作中的什么等等。对于经理和其他人,我也想知道我是否被派去参加会议,是否能请几天假去做与公司利益相关的个人项目等等。
我作为面试官问的问题
虽然我没有花很多时间,但我确实参加了数据科学家职位的面试。我没有问所有这些问题,但考虑到我是一名数据科学家,并且我过去有一点工程和研究背景,我的问题主要有四种:
- 技术问题:比如关于一些 NLP/ML/DL 算法及其用例。我没有问任何编程问题,因为这通常会出现在在线测试或另一位面试官的提问中。
- 解决问题:比如“你将如何为中型文章设计一个自动标记系统?”
- 关于简历/过去的工作、流程和实践的问题:例如,“你实践团队数据科学流程吗?”,“你为其他数据科学家做代码评审吗?”,“在 X 公司,你用了哪些库?”等等。
- 工作文化问题:例如,“你关注什么时事通讯/博客来保持与最新发展的联系?”
这是一个相当长的帖子,所有这些都不是在一两天内完成的。我的问题文档是在几个月的时间里建立起来的,如果我发现一些有趣的东西,我会偶尔更新它。就像我之前提到的,并不是所有这些都与每个人相关,但我希望每个人都能从中受益。我不是说这是唯一的办法,但准备这份文件对我来说真的很有用。当然,我还得补充一点:准备问题和答案只是故事的一部分。 在面试中练习和保证恰当的沟通同样重要!毕竟,我们没有一生的时间去打动面试官! 感谢阅读!
准备您的数据科学简历和投资组合
在过去的几年里,我会见了许多雇主,并进行了培训项目的面试。通过对话和面试并看到最终结果,我想我会分享更多关于如何准备你的简历,甚至是数据科学职位的面试。大部分提示都是给那些想进入数据科学行业并有“绿色”背景的人的。我不能保证结果,但我希望它可以帮助那些对数据科学充满热情的人。给出的提示是给那些对 it 充满热情的人的,因为这需要很多努力。
项目
标题本身就说明了问题,但让我借此机会进一步解释一下。经常有人问我“我能把我的学校项目作为项目组合的一部分吗?”如果要展示他们的学校项目,我有一些想法。
首先,这些学校项目中的大部分是有指导的(希望如此)并且是团队合作的。区分项目的哪一部分由谁来完成是非常具有挑战性的。我只能推断的是,基于项目的结果,团队是功能性的还是功能性的。
展示的最佳项目是在课程之外,在一个人的空闲时间完成的,因为它表明这个人对数据科学充满热情,并且愿意将他们的空闲时间花在这上面。我也可以把项目中所做的一切归功于受访者。但那是在我问了几个关于这个项目的问题以确定它之后。
使用关键词(如使用的机器学习模型、模型训练过程等)来解释项目,但要准备好解释这些关键词,尤其是在技术面试的时候。我倾向于要求受访者解释这些关键词,并且解释必须达到外行人能够理解的水平。嗯,如果一个人不能向门外汉解释它,这意味着他仍然不能完全理解它,对吗?
团队工作
如果一个人要从事数据科学甚至人工智能的工作,能够在团队中工作是非常重要的,不管他是领导还是团队成员。因此,展示任何团队项目以及取得的影响是很重要的,最好量化影响,这样面试官就可以建立一个良好的心理印象。这种影响会给我一些信息,让我知道受访者是否能在团队中工作。我还倾向于要求受访者分享他们在至少一个项目中的更多经验,以确定他/她是否能在团队中工作。
数学&统计背景
我喜欢被采访者对数学和统计学水平的良好把握。可以从他们使用的模块等级、项目、工具来推断。
模块等级确实有助于确定水平。我通常会查看整个数学模块组合,作为一个整体来确定数学和统计背景的水平。我确实会给那些成绩平平的人机会,但我肯定会问受访者为什么成绩平平。我确实会问受访者他们喜欢和不喜欢数学和统计学的什么,以确定他/她是否能够处理数据科学和人工智能所需的数学。
项目和工具确实有助于推断数学背景。这是通过他们使用的机器学习模型,他们如何实现它以及他们为什么以特定的方式实现它来看的。我可能会问他们在这些项目中面临的挑战是什么,选择特定解决方案的原因是什么,以及尽可能与背后的数学知识有关。
编程
如果可能的话,展示所有编写的代码,尤其是为数据科学项目编写的代码。否则欢迎其他语言,不一定一定是数据科学中常用的那些语言(R,Python,Scala)。
确保它是有据可查的。良好记录的意思是对代码做了什么,为什么需要以这种方式编写代码,为什么要实现代码等有很好的描述。主要目的是让采访者了解采访者在编写代码和从项目中获得洞察力时所经历的思维过程(这是我关于如何改进它的博文)。为了使数据科学具有可再现性、解释性和可说明性,文档非常重要。展示思考过程对于面试官来说是一个非常重要的考虑因素,以决定给予新员工多大的自主权来从项目中获得有意义的结果。
因此,记录良好的代码非常重要,因为它可以表明潜在雇员的知识、技能和思维水平。
结论
以上几点是我在参加培训项目面试和与许多雇主交谈时收集到的。我希望分享的几点能帮助你构建一份对潜在雇主更具“吸引力”的简历,并为可能出现的面试问题做好充分准备。
我还要推荐下面这篇文章,“如何从零开始构建数据科学投资组合”。
祝您的数据科学学习之旅愉快,请务必访问我的其他博客文章和 LinkedIn 个人资料。
**补充说明:**作为我 2020 年新年计划的一部分,我已经建立了自己的网站,最新消息请访问这里。感谢支持!
物联网数据预处理:线性重采样
处理间隔不均匀的时间序列数据
在本文中,我将介绍我们认为在分析来自物联网(IoT)的时间序列数据时最重要的预处理步骤:线性重采样。我将描述对物联网传感器数据进行重采样所面临的挑战,并介绍我们为解决这些挑战而设计的简单解决方案。
不规则物联网时间序列数据
在物联网(IoT)中,传感器和其他连接设备收集数据。这些数据被发送到云端,以便进行处理、分析或建模,从而构建智能应用。
因为物联网设备通常不会定期发出数据,所以物联网时间序列数据在采样率方面非常不规则,无论是在设备内部还是在设备之间。这使得处理和分析变得麻烦,尤其是当来自多个传感器的数据被组合在一起分析时。
因此,重采样不规则和不均匀间隔的时间序列数据到一致和规则的频率是物联网中至关重要的预处理步骤,可以极大地促进数据的连续处理。
在总部位于柏林的风险建筑商 WATTx ,我们专注于深度技术,包括物联网。在我们最近的一个项目中,我们在一栋安装了数百个传感器的建筑中建造了一个能源优化原型。这些传感器收集关于温度、湿度、亮度和运动的信息。下面,您可以看到一张展示该设置的平面图:
Smart Office IoT setup
通过分析来自办公室这些传感器的数据,我们发现了一个特别有趣的现象:
Clusters of averaged daily temperature curves
该图显示了平均温度曲线簇,并显示了大量房间在夜间和白天都出现过热,这表明 HVAC 系统的使用不理想,因此浪费了能量。
使用熊猫进行重采样
在运行与上面类似的分析之前,一个关键的预处理步骤是将不规则的时间序列数据转换为规则的频率,在所有传感器上保持一致。通过这样做,我们消除了在后面的分析过程中必须处理不规则和不一致的跨传感器时间戳的痛苦。
在 WATTx,我们大量使用 Python 及其数据科学堆栈,因此这个过程的自然选择是使用来自 pandas 的[resample](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html)
功能。
让我们来看一个简单的模拟温度曲线示例,数据点间距不均匀:
现在,假设我们想要使用平均值作为聚合函数和线性插值,以 50 分钟(任意选择)的频率对此温度曲线进行重新采样:
pd.resample(tseries, '50min', 'mean').interpolate()
如上所述,重新采样后的时间序列与原始数据并不完全匹配,但显示出相当大的偏移。这主要是因为 pandas 的重采样功能是一个按时间分组的操作,这使得它非常容易受到原始数据的精确采样和期望目标频率的影响。
物联网的两步重采样过程
为了克服这些不一致性,我们提出了一种解决方案,可以解决我们所有需要线性插值的物联网传感器的这个问题。
该解决方案由两步重采样过程组成,其中我们 (1)首先使用均值作为聚合函数和线性插值将原始时间序列向上采样到高频(例如 1 分钟或 1 秒,取决于初始数据的分辨率),然后使用简单的正向填充聚合将序列向下采样到所需的目标频率。
应用于上面的示例曲线,代码如下所示:
tmp = pd.resample(tseries, '1min', 'mean').interpolate()
resampled = pd.resample(tmp, '50min', 'ffill')
让我们来看看结果:
显然,这种两步重采样过程的结果曲线与底层数据的匹配程度更高,并且在我们所有需要线性重采样的物联网传感器中都是如此。
增强稳健性:处理缺失数据
当对物联网传感器数据进行重采样时,我们希望考虑的另一种情况是时间序列中缺失数据的大缺口。例如,传感器离线几个小时就是这种情况。
以下是一个模拟温度曲线的示例,显示了传感器在夜间(大约从晚上 10 点到早上 6 点)离线的几个小时间隔:
如果我们对这个时间序列进行重新采样,得到的数据点如下所示:
显然,重采样的数据与大块数据丢失期间的基本真实温度曲线不匹配。为了涵盖这种情况,我们引入了一个附加参数,该参数规定了缺失数据的最大间隙应该是多大,以便进行插值。如果差距超过这个指定的阈值(我们发现在大多数情况下,1 小时左右是一个好的选择),数据点不会被插值,而是作为 *NaN(不是数字)*值返回。
应用这个额外的功能,我们得到了我们想要的结果;在无数据传输期间,定期采样的数据为空值:
摘要
在这篇博文中,我们展示了对不规则物联网时间序列数据进行重采样的挑战,以及我们为克服这些挑战而设计的简单解决方案。我们简单的物联网传感器数据重采样解决方案的代码可在 GitHub gist 的中找到。
这篇博文的内容是我在 PyData Berlin 2017 演讲的一部分,幻灯片可以在这里找到。
要了解我们在 WATTx 工作的更多令人兴奋的内容,请查看我们的博客和Statice——我目前正在从事的项目,我们在其中开发技术以实现隐私保护数据科学。