Introducción a Kaggle Actual Combat (3) Predicción del precio del taxi de Nueva York Predicción del precio del taxi de la ciudad de Nueva York

Hoy compartiré con ustedes el tercer proyecto de competencia de kaggle, New-York-City-Taxi-Fare-Prediction. La característica de este proyecto es que el conjunto de datos que se nos proporciona es relativamente grande, 5.3G, y la cantidad total de datos es 5400W filas. Sin embargo, cuando estamos haciendo este proyecto, no necesitamos tantos datos. Echemos un vistazo a este proyecto juntos.

Parte 1. Importación de datos y análisis preliminar

Primero importe nuestro conjunto de datos. Debido a la gran cantidad de datos, solo importamos las primeras filas de datos de 500W para modelar.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

train = pd.read_csv('train.csv',nrows=5000000)
test = pd.read_csv('test.csv')
test_ids = test['key']

train.head()

Inserte la descripción de la imagen aquí

Se puede ver que nuestra cantidad de características de datos esta vez sigue siendo relativamente pequeña, aunque la cantidad total de datos es grande, solo hay 8 características.

train.info()

Inserte la descripción de la imagen aquí

key: index
fare_amount: precio
pickup_datetime: hora
en que el taxi recibe un invitado pickup_longitude: longitud
a la salida
pickup_latitude: latitud a la salida dropoff_longitude: longitud
a la llegada dropoff_latitude: latitud a la llegada cuenta_de_pasajeros
: número de pasajeros

train.describe()

Inserte la descripción de la imagen aquí
Los datos encerrados en el círculo rojo son un valor atípico: precios negativos, el número mínimo de pasajeros es 0 y el número máximo de pasajeros es 208.
Los datos trazados por la línea horizontal son desconcertantes: ¿Qué tipo de viaje tendrá un costo de alquiler de 1270?

Parte 2. Análisis de datos

Primero observe la distribución de las características del precio:

train.fare_amount.hist(bins=100,figsize = (16,8))
plt.xlabel("Fare Amount")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.fare_amount <100 ].fare_amount.hist(bins=100, figsize = (16,8))
plt.xlabel("Fare Amount")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.fare_amount >=100 ].fare_amount.hist(bins=100, figsize = (16,8))
plt.xlabel("Fare Amount")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.fare_amount <100].shape

Inserte la descripción de la imagen aquí

train[train.fare_amount >=100].shape

Inserte la descripción de la imagen aquí
A partir del código y diagrama anteriores, podemos sacar varias conclusiones:
1. La distribución de precios está mayoritariamente dentro de 100, una pequeña parte está por encima de 100
y los precios dentro de 100 se concentran principalmente entre 0 y 20, 3
y fuera de 100 . La mayoría de los precios se concentran en torno a 200, y algunos precios relativamente altos pueden ser valores atípicos o pueden ser precios para el aeropuerto.

A continuación, observe la distribución del número de pasajeros:

train.passenger_count.hist(bins=100,figsize = (16,8))
plt.xlabel("passenger_count")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.passenger_count<10].passenger_count.hist(bins=10,figsize = (16,8))
plt.xlabel("passenger_count")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.passenger_count<7].passenger_count.hist(bins=10,figsize = (16,8))
plt.xlabel("passenger_count")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.passenger_count>7].passenger_count.hist(bins=10,figsize = (16,8))
plt.xlabel("passenger_count")
plt.ylabel("Frequency")

Inserte la descripción de la imagen aquí

train[train.passenger_count >7]

Inserte la descripción de la imagen aquí

train[train.passenger_count ==0].shape

Inserte la descripción de la imagen aquí

plt.figure(figsize= (16,8))
sns.boxplot(x = train[train.passenger_count< 7].passenger_count, y = train.fare_amount)

Inserte la descripción de la imagen aquí

train[train.passenger_count <7][['fare_amount','passenger_count']].corr()

Inserte la descripción de la imagen aquí

A partir del código y el gráfico anteriores, podemos sacar varias conclusiones:
1. La distribución del número de personas está mayormente dentro de 7, una pequeña parte está fuera
de 7. 2. En los datos con el número de personas fuera de 7, faltan la mayoría de las coordenadas de datos y el número de personas es 208
3. Hay 17,602 datos que indican que el número de pasajeros es 0, puede ser un taxi que transporta mercancías, o puede que falten datos.
4. En el cuadro de caja se puede ver que el precio promedio de los taxis con menos de 7 se acerca a
5. Use la interfaz .corr () para verificar que la correlación entre el número de pasajeros y el monto de la tarifa no sea alta, solo 0.013

