Tensorflow 如何在Python中运行条件神经网络(类似于R/Stata中的clogit)?

Tensorflow 如何在Python中运行条件神经网络(类似于R/Stata中的clogit)?,tensorflow,machine-learning,keras,neural-network,statistics,Tensorflow,Machine Learning,Keras,Neural Network,Statistics,我希望在Keras(或tensorflow,如果需要)中训练一个神经网络,预测每一场NHL曲棍球比赛中指定的三名球员。我的X矩阵由每个球员的标准方块分数信息组成,例如上场分钟数、进球、助攻等,目标变量可以是四类中的一类(0-不在最佳三类中,1-最佳球员,2-第二最佳球员,3-第三最佳球员) 到目前为止,这是一个非常标准的问题,一个普通的神经网络在预测球员被指定为明星的概率方面做得很好。问题是,我想添加一个约束,强制单个游戏中1、2、3类玩家的概率总和为1(所有玩家),同时保持softmax约束,

我希望在Keras(或tensorflow,如果需要)中训练一个神经网络,预测每一场NHL曲棍球比赛中指定的三名球员。我的X矩阵由每个球员的标准方块分数信息组成,例如上场分钟数、进球、助攻等,目标变量可以是四类中的一类(0-不在最佳三类中,1-最佳球员,2-第二最佳球员,3-第三最佳球员)

到目前为止,这是一个非常标准的问题,一个普通的神经网络在预测球员被指定为明星的概率方面做得很好。问题是,我想添加一个约束,强制单个游戏中1、2、3类玩家的概率总和为1(所有玩家),同时保持softmax约束,即每个玩家所有类的概率总和也必须为1。我注意到该模型在二进制分类中实现了这一点,但我还没有看到在机器学习框架中实现这一点

我相信这将需要一个定制的激活功能,Keras可以实现。然而,我不确定数学/代码会是什么样子

到目前为止,我运行的示例代码如下:

# import packages
import numpy as np
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import Adam

# generate data
games, m = 50, 40
X = np.zeros((games * m, 11))
Y = np.zeros((games * m, 4))

for i in range(games):
    rowStart, rowEnd = (i) * m, (1 + i) * m
    X[rowStart:rowEnd, 0] = i
    X[rowStart:rowEnd, 1:] = np.random.rand(m, 10)  

    for j in range(1, 4):
        rowInd = rowStart + np.random.randint(0, m)
        while np.sum(Y[rowInd]) != 0.0:
            rowInd = rowStart + np.random.randint(0, m)
        Y[rowInd, j] = 1    

# run model   
mod2 = Sequential()
mod2.add(Dense(10, activation='relu', input_shape=(X.shape[1]-1,)))
mod2.add(Dense(6, activation='relu'))
mod2.add(Dense(4, activation='softmax'))
adam = Adam(lr=0.001)
mod2.compile(optimizer=adam, loss='categorical_crossentropy', metrics=['categorical_accuracy'])
hist = mod2.fit(X[:,1:], Y, epochs=10, batch_size=m)

我真的很喜欢你关于“双向softmax”的想法。很抱歉,但过了一段时间,我能够证明这样一个softmax在一般情况下是不可能的(如果有兴趣,我可以添加一个简化的说明)

但是,在没有“双向softmax”和不违反您的限制的情况下,还有其他方法可以解决此问题。我建议您使用完整的游戏40名玩家和10个功能作为输入,并将40名玩家中的每一个作为输出进行排名。 我建议你给每个球员一个分数,而不是将每个球员分为4类(例如:1分表示不在最佳三名,0分表示第三名最佳球员,1分表示第二名最佳球员,2分表示最佳球员)。在预测中,你可以选择得分最高的球员作为最佳球员,第二名作为第二名,第三名作为第三名,其余的不在最佳三名。 这样,您就不会违反每个玩家都应该获得“等级”的限制,并且只有一个玩家获得第一、第二和第三名

请参阅下面的一个最简单的工作示例:

#导入软件包
将numpy作为np导入
从tensorflow.keras.layers导入稠密、输入、展平、重塑
从tensorflow.keras.models导入模型
从tensorflow.keras.optimizers导入Adam
#生成数据
游戏,m=50,40
X=np.0((游戏,m,11))
Y=np.零((游戏,m))
对于i系列(游戏):
X[i,:,0]=i
X[i,:,1:]=np.rand.rand(m,10)
y_指数=np.arange(m)
np.random.shuffle(y_索引)
#记分员
Y[i,Y#u索引[0]=2#最佳
Y[i,Y#u索引[1]]=1#次佳
Y[i,Y#u索引[2]=0#第三好
Y[i,Y#u索引[3:]=-1#不是最好的
#运行模式
输入=输入(形状=(m,10))#-1,因为我们不使用第一列(游戏编号)
输入\u展平=展平()(输入)
x=密集(1024,激活='relu')(输入变平)
x=密集(512,激活='relu')(x)
x=密集(256,激活='relu')(x)
输出=密集(m,激活=无)(x)
模型=模型(输入=输入,输出=输出)
亚当=亚当(lr=0.001)
compile(优化器=adam,loss='mse',metrics=['accurity'])
hist=model.fit(X[:,:,1:,Y,epochs=20,batch\u size=10)
#预测第一场比赛的第三名、第二名和最佳球员
#打印号码是玩家号码
Y_pred=model.predict(X[0:1,:,1:])
打印(np.argsort(Y_pred.reformate(-1))[-3:]
#[7 29 19]
#真正的最佳选手拳击比赛
打印(np.argsort(Y[0,:]。重塑(-1))[-3:]
#[7 29 19]

请注意,该模型体系结构比如此小的数据集(仅50个事件,每个游戏一个)更深入,节点也更多

我不明白你提到的限制。你能给出一个数字例子来说明这种情况吗?因此,神经网络确保每个玩家的类概率总和为一(行/观察)-这显然是一件好事。我需要添加一个约束条件,即对于类1、2、3,它们在每个游戏中的总和为1。直观的原因是:只有一名玩家被指定为一星级(最佳玩家),因此给定游戏的概率应限制为一。我做了一个简化的假设,每个游戏正好包含40名玩家。如果我理解正确,我认为你的模型的输入应该是整个游戏,而不仅仅是一名玩家,对吗?因为我对问题的解释是这样的:给定一场游戏中一组玩家的统计数据,预测最好、第二好和第三好的玩家(或者预测给定输入游戏中每个玩家的最佳、第二好和第三好的概率)。如果我错了,请告诉我。你的解释是正确的。虽然我不知道你会怎么把每场比赛的40名球员挤成一排?X矩阵现在是nx11*40?Y矩阵是什么?我将批量大小设置为=40=一场游戏中的所有玩家。我希望我能强制每个类的概率在每一批中总和为一,即100%有人在每个游戏中获得最佳玩家这是一个很好的解决方案,但在我的情况下,我需要概率预测,而不是预测类。我目前的(hacky)方法是迭代地将数据除以行的和,即softmax,然后除以列的和。最终,概率收敛到这样一种状态:一个玩家的所有类之和=1,所有玩家的类(1,2,3)之和=1。然而,由于许多原因,这并不令人满意,最主要的是因为我似乎无法将此过程合并到keras激活函数中。