[PYTHON] Apprenez du concours code-Mercari gagnant

introduction

En étudiant Kaggle, j'ai décidé d'étudier à partir du code de la personne qui avait remporté la première place lors du concours précédent, donc cette fois Mercari Competition -challenge "Qiita") code de la 1ère place A fait l'objet d'étude.

Ce que j'ai appris

・ Mesure du temps à l'aide du gestionnaire de contexte ・ Transformateur de pipeline et de fonction ・ TF-IDF, itemgetter, TfidfVectorizer ・ La précision peut être obtenue même avec MLP 4 couches (Perceptron multicouche). ・ Utilisez partial pour corriger y_train et ne changer que x_train

Présentation du concours Mercari

Contenu

Créer un modèle qui prédit un prix raisonnable au moment de l'inscription

importance

En présentant automatiquement un prix approprié à partir des informations sur le produit au moment de la liste, le temps et les efforts au moment de la liste sont réduits. La liste est facile.

Contexte

Si vous vendez à un prix élevé en dehors du prix du marché de Mercari, vous ne vendrez pas Au contraire, si l'article est listé à un prix inférieur au prix du marché de Mercari, le client sera perdant.

Contraintes de concurrence

Compétition du noyau: soumettez le code source lui-même à Kaggle. Une fois soumis, il sera exécuté sur Kaggle et le score sera calculé. Il existe des restrictions sur les ressources informatiques et le temps de calcul

CPU: 4 cores Memory: 16GB Disk: 1GB Délai: 1 heure GPU: aucun

Évaluation

RMLSE:Root Mean Squared Logarithmic Error Plus le score est bas, plus l'erreur d'estimation du prix est faible. image.png

Le premier modèle est RMLSE: 0,3875 image.png

Des données d'utilisation

image.png

Nom de colonne La description
name Nom du produit
item_condition_id L'état du produit, tel qu'utilisé ou neuf.(1~5)Le plus grand est en meilleur état.
category_name Catégorie approximative/Catégorie détaillée/よりCatégorie détaillée
brand_name marque. Exemple: Nike, Apple
price Prix de vente passé(USD)
shipping Que le vendeur ou l'acheteur paie les frais d'expédition. 1->Le vendeur paie, 0 ->L'acheteur paie.
item_description Détails du produit

Format de sortie

Test_id et prix image.png

Le point principal du code de la 1ère place

・ Aussi court que 100 lignes. Facile. ・ MLP 4 couches. C'est exact. Le réseau neuronal n'était-il pas encore utilisé à cette époque? ・ TF-IDF. df ['name']. Fillna ('') + '' '+ df [' brand_name ']. Fillna (' ') est utilisé pour combiner des chaînes pour améliorer la précision? ・ Standardisation de y_train ・ Apprenez 4 modèles avec 4 cœurs-> Ensemble

Préparation des données des enseignants

Mesurer le temps nécessaire à chaque processus

Puisqu'il y a une limite d'une heure, il est conçu pour mesurer combien de temps est passé dans quel processus. Avec timer est mis à la place de chaque traitement. Description de avec minuterie. image.png

Création de données enseignants

qiita.rb


 with timer('process train'):
#Route
        train = pd.read_table('../input/train.tsv')
#C'est repoussant parce qu'il y a un prix de 0 $
        train = train[train['price'] > 0].reset_index(drop=True)
#Se préparer à fractionner les données pour la formation et la validation
        cv = KFold(n_splits=20, shuffle=True, random_state=42)
#Divisez les données en formation et validation
#.split()L'objet itérable est renvoyé. "L'index pour l'apprentissage et l'index pour la vérification peuvent être récupérés.
#next()Récupérez l'élément depuis l'itérateur avec
        train_ids, valid_ids = next(cv.split(train))
#Fractionner pour la formation et la validation avec l'index obtenu
        train, valid = train.iloc[train_ids], train.iloc[valid_ids]
#Price convertit 1 ligne n colonnes en n lignes 1 colonne. Journal(a+1)Convertissez avec. Normalisation
        y_train = y_scaler.fit_transform(np.log1p(train['price'].values.reshape(-1, 1)))
#Traité dans le pipeline
        X_train = vectorizer.fit_transform(preprocess(train)).astype(np.float32)
        print(f'X_train: {X_train.shape} of {X_train.dtype}')
        del train
#Prétraitement des données de vérification également
  with timer('process valid'):
        X_valid = vectorizer.transform(preprocess(valid)).astype(np.float32)

Prétraitement

Puisque le nom de marque a une valeur manquante, il est remplacé par un espace. En plus de cela, le nom du produit et le nom de la marque sont combinés. Pour rendre plus facile TF-IDF plus tard. Je crée un nouvel élément appelé texte. 'name', 'text', 'shipping' et'item_condition_id 'seront utilisés dans le traitement Pipeline suivant.