Parte 3. Procesamiento de datos

1. Procesamiento de valor nulo

train.isnull().sum()#找出空值

Inserte la descripción de la imagen aquí

train = train.dropna(how='any', axis=0)

36 valores perdidos son insignificantes para nuestro volumen de datos de 500 W, así que elijo eliminar directamente los valores perdidos

test = pd.read_csv('test.csv')
test_ids = test['key']
test.head()
test.isnull().sum()

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Haga lo mismo con el equipo de prueba, pero no faltan valores en el equipo de prueba

2. Manejo de valores atípicos

train = train[train.fare_amount>=0]

Eliminar datos con precios negativos

3. Ingeniería de
funciones ① Acorte el alcance del conjunto de entrenamiento Debido a que la cantidad de datos en el conjunto de entrenamiento es relativamente grande, podemos reducir el conjunto de entrenamiento de
acuerdo con el rango de coordenadas del conjunto de prueba.

print(min(test.pickup_longitude.min(),test.dropoff_longitude.min()))
print(max(test.pickup_longitude.max(),test.dropoff_longitude.max()))
print(min(test.pickup_latitude.min(),test.dropoff_latitude.min()))
print(max(test.pickup_latitude.max(),test.dropoff_latitude.max()))

Inserte la descripción de la imagen aquí
Obtenga -74,2 a -73 como rango de selección de longitud y 40,5 a 41,8 como rango de selección de latitud

def select_train(df, fw):
    return (df.pickup_longitude >= fw[0]) & (df.pickup_longitude <= fw[1]) & \
           (df.pickup_latitude >= fw[2]) & (df.pickup_latitude <= fw[3]) & \
           (df.dropoff_longitude >= fw[0]) & (df.dropoff_longitude <= fw[1]) & \
           (df.dropoff_latitude >= fw[2]) & (df.dropoff_latitude <= fw[3])
fw = (-74.2, -73, 40.5, 41.8)
train = train[select_train(train, fw)]

Use select_train para reducir los datos del conjunto de entrenamiento

②Construcción de nuevas características de hora. Las
características de hora originales no son adecuadas para que las usemos directamente. Teniendo en cuenta que los taxis pueden aumentar los precios en diferentes períodos de tiempo, años y meses, necesitamos extraer nuevos años y meses de las características de hora originales. , El día y la hora son novedades de nuestro modelo.

def deal_time_features(df):
    df['pickup_datetime'] = df['pickup_datetime'].str.slice(0, 16)
    df['pickup_datetime'] = pd.to_datetime(df['pickup_datetime'], utc=True, format='%Y-%m-%d %H:%M')
    df['hour'] = df.pickup_datetime.dt.hour
    df['month'] = df.pickup_datetime.dt.month
    df["year"] = df.pickup_datetime.dt.year
    df["weekday"] = df.pickup_datetime.dt.weekday
    return df
train = deal_time_features(train)
test = deal_time_features(test)
train.head()

Inserte la descripción de la imagen aquí
La función de tiempo procesado consta de hora, mes, año y día de la semana.

③Construir nuevas características de distancia
directamente usando coordenadas de latitud y longitud no favorece el funcionamiento de nuestro modelo, usamos fórmulas de conversión para convertir las coordenadas de latitud y longitud en distancia

def distance(x1, y1, x2, y2):
    p = 0.017453292519943295 
    a = 0.5 - np.cos((x2 - x1) * p)/2 + np.cos(x1 * p) * np.cos(x2 * p) * (1 - np.cos((y2 - y1) * p)) / 2
    dis = 0.6213712 * 12742 * np.arcsin(np.sqrt(a))
    return dis  
train['distance_miles'] = distance(train.pickup_latitude,train.pickup_longitude,train.dropoff_latitude,train.dropoff_longitude)
test['distance_miles'] = distance(test.pickup_latitude, test.pickup_longitude,test.dropoff_latitude,test.dropoff_longitude)
train.head()

Inserte la descripción de la imagen aquí

train[(train['distance_miles']==0)&(train['fare_amount']==0)]

Inserte la descripción de la imagen aquí
Después de construir la función de distancia, encontraremos que hay 15 datos más inútiles cuya distancia y precio son ambos 0, que se pueden eliminar

train = train.drop(index= train[(train['distance_miles']==0)&(train['fare_amount']==0)].index, axis=0)

Procesamiento especial
1. Elimine los datos con fare_amount menor que 2.5, porque la tarifa inicial de los taxis en Nueva York es 2.5

train = train.drop(index= train[train['fare_amount'] < 2.5].index, axis=0)

2. Eliminar datos con más de 7 personas

train[train.passenger_count >= 7]

Inserte la descripción de la imagen aquí

train = train.drop(index= train[train.passenger_count >= 7].index, axis=0)

Parte 4. Modelado de datos

Eche un vistazo al aspecto final después de que se procesen los datos

train.describe().T

Inserte la descripción de la imagen aquí
Utilice la interfaz .corr para ver cómo estas nuevas funciones se relacionan con los precios

train.corr()['fare_amount']

Inserte la descripción de la imagen aquí
Pasos para modelar:

df_train = train.drop(columns= ['key','pickup_datetime'], axis= 1).copy()
df_test = test.drop(columns= ['key','pickup_datetime'], axis= 1).copy()
#使用copy后的数据进行建模


from sklearn.model_selection import train_test_split 
X_train, X_test, y_train, y_test = train_test_split(df_train.drop('fare_amount',axis=1)
                                                    ,df_train['fare_amount']
                                                    ,test_size=0.2
                                                    ,random_state = 42)


#用train_test_split分出训练集和测试集

import xgboost as xgb
params = {
    
     
    'max_depth': 7,
    'gamma' :0,
    'eta':0.3, 
    'subsample': 1,
    'colsample_bytree': 0.9, 
    'objective':'reg:linear',
    'eval_metric':'rmse',
    'silent': 0
}
def XGBmodel(X_train,X_test,y_train,y_test,params):
    matrix_train = xgb.DMatrix(X_train,label=y_train)
    matrix_test = xgb.DMatrix(X_test,label=y_test)
    model=xgb.train(params=params,
                    dtrain=matrix_train,
                    num_boost_round=5000, 
                    early_stopping_rounds=10,
                    evals=[(matrix_test,'test')])
    return model

model = XGBmodel(X_train,X_test,y_train,y_test,params)

#建模


Inserte la descripción de la imagen aquí

prediction = model.predict(xgb.DMatrix(df_test), ntree_limit = model.best_ntree_limit)
prediction
#数据预测

Inserte la descripción de la imagen aquí

res = pd.DataFrame()
res['key'] = test_ids
res['fare_amount'] = prediction
res.to_csv('submission.csv', index=False)
#结果保存

Parte 5. Resumen

Mi enfoque es simplemente una forma de pensar relativamente simple, porque los únicos factores en los que puedo pensar acerca de los precios de los taxis son diferentes períodos de tiempo y distancias, estos dos factores tendrán un mayor impacto. Si tiene otras ideas y prácticas mejores, deje un mensaje en el área de discusión para informar al bloguero.
Además, hay una forma en la comunidad de kaggle de construir una nueva característica, que representa la distancia desde las coordenadas a tres aeropuertos locales diferentes. Este método lo usa el blogger directamente cuando los parámetros no están ajustados. El resultado es un aumento de 0.03. Creo que la mejora es No es demasiado grande y la función se superpone un poco con la distancia, por lo que no la usé al final. Publícalo aquí y compártelo con todos.

# def transform(data):
#     # Distances to nearby airports, 
#     jfk = (-73.7781, 40.6413)
#     ewr = (-74.1745, 40.6895)
#     lgr = (-73.8740, 40.7769)

#     data['pickup_distance_to_jfk'] = distance(jfk[1], jfk[0],
#                                          data['pickup_latitude'], data['pickup_longitude'])
#     data['dropoff_distance_to_jfk'] = distance(jfk[1], jfk[0],
#                                            data['dropoff_latitude'], data['dropoff_longitude'])
#     data['pickup_distance_to_ewr'] = distance(ewr[1], ewr[0], 
#                                           data['pickup_latitude'], data['pickup_longitude'])
#     data['dropoff_distance_to_ewr'] = distance(ewr[1], ewr[0],
#                                            data['dropoff_latitude'], data['dropoff_longitude'])
#     data['pickup_distance_to_lgr'] = distance(lgr[1], lgr[0],
#                                           data['pickup_latitude'], data['pickup_longitude'])
#     data['dropoff_distance_to_lgr'] = distance(lgr[1], lgr[0],
#                                            data['dropoff_latitude'], data['dropoff_longitude'])
    
#     return data

# train = transform(train)
# test = transform(test)

¡Gracias por leer!

Supongo que te gusta

Origin blog.csdn.net/kiligso/article/details/108696392
Recomendado
Clasificación