Skip to content

A DVD rental company needs your help! They want to figure out how many days a customer will rent a DVD for based on some features and has approached you for help. They want you to try out some regression models which will help predict the number of days a customer will rent a DVD for. The company wants a model which yeilds a MSE of 3 or less on a test set. The model you make will help the company become more efficient inventory planning.

The data they provided is in the csv file rental_info.csv. It has the following features:

  • "rental_date": The date (and time) the customer rents the DVD.
  • "return_date": The date (and time) the customer returns the DVD.
  • "amount": The amount paid by the customer for renting the DVD.
  • "amount_2": The square of "amount".
  • "rental_rate": The rate at which the DVD is rented for.
  • "rental_rate_2": The square of "rental_rate".
  • "release_year": The year the movie being rented was released.
  • "length": Lenght of the movie being rented, in minuites.
  • "length_2": The square of "length".
  • "replacement_cost": The amount it will cost the company to replace the DVD.
  • "special_features": Any special features, for example trailers/deleted scenes that the DVD also has.
  • "NC-17", "PG", "PG-13", "R": These columns are dummy variables of the rating of the movie. It takes the value 1 if the move is rated as the column name and 0 otherwise. For your convinience, the reference dummy has already been dropped.
import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# Import any additional modules and start coding below
# Paso 1: Cargar los datos
df = pd.read_csv('rental_info.csv')

# Veamos primero las primeras filas para entender la estructura
print(df.head())

# Y también revisemos la información de las columnas
print(df.info())
# Paso 2: Crear la columna de duración del alquiler en días
# Convertir las columnas de fechas a datetime
df['rental_date'] = pd.to_datetime(df['rental_date'])
df['return_date'] = pd.to_datetime(df['return_date'])

# Calcular la duración del alquiler en días
df['rental_length_days'] = (df['return_date'] - df['rental_date']).dt.total_seconds() / (24 * 60 * 60)
# Paso 3: Crear variables dummy para características especiales
# Crear columna 'deleted_scenes'
df['rental_length_days'] = (df['return_date'] - df['rental_date']).dt.days

# Crear columna 'behind_the_scenes'
df['behind_the_scenes'] = df['special_features'].str.contains('Behind the Scenes').astype(int)
# Paso 4: Preparar X (características) e y (variable objetivo)
# Crear variables dummy para características especiales
df['deleted_scenes'] = df['special_features'].str.contains('Deleted Scenes').astype(int)
df['behind_the_scenes'] = df['special_features'].str.contains('Behind the Scenes').astype(int)

# Seleccionar las características adecuadas para X (evitando filtrar datos sobre el objetivo)
X = df.drop(['rental_date', 'return_date', 'rental_length_days', 'special_features'], axis=1)

# Seleccionar la variable objetivo y
y = df['rental_length_days']

# Revisemos las primeras filas de X para confirmar la estructura
print(X.head())
print("Forma de X:", X.shape)
print("Forma de y:", y.shape)
# Paso 5: Dividir los datos en conjuntos de entrenamiento y prueba
X = df.drop(['rental_date', 'return_date', 'rental_length_days', 'special_features'], axis=1)
y = df['rental_length_days']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=9)

print("Forma de X_train:", X_train.shape)
print("Forma de X_test:", X_test.shape)
print("Forma de y_train:", y_train.shape)
print("Forma de y_test:", y_test.shape)
# Paso 6: Implementar y evaluar diferentes modelos de regresión
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import mean_squared_error

# Crear un diccionario para almacenar los modelos y sus MSE
models = {}

# Modelo 1: Regresión Lineal
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_test)
mse_lr = mean_squared_error(y_test, y_pred_lr)
models['Regresión Lineal'] = {'model': lr, 'mse': mse_lr}

# Modelo 2: Ridge (Regresión con regularización L2)
ridge = Ridge(random_state=9)
ridge.fit(X_train, y_train)
y_pred_ridge = ridge.predict(X_test)
mse_ridge = mean_squared_error(y_test, y_pred_ridge)
models['Ridge'] = {'model': ridge, 'mse': mse_ridge}

# Modelo 3: Lasso (Regresión con regularización L1)
lasso = Lasso(random_state=9)
lasso.fit(X_train, y_train)
y_pred_lasso = lasso.predict(X_test)
mse_lasso = mean_squared_error(y_test, y_pred_lasso)
models['Lasso'] = {'model': lasso, 'mse': mse_lasso}

# Modelo 4: Elastic Net (Combinación de L1 y L2)
elastic = ElasticNet(random_state=9)
elastic.fit(X_train, y_train)
y_pred_elastic = elastic.predict(X_test)
mse_elastic = mean_squared_error(y_test, y_pred_elastic)
models['Elastic Net'] = {'model': elastic, 'mse': mse_elastic}

# Modelo 5: Random Forest
rf = RandomForestRegressor(random_state=9)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)
mse_rf = mean_squared_error(y_test, y_pred_rf)
models['Random Forest'] = {'model': rf, 'mse': mse_rf}

# Modelo 6: Gradient Boosting
gb = GradientBoostingRegressor(random_state=9)
gb.fit(X_train, y_train)
y_pred_gb = gb.predict(X_test)
mse_gb = mean_squared_error(y_test, y_pred_gb)
models['Gradient Boosting'] = {'model': gb, 'mse': mse_gb}

# Comparar los MSE de todos los modelos
for model_name, model_info in models.items():
    print(f"{model_name}: MSE = {model_info['mse']:.4f}")

# Encontrar el mejor modelo (con MSE más bajo)
best_model_name = min(models, key=lambda k: models[k]['mse'])
best_model = models[best_model_name]['model']
best_mse = models[best_model_name]['mse']

print("\nMejor modelo:", best_model_name)
print("MSE del mejor modelo:", best_mse)

# Verificar si cumple con el criterio (MSE < 3)
if best_mse < 3:
    print("¡El mejor modelo cumple con el criterio de MSE < 3!")
else:
    print("El mejor modelo no cumple con el criterio de MSE < 3. Se requiere más optimización.")
# Guardar el mejor modelo y su MSE según las instrucciones del proyecto
best_model = models['Random Forest']['model']
best_mse = models['Random Forest']['mse']

print("Modelo final seleccionado:", best_model)
print("MSE final:", best_mse)