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.
・ 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
Créer un modèle qui prédit un prix raisonnable au moment de l'inscription
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.
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.
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
RMLSE:Root Mean Squared Logarithmic Error Plus le score est bas, plus l'erreur d'estimation du prix est faible.
Le premier modèle est RMLSE: 0,3875
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 |
Test_id et prix
・ 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
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.
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)
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.
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.
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 ①](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