What shape does my Input layer need to be? I keep getting ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors

What shape does my Input layer need to be? I keep getting ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors

这是从 this project and converting to the Keras functional API. I un-subclassed the model from here 获取代码并从 inputs 开始重新定义它。

我 运行 遇到的问题是当我尝试拟合模型时出现以下错误。

ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors. Inputs received: 
[<tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>]

所以我的初始张量的形状一定是错误的 - 但我不确定如何继续,因为我尝试了几种不同的方法,但似乎没有任何意义。

import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from tensorflow import keras
from tensorflow.keras import layers
# Import CF Model Architecture
from CFModel import CFModel

RNG_SEED = 42

# Reading ratings file
ratings = pd.read_csv('data/ratings.csv', sep='\t', encoding='latin-1', 
                      usecols=['user_id', 'movie_id', 'user_emb_id', 'movie_emb_id', 'rating'])
max_userid = ratings['user_id'].drop_duplicates().max()
max_movieid = ratings['movie_id'].drop_duplicates().max()

# Reading ratings file
users = pd.read_csv('data/users.csv', sep='\t', encoding='latin-1', 
                    usecols=['user_id', 'gender', 'zipcode', 'age_desc', 'occ_desc'])

# Reading ratings file
movies = pd.read_csv('data/movies.csv', sep='\t', encoding='latin-1', 
                     usecols=['movie_id', 'title', 'genres'])

# Create training set
shuffled_ratings = ratings.sample(frac=1., random_state=RNG_SEED)

# Shuffling users
Users = shuffled_ratings['user_emb_id'].values
print( 'Users:', Users, ', shape =', Users.shape)
# Users: [5411 5439  367 ...  853 4032  785] , shape = (1000209,)

# Shuffling movies
Movies = shuffled_ratings['movie_emb_id'].values
print( 'Movies:', Movies, ', shape =', Movies.shape)
# Movies: [2682  903 3716 ... 3101 3478 1390] , shape = (1000209,)

# Shuffling ratings
Ratings = shuffled_ratings['rating'].values
print( 'Ratings:', Ratings, ', shape =', Ratings.shape)
# Ratings: [2 5 4 ... 3 5 4] , shape = (1000209,)

K_FACTORS = 100 # The number of dimensional embeddings for movies and users
TEST_USER = 2000 # A random test user (user_id = 2000)
# Define model

inputs = layers.Input(shape=(1000209, 100)) # What should this input be? 

embeddingUsers = layers.Embedding(max_userid, K_FACTORS, input_length=1)
usersEmbedded = embeddingUsers(inputs)

embeddingMovies = layers.Embedding(max_movieid, K_FACTORS, input_length=1)
moviesEmbedded = embeddingMovies(inputs)

inputs = layers.Dot(axes=1)([usersEmbedded, moviesEmbedded])

outputs = layers.Dense(5, activation='relu')(inputs)

model = keras.Model(inputs=inputs, outputs=outputs)
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)

print(model.summary())
#  Layer (type)                Output Shape              Param #
# =================================================================
#  input_2 (InputLayer)        [(None, 100, 100, 100, 1  0
#                              00)]

#  dense (Dense)               (None, 100, 100, 100, 5)  505

# =================================================================
# Total params: 505
# Trainable params: 505
# Non-trainable params: 0
# _________________________________________________________________

model.compile(optimizer="rmsprop", loss="mse")

history = model.fit(
    [Users, Movies],
    Ratings,
    epochs=10,
    batch_size=32,
    validation_split=0.2,
) 

# ValueError: Layer "model" expects 1 input(s), but it received 2 input tensors. Inputs received: 
# [<tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=int64>]

我认为你混淆了一些东西。 CFModel,您引用并试图将其转换为具有功能 API 的 Model,由两个 Sequential 子模型组成。如果你想将两个输入传递给你的模型,它应该有两个 Input 层:

import tensorflow as tf

max_userid = 5000
max_movieid = 5000
K_FACTORS = 100
user_input = tf.keras.layers.Input(shape=(1,))
movie_input = tf.keras.layers.Input(shape=(1,))

embedding_users = tf.keras.layers.Embedding(max_userid, K_FACTORS, input_length=1)
users_embedded = embedding_users(user_input)

embedding_movies = tf.keras.layers.Embedding(max_movieid, K_FACTORS, input_length=1)
movies_embedded = embedding_movies(movie_input)

inputs = tf.keras.layers.Dot(axes=1)([users_embedded, movies_embedded])
outputs = tf.keras.layers.Dense(5, activation='relu')(inputs)
model = tf.keras.Model(inputs=[user_input, movie_input], outputs=outputs)

tf.keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)

print(model.summary())

model.compile(optimizer="rmsprop", loss="mse")

history = model.fit(
    [Users, Movies],
    Ratings,
    epochs=10,
    batch_size=32,
    validation_split=0.2,
) 
Model: "model_1"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_4 (InputLayer)           [(None, 1)]          0           []                               
                                                                                                  
 input_5 (InputLayer)           [(None, 1)]          0           []                               
                                                                                                  
 embedding_2 (Embedding)        (None, 1, 100)       500000      ['input_4[0][0]']                
                                                                                                  
 embedding_3 (Embedding)        (None, 1, 100)       500000      ['input_5[0][0]']                
                                                                                                  
 dot_1 (Dot)                    (None, 100, 100)     0           ['embedding_2[0][0]',            
                                                                  'embedding_3[0][0]']            
                                                                                                  
 dense_1 (Dense)                (None, 100, 5)       505         ['dot_1[0][0]']                  
                                                                                                  
==================================================================================================
Total params: 1,000,505
Trainable params: 1,000,505
Non-trainable params: 0
__________________________________________________________________________________________________
None

由于 UsersMovies 都具有 (1000209,) 形状,因此 Input 层的输入形状都是 shape=(1,)。这意味着每个样本都包含一个 ID,该 ID 使用 Embedding 层映射到 100 维向量。哦,以防万一这不是故意的,CFModel 在计算点积后不使用 Dense 层。