qiita.rb


def preprocess(df: pd.DataFrame) -> pd.DataFrame:
    df['name'] = df['name'].fillna('') + ' ' + df['brand_name'].fillna('')
    df['text'] = (df['item_description'].fillna('') + ' ' + df['name'] + ' ' + df['category_name'].fillna(''))
    return df[['name', 'text', 'shipping', 'item_condition_id']]

Pipeline est utilisé pour que l'extraction de caractères et le calcul TF-IDF puissent être effectués en une série d'étapes.

Description de PipeLine.

qiita.rb


def on_field(f: str, *vec) -> Pipeline:
    return make_pipeline(FunctionTransformer(itemgetter(f), validate=False), *vec)

def to_records(df: pd.DataFrame) -> List[Dict]:
    return df.to_dict(orient='records')

 vectorizer = make_union(
        on_field('name', Tfidf(max_features=100000, token_pattern='\w+')),
        on_field('text', Tfidf(max_features=100000, token_pattern='\w+', ngram_range=(1, 2))),
        on_field(['shipping', 'item_condition_id'],
                 FunctionTransformer(to_records, validate=False), DictVectorizer()),
        n_jobs=4)
    y_scaler = StandardScaler()

 X_train = vectorizer.fit_transform(preprocess(train)).astype(np.float32)

Le résultat est le score (Sac de mots) pour le type de caractère (200000) et le score total de 'expédition' et 'élément_condition_id' 200002. image.png

Apprentissage

Il apprend avec 4 cœurs et 4 threads, puis fait la moyenne de l'ensemble. Lors de l'apprentissage, y_train est fixé à partial et seul xs est modifié.

qiita.rb


def fit_predict(xs, y_train) -> np.ndarray:
    X_train, X_test = xs
    config = tf.ConfigProto(
        intra_op_parallelism_threads=1, use_per_session_threads=1, inter_op_parallelism_threads=1)
    with tf.Session(graph=tf.Graph(), config=config) as sess, timer('fit_predict'):
        ks.backend.set_session(sess)
        model_in = ks.Input(shape=(X_train.shape[1],), dtype='float32', sparse=True)#Conception MLP
        out = ks.layers.Dense(192, activation='relu')(model_in)
        out = ks.layers.Dense(64, activation='relu')(out)
        out = ks.layers.Dense(64, activation='relu')(out)
        out = ks.layers.Dense(1)(out)
        model = ks.Model(model_in, out)
        model.compile(loss='mean_squared_error', optimizer=ks.optimizers.Adam(lr=3e-3))
        for i in range(3):#3 époque
            with timer(f'epoch {i + 1}'):
                model.fit(x=X_train, y=y_train, batch_size=2**(11 + i), epochs=1, verbose=0)#La taille du lot augmente de façon exponentielle
        return model.predict(X_test)[:, 0]#Attentes de retour


 with ThreadPool(processes=4) as pool: #4 fils
        Xb_train, Xb_valid = [x.astype(np.bool).astype(np.float32) for x in [X_train, X_valid]]
        xs = [[Xb_train, Xb_valid], [X_train, X_valid]] * 2
        y_pred = np.mean(pool.map(partial(fit_predict, y_train=y_train), xs), axis=0)#Prend la moyenne de ce que vous avez appris dans 4 cœurs
    y_pred = np.expm1(y_scaler.inverse_transform(y_pred.reshape(-1, 1))[:, 0])#Renvoie ce qui a été converti par journal en prix
    print('Valid RMSLE: {:.4f}'.format(np.sqrt(mean_squared_log_error(valid['price'], y_pred))))

référence

[Référence ①](https://copypaste-ds.hatenablog.com/entry/2019/02/15/170121#1-%E3%82%B7%E3%83%B3%E3%83%97%E3% 83% AB% E3% 81% AAMLP "Qiita") Référence ② Référence ③ Référence ④ Méthode de l'acquéreur BRONZE Mercari HP

Recommended Posts

Apprenez du concours code-Mercari gagnant
Apprenez Nim avec Python (dès le début de l'année).
Processus de compétition Kaggle du point de vue de la transition des scores
Cherchons à partir de la ligne
Supprimer le cadre de l'image
J'ai tweeté depuis le terminal!
Découvrez les bonnes pratiques de cookiecutter-django
Renforcer l'apprentissage Apprendre d'aujourd'hui
À partir d'un livre que le programmeur peut apprendre ... (Python): trouver la valeur la plus fréquente
Apprenez les méthodes M-H et HMC en lisant les statistiques bayésiennes à partir des bases
Évaluer la précision du modèle d'apprentissage par test croisé de scikit learn