[PYTHON] J'étais frustré par Kaggle, alors j'ai essayé de trouver une bonne propriété locative en grattant et en apprentissage automatique

introduction

Depuis que j'ai commencé à étudier l'apprentissage automatique, j'ai pu saisir diverses connaissances, je le ferai donc avec kaggle! J'ai essayé, mais j'étais frustré. Je n'ai aucune idée de comment y faire face! !! J'étais dans un état et ma motivation à apprendre a diminué.

J'ai trouvé l'article suivant lorsque je cherchais quelque chose d'intéressant car je pensais que ce serait inutile tel quel! [Pour les super débutants] Créez un environnement Python dont vous pouvez profiter en vous déplaçant avec le copier-coller et le grattage, l'apprentissage automatique et l'application pratique [Trouvons une bonne propriété locative avec SUUMO! ]

Je cherchais récemment une propriété à louer, alors j'ai pensé que c'était juste et l'ai essayé.

Mis en œuvre en référence à l'article. Je vais le présenter car j'ai apporté diverses améliorations à ma manière.

Pour quel genre de personne?

Pour les débutants autoproclamés de l'apprentissage automatique comme moi. C'est pour les personnes qui ont apporté diverses choses mais ne savent pas quoi faire par la suite. Je n'ai pas expliqué les termes et méthodes de base de l'apprentissage automatique, alors n'ayez pas peur.

Mon environnement

windous10 Home python3.7.3 notebook jupyter (pour les tests)

Code source https://github.com/pattatto/scraping

Amélioré

Laissez-moi d'abord vous donner un aperçu. La structure des répertoires est la suivante. image.png

Comme une série de flux

  1. Acquisition de données par scraping (suumo_getdata.py)
  2. Prétraitement des données (Preprocessing.py)
  3. Création de fonctionnalités (Feature_value.py)
  4. Apprentissage de modèles (model_lightgbm.py)
  5. Sortie du résultat de la prédiction à partir du modèle entraîné (Create_Otoku_data.py)

À l'origine, c'était un code unique, mais nous les avons modulaires. Le résultat du traitement des données est émis au format CSV à chaque fois et appelé chaque fois qu'il est utilisé.

Grattage

suumo_getdata.py


from bs4 import BeautifulSoup
import urllib3
import re
import requests
import time
import pandas as pd
from pandas import Series, DataFrame

url = input()

result = requests.get(url)
c = result.content

soup = BeautifulSoup(c)

#Je veux obtenir le nombre total de pages
summary = soup.find("div",{'id':'js-bukkenList'})
body = soup.find("body")
pages = body.find_all("div",{'class':'pagination pagination_set-nav'})
pages_text = str(pages)
pages_split = pages_text.split('</a></li>\n</ol>')
pages_split0 = pages_split[0]
pages_split1 = pages_split0[-3:]
pages_split2 = pages_split1.replace('>','')#Ça gêne quand c'est 2 chiffres>Retirer
pages_split3 = int(pages_split2)

urls = []

urls.append(url)

#Après la page 2, à la fin de l'url&page=2 est attaché
for i in range(pages_split3-1):
    pg = str(i+2)
    url_page = url + '&page=' + pg
    urls.append(url_page)

names = []
addresses = []
buildings = []
locations0 = []
locations1 = []
locations2 = []
ages = []
heights = []
floors = []
rent = []
admin = []
others = []
floor_plans = []
areas = []
detail_urls = []


for url in urls:
    result = requests.get(url)
    c = result.content
    soup = BeautifulSoup(c)
    summary = soup.find("div",{'id':'js-bukkenList'})
    apartments = summary.find_all("div",{'class':'cassetteitem'})

    for apartment in apartments:

        room_number = len(apartment.find_all('tbody'))

        name = apartment.find('div', class_='cassetteitem_content-title').text
        address = apartment.find('li', class_='cassetteitem_detail-col1').text
        building = apartment.find('span', class_='ui-pct ui-pct--util1').text
        #Ajoutez autant de noms et d'adresses de propriétés à la liste qu'il y a de chambres pour chaque location
        for i in range(room_number):
            names.append(name)
            addresses.append(address)
            buildings.append(building)

        sublocation = apartment.find('li', class_='cassetteitem_detail-col2')
        cols = sublocation.find_all('div')
        for i in range(len(cols)):
            text = cols[i].find(text=True)
            #Ajoutez des données à chaque liste autant que le nombre de pièces
            for j in range(room_number):
                if i == 0:
                    locations0.append(text)
                elif i == 1:
                    locations1.append(text)
                elif i == 2:
                    locations2.append(text)

        age_and_height = apartment.find('li', class_='cassetteitem_detail-col3')
        age = age_and_height('div')[0].text
        height = age_and_height('div')[1].text

        for i in range(room_number):
            ages.append(age)
            heights.append(height)

        table = apartment.find('table')
        rows = []
        rows.append(table.find_all('tr'))#Informations sur chaque chambre

        data = []
        for row in rows:
            for tr in row:
                cols = tr.find_all('td')#td informations détaillées sur la chambre
                if len(cols) != 0:
                    _floor = cols[2].text
                    _floor = re.sub('[\r\n\t]', '', _floor)

                    _rent_cell = cols[3].find('ul').find_all('li')
                    _rent = _rent_cell[0].find('span').text#location
                    _admin = _rent_cell[1].find('span').text#Frais de gestion

                    _deposit_cell = cols[4].find('ul').find_all('li')
                    _deposit = _deposit_cell[0].find('span').text
                    _reikin = _deposit_cell[1].find('span').text
                    _others = _deposit + '/' + _reikin

                    _floor_cell = cols[5].find('ul').find_all('li')
                    _floor_plan = _floor_cell[0].find('span').text
                    _area = _floor_cell[1].find('span').text

                    _detail_url = cols[8].find('a')['href']
                    _detail_url = 'https://suumo.jp' + _detail_url

                    text = [_floor, _rent, _admin, _others, _floor_plan, _area, _detail_url]
                    data.append(text)

        for row in data:
            floors.append(row[0])
            rent.append(row[1])
            admin.append(row[2])
            others.append(row[3])
            floor_plans.append(row[4])
            areas.append(row[5])
            detail_urls.append(row[6])


        time.sleep(3)

names = Series(names)
addresses = Series(addresses)
buildings = Series(buildings)
locations0 = Series(locations0)
locations1 = Series(locations1)
locations2 = Series(locations2)
ages = Series(ages)
heights = Series(heights)
floors = Series(floors)
rent = Series(rent)
admin = Series(admin)
others = Series(others)
floor_plans = Series(floor_plans)
areas = Series(areas)
detail_urls = Series(detail_urls)

suumo_df = pd.concat([names, addresses, buildings, locations0, locations1, locations2, ages, heights, floors, rent, admin, others, floor_plans, areas, detail_urls], axis=1)

suumo_df.columns=['Nom de l'appartement','adresse de rue', 'Type de bâtiment', 'Emplacement 1','Emplacement 2','Emplacement 3','Âge','Hauteur du bâtiment','hiérarchie','Location','Frais de gestion', 'Shiki/Je vous remercie/garantie/Shiki引,Amortissement','Plan d'étage','Zone occupée', 'URL détaillée']

suumo_df.to_csv('suumo.csv', sep = '\t', encoding='utf-16', header=True, index=False)

Le type de bâtiment (appartement, appartement, etc.) est également acquis. Quand j'ai exécuté le code original, il y avait pas mal d'appartements en tête des offres. Dans les mêmes conditions, il est naturel que l'appartement soit moins cher.

Prétraitement

Preprocessing.py


import pandas as pd
import numpy as np
from sklearn.preprocessing import OrdinalEncoder
from sklearn import preprocessing
import pandas_profiling as pdp

df = pd.read_csv('otokuSearch/data/suumo.csv', sep='\t', encoding='utf-16')

splitted1 = df['Emplacement 1'].str.split('Ayumu', expand=True)
splitted1.columns = ['Emplacement 11', 'Emplacement 12']
splitted2 = df['Emplacement 2'].str.split('Ayumu', expand=True)
splitted2.columns = ['Emplacement 21', 'Emplacement 22']
splitted3 = df['Emplacement 3'].str.split('Ayumu', expand=True)
splitted3.columns = ['Emplacement 31', 'Emplacement 32']

splitted4 = df['Shiki/Je vous remercie/garantie/Shiki引,Amortissement'].str.split('/', expand=True)
splitted4.columns = ['Dépôt', 'de l'argent clé']

df = pd.concat([df, splitted1, splitted2, splitted3, splitted4], axis=1)

df.drop(['Emplacement 1','Emplacement 2','Emplacement 3','Shiki/Je vous remercie/garantie/Shiki引,Amortissement'], axis=1, inplace=True)

df = df.dropna(subset=['Location'])

df['Location'] = df['Location'].str.replace(u'Dix mille yens', u'')
df['Dépôt'] = df['Dépôt'].str.replace(u'Dix mille yens', u'')
df['de l'argent clé'] = df['de l'argent clé'].str.replace(u'Dix mille yens', u'')
df['Frais de gestion'] = df['Frais de gestion'].str.replace(u'Cercle', u'')
df['Âge'] = df['Âge'].str.replace(u'Nouvelle construction', u'0')
df['Âge'] = df['Âge'].str.replace(u'Plus de 99 ans', u'0') #
df['Âge'] = df['Âge'].str.replace(u'Construit', u'')
df['Âge'] = df['Âge'].str.replace(u'Année', u'')
df['Zone occupée'] = df['Zone occupée'].str.replace(u'm', u'')
df['Emplacement 12'] = df['Emplacement 12'].str.replace(u'Minutes', u'')
df['Emplacement 22'] = df['Emplacement 22'].str.replace(u'Minutes', u'')
df['Emplacement 32'] = df['Emplacement 32'].str.replace(u'Minutes', u'')

df['Frais de gestion'] = df['Frais de gestion'].replace('-',0)
df['Dépôt'] = df['Dépôt'].replace('-',0)
df['de l'argent clé'] = df['de l'argent clé'].replace('-',0)

splitted5 = df['Emplacement 11'].str.split('/', expand=True)
splitted5.columns = ['Route 1', 'Station 1']
splitted5['1 à pied de la gare'] = df['Emplacement 12']
splitted6 = df['Emplacement 21'].str.split('/', expand=True)
splitted6.columns = ['Route 2', 'Station 2']
splitted6['2 à pied de la gare'] = df['Emplacement 22']
splitted7 = df['Emplacement 31'].str.split('/', expand=True)
splitted7.columns = ['Route 3', 'Station 3']
splitted7['3 à pied de la gare'] = df['Emplacement 32']

df = pd.concat([df, splitted5, splitted6, splitted7], axis=1)

df.drop(['Emplacement 11','Emplacement 12','Emplacement 21','Emplacement 22','Emplacement 31','Emplacement 32'], axis=1, inplace=True)

df['Location'] = pd.to_numeric(df['Location'])
df['Frais de gestion'] = pd.to_numeric(df['Frais de gestion'])
df['Dépôt'] = pd.to_numeric(df['Dépôt'])
df['de l'argent clé'] = pd.to_numeric(df['de l'argent clé'])
df['Âge'] = pd.to_numeric(df['Âge'])
df['Zone occupée'] = pd.to_numeric(df['Zone occupée'])

df['Location'] = df['Location'] * 10000
df['Dépôt'] = df['Dépôt'] * 10000
df['de l'argent clé'] = df['de l'argent clé'] * 10000

df['1 à pied de la gare'] = pd.to_numeric(df['1 à pied de la gare'])
df['2 à pied de la gare'] = pd.to_numeric(df['2 à pied de la gare'])
df['3 à pied de la gare'] = pd.to_numeric(df['3 à pied de la gare'])

splitted8 = df['hiérarchie'].str.split('-', expand=True)
splitted8.columns = ['1er étage', '2e étage']
splitted8['1er étage'].str.encode('cp932')
splitted8['1er étage'] = splitted8['1er étage'].str.replace(u'Sol', u'')
splitted8['1er étage'] = splitted8['1er étage'].str.replace(u'B', u'-')
splitted8['1er étage'] = splitted8['1er étage'].str.replace(u'M', u'')
splitted8['1er étage'] = pd.to_numeric(splitted8['1er étage'])
df = pd.concat([df, splitted8], axis=1)

df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 1 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 2 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 3 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 4 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 5 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 6 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'7 souterrains', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'8 souterrains', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Souterrain 9 hors sol', u'')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Une histoire', u'1')
df['Hauteur du bâtiment'] = df['Hauteur du bâtiment'].str.replace(u'Sol', u'')
df['Hauteur du bâtiment'] = pd.to_numeric(df['Hauteur du bâtiment'])

df = df.reset_index(drop=True)
df['Disposition DK'] = 0
df['Disposition K'] = 0
df['Disposition L'] = 0
df['Disposition S'] = 0
df['Plan d'étage'] = df['Plan d'étage'].str.replace(u'Studio', u'1')

for x in range(len(df)):
    if 'DK' in df['Plan d'étage'][x]:
        df.loc[x,'Disposition DK'] = 1
df['Plan d'étage'] = df['Plan d'étage'].str.replace(u'DK',u'')

for x in range(len(df)):
    if 'K' in df['Plan d'étage'][x]:
        df.loc[x,'Disposition K'] = 1
df['Plan d'étage'] = df['Plan d'étage'].str.replace(u'K',u'')

for x in range(len(df)):
    if 'L' in df['Plan d'étage'][x]:
        df.loc[x,'Disposition L'] = 1
df['Plan d'étage'] = df['Plan d'étage'].str.replace(u'L',u'')

for x in range(len(df)):
    if 'S' in df['Plan d'étage'][x]:
        df.loc[x,'Disposition S'] = 1
df['Plan d'étage'] = df['Plan d'étage'].str.replace(u'S',u'')

df['Plan d'étage'] = pd.to_numeric(df['Plan d'étage'])

splitted9 = df['adresse de rue'].str.split('quartier', expand=True)
splitted9.columns = ['Municipal']
#splitted9['quartier'] = splitted9['quartier'] + 'quartier'
#splitted9['quartier'] = splitted9['quartier'].str.replace('Tokyo','')
df = pd.concat([df, splitted9], axis=1)

splitted10 = df['Station 1'].str.split('autobus', expand=True)
splitted10.columns = ['Station 1', 'Autobus 1']
splitted11 = df['Station 2'].str.split('autobus', expand=True)
splitted11.columns = ['Station 2', 'Autobus 2']
splitted12 = df['Station 3'].str.split('autobus', expand=True)
splitted12.columns = ['Station 3', 'Autobus 3']

splitted13 = splitted10['Autobus 1'].str.split('Minutes\(arrêt de bus\)', expand=True)
splitted13.columns = ['Heure de bus 1', 'Arrêt de bus 1']
splitted14 = splitted11['Autobus 2'].str.split('Minutes\(arrêt de bus\)', expand=True)
splitted14.columns = ['Heure de bus 2', 'Arrêt de bus 2']
splitted15 = splitted12['Autobus 3'].str.split('Minutes\(arrêt de bus\)', expand=True)
splitted15.columns = ['Heure de bus 3', 'Arrêt de bus 3']

splitted16 = pd.concat([splitted10, splitted11, splitted12, splitted13, splitted14, splitted15], axis=1)
splitted16.drop(['Autobus 1','Autobus 2','Autobus 3'], axis=1, inplace=True)

df.drop(['Station 1','Station 2','Station 3'], axis=1, inplace=True)
df = pd.concat([df, splitted16], axis=1)

splitted17 = df['Station 1'].str.split('voiture', expand=True)
splitted17.columns = ['Station 1', 'Voiture 1']
splitted18 = df['Station 2'].str.split('voiture', expand=True)
splitted18.columns = ['Station 2', 'Voiture 2']
splitted19 = df['Station 3'].str.split('voiture', expand=True)
splitted19.columns = ['Station 3', 'Voiture 3']

splitted20 = splitted17['Voiture 1'].str.split('Minutes', expand=True)
splitted20.columns = ['Temps de voiture 1', 'Distance du véhicule 1']
splitted21 = splitted18['Voiture 2'].str.split('Minutes', expand=True)
splitted21.columns = ['Temps de voiture 2', 'Distance du véhicule 2']
splitted22 = splitted19['Voiture 3'].str.split('Minutes', expand=True)
splitted22.columns = ['Temps de voiture 3', 'Distance du véhicule 3']

splitted23 = pd.concat([splitted17, splitted18, splitted19, splitted20, splitted21, splitted22], axis=1)
splitted23.drop(['Voiture 1','Voiture 2','Voiture 3'], axis=1, inplace=True)

df.drop(['Station 1','Station 2','Station 3'], axis=1, inplace=True)
df = pd.concat([df, splitted23], axis=1)

df['Distance du véhicule 1'] = df['Distance du véhicule 1'].str.replace(u'\(', u'')
df['Distance du véhicule 1'] = df['Distance du véhicule 1'].str.replace(u'km\)', u'')
df['Distance du véhicule 2'] = df['Distance du véhicule 2'].str.replace(u'\(', u'')
df['Distance du véhicule 2'] = df['Distance du véhicule 2'].str.replace(u'km\)', u'')
df['Distance du véhicule 3'] = df['Distance du véhicule 3'].str.replace(u'\(', u'')
df['Distance du véhicule 3'] = df['Distance du véhicule 3'].str.replace(u'km\)', u'')

df[['Route 1','Route 2','Route 3', 'Station 1', 'Station 2','Station 3','Municipal', 'Arrêt de bus 1', 'Arrêt de bus 2', 'Arrêt de bus 3']] = df[['Route 1','Route 2','Route 3', 'Station 1', 'Station 2','Station 3','Municipal', 'Arrêt de bus 1', 'Arrêt de bus 2', 'Arrêt de bus 3']].fillna("NAN")
df[['Heure de bus 1','Heure de bus 2','Heure de bus 3',]] = df[['Heure de bus 1','Heure de bus 2','Heure de bus 3']].fillna(0)#S'il y a une valeur manquante, une erreur se produira dans le calcul du montant de la fonction, remplacez-la par 0.
df['Heure de bus 1'] = df['Heure de bus 1'].astype(float)
df['Heure de bus 2'] = df['Heure de bus 2'].astype(float)
df['Heure de bus 3'] = df['Heure de bus 3'].astype(float)

oe = preprocessing.OrdinalEncoder()
df[['Type de bâtiment', 'Route 1','Route 2','Route 3', 'Station 1', 'Station 2','Station 3','Municipal', 'Arrêt de bus 1', 'Arrêt de bus 2', 'Arrêt de bus 3']] = oe.fit_transform(df[['Type de bâtiment', 'Route 1','Route 2','Route 3', 'Station 1', 'Station 2','Station 3','Municipal', 'Arrêt de bus 1', 'Arrêt de bus 2', 'Arrêt de bus 3']].values)

df['Location+Frais de gestion'] = df['Location'] + df['Frais de gestion']

df_for_search = df.copy()

#Fixer le prix maximum
df = df[df['Location+Frais de gestion'] < 300000]

df = df[["Nom de l'appartement",'Type de bâtiment', 'Location+Frais de gestion', 'Âge', 'Hauteur du bâtiment', '1er étage',
       'Zone occupée','Route 1','Route 2','Route 3', 'Station 1', 'Station 2','Station 3','1 à pied de la gare', '2 à pied de la gare','3 à pied de la gare','Plan d'étage', 'Plan d'étageDK', 'Plan d'étageK', 'Plan d'étageL', 'Plan d'étageS',
       'Municipal', 'Arrêt de bus 1', 'Arrêt de bus 2', 'Arrêt de bus 3', 'Heure de bus 1','Heure de bus 2','Heure de bus 3']]

df.columns = ['name', 'building', 'real_rent','age', 'hight', 'level','area', 'route_1','route_2','route_3','station_1','station_2','station_3','station_wolk_1','station_wolk_2','station_wolk_3','room_number','DK','K','L','S','adress', 'bus_stop1', 'bus_stop2', 'bus_stop3', 'bus_time1', 'bus_time2', 'bus_time3']


#pdp.ProfileReport(df)
df.to_csv('otokuSearch/Preprocessing/Preprocessing.csv', sep = '\t', encoding='utf-16', header=True, index=False)
df_for_search.to_csv('otokuSearch/Preprocessing/df_for_search.csv', sep = '\t', encoding='utf-16', header=True, index=False)

Le traitement était assez difficile ici. La colonne améliorée contient des informations sur la station. À l'origine, ce n'était que des informations sur la station et la distance de la gare. Cependant, les informations sur la gare comprenaient toujours le temps de trajet en arrêt de bus et en bus, ainsi que le temps en voiture jusqu'à la gare la plus proche.

Comme ça ** Kawaguchi Station Bus 9 minutes (arrêt de bus) Motogo Junior High School 1 minute à pied ** Lorsque ces données sont prétraitées

Station 1 1 à pied
Bus de la gare de Kawaguchi 9 minutes(arrêt de bus)École secondaire Motogo 1

Dans la colonne de la station 1 Kawaguchi Station Bus 9 minutes (arrêt de bus) Motogo Junior High School À pied 1 1 minute) Ce sera à 1 minute à pied de la prochaine gare. De plus, puisque les informations de bus sont incluses dans le nom de la station, les informations de la station seront différentes de celles de la station Kawaguchi lorsqu'elles seront codées par étiquette plus tard. Je divise donc cela en ** arrêt de bus **, ** temps de bus **, ** temps de trajet en voiture **.

De plus, le type de bâtiment et l'arrêt de bus ajoutés sont codés par étiquette.

Création de fonctionnalités

Feature_value.py


import pandas as pd
import numpy as np

df = pd.read_csv('otokuSearch/Preprocessing/Preprocessing.csv', sep='\t', encoding='utf-16')

df["per_area"] = df["area"]/df["room_number"]
df["hight_level"] = df["hight"]*df["level"]
df["area_hight_level"] = df["area"]*df["hight_level"]
df["distance_staion_1"] = df["station_1"]*df["station_wolk_1"]+df["bus_stop1"]*df["bus_time1"]
df["distance_staion_2"] = df["station_2"]*df["station_wolk_2"]+df["bus_stop2"]*df["bus_time2"]
df["distance_staion_3"] = df["station_3"]*df["station_wolk_3"]+df["bus_stop3"]*df["bus_time3"]

df.to_csv('otokuSearch/Featurevalue/Fettur_evalue.csv', sep = '\t', encoding='utf-16', header=True, index=False)

En utilisant les données de bus nouvellement créées, nous avons créé une nouvelle quantité de fonction de la distance à la station.

Au début, j'ai créé un tel montant de fonctionnalités. df["per_real_rent"] = df["real_rent"]/df["area"] Cependant, quand j'ai regardé de près, je l'ai supprimé car il contenait la variable objective (informations sur le loyer prévu). Plus tard, je visualiserai l'importance de chaque fonctionnalité lors de l'apprentissage. Au début, j'étais ravi d'avoir pu obtenir un bon nombre de fonctionnalités car l'importance était exceptionnelle. .. ..

Apprentissage de modèle

model_lightgbm.py


#Bibliothèque d'analyse de données
import pandas as pd
import numpy as np

#Bibliothèque de visualisation de données
import matplotlib.pyplot as plt
import seaborn as sns

#Bibliothèque de forêt aléatoire
import lightgbm as lgb

#Une bibliothèque qui sépare les données d'entraînement et les données d'évaluation du modèle pour la vérification des intersections
from sklearn.model_selection import KFold

#Bibliothèque requise pour le traitement des fonctions
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
#Bibliothèque requise pour enregistrer le modèle
import pickle

#Une fonction qui décrit les valeurs prédites et correctes
def True_Pred_map(pred_df):
    RMSE = np.sqrt(mean_squared_error(pred_df['true'], pred_df['pred']))
    R2 = r2_score(pred_df['true'], pred_df['pred'])
    plt.figure(figsize=(8,8))
    ax = plt.subplot(111)
    ax.scatter('true', 'pred', data=pred_df)
    ax.set_xlabel('True Value', fontsize=15)
    ax.set_ylabel('Pred Value', fontsize=15)
    ax.set_xlim(pred_df.min().min()-0.1 , pred_df.max().max()+0.1)
    ax.set_ylim(pred_df.min().min()-0.1 , pred_df.max().max()+0.1)
    x = np.linspace(pred_df.min().min()-0.1, pred_df.max().max()+0.1, 2)
    y = x
    ax.plot(x,y,'r-')
    plt.text(0.1, 0.9, 'RMSE = {}'.format(str(round(RMSE, 5))), transform=ax.transAxes, fontsize=15)
    plt.text(0.1, 0.8, 'R^2 = {}'.format(str(round(R2, 5))), transform=ax.transAxes, fontsize=15)


df = pd.read_csv('otokuSearch/Featurevalue/Fettur_evalue.csv', sep='\t', encoding='utf-16')

#kf :Une zone qui spécifie le comportement du partitionnement des données. Cette fois, il y a 10 divisions et un mélange de données.
kf = KFold(n_splits=10, shuffle=True, random_state=1)

#predicted_df :Facilitez désormais les trames de données vides en combinant chaque valeur prédite à partir de maintenant
predicted_df = pd.DataFrame({'index':0, 'pred':0}, index=[1])

#Les paramètres n'ont pas été ajustés
lgbm_params = {
        'objective': 'regression',
        'metric': 'rmse',
        'num_leaves':80
}

#Vérification du croisement Puisqu'elle est divisée en 4 parties, la boucle est répétée 10 fois.
#Donnez un index à kf et demandez-leur de déterminer l'index des données d'entraînement et l'index des données d'évaluation.
#df,Former le numéro d'index des données d'apprentissage et le numéro d'index des données d'évaluation utilisées pour la première fois à partir de l'index_index, val_Sortie vers index
for train_index, val_index in kf.split(df.index):

    #Divisez en données d'entraînement et données d'évaluation et variables explicatives et variables objectives en utilisant l'index des données d'entraînement et l'index des données d'évaluation
    X_train = df.drop(['real_rent','name'], axis=1).iloc[train_index]
    y_train = df['real_rent'].iloc[train_index]
    X_test = df.drop(['real_rent','name'], axis=1).iloc[val_index]
    y_test = df['real_rent'].iloc[val_index]

    #Traiter dans un ensemble de données pour accélérer LightGBM
    lgb_train = lgb.Dataset(X_train, y_train)
    lgb_eval = lgb.Dataset(X_test, y_test)

    #Construction de modèles LightGBM
    gbm = lgb.train(lgbm_params,
                lgb_train,
                valid_sets=(lgb_train, lgb_eval),
                num_boost_round=10000,
                early_stopping_rounds=100,
                verbose_eval=50)

    #Mettez les variables explicatives pour l'évaluation dans le modèle et sortez la valeur prévue
    predicted = gbm.predict(X_test)

    #temp_df :Combinez la valeur prédite avec l'index d'origine pour faire correspondre la valeur prédite avec la valeur de réponse correcte
    temp_df = pd.DataFrame({'index':X_test.index, 'pred':predicted})

    #predicted_df :Temp dans un bloc de données vide_Combine df → Dans la boucle après le deuxième tour, prédite_temp à df (contenu fourmi)_jointure df
    predicted_df = pd.concat([predicted_df, temp_df], axis=0)

predicted_df = predicted_df.sort_values('index').reset_index(drop=True).drop(index=[0]).set_index('index')
predicted_df = pd.concat([predicted_df, df['real_rent']], axis=1).rename(columns={'real_rent' : 'true'})

True_Pred_map(predicted_df)

print(r2_score(y_test, predicted)  )
lgb.plot_importance(gbm, figsize=(12, 6))
plt.show()

#Enregistrer le modèle
with open('otokuSearch/model/model.pickle', mode='wb') as fp:
    pickle.dump(gbm, fp)

Comme mentionné dans l'article d'origine, les données d'entraînement et les données que vous souhaitez prédire sont presque les mêmes. Il est à l'état de "mise en conserve"

J'ai donc mis en place une validation croisée. J'ai emprunté le code ici. Il est expliqué d'une manière très facile à comprendre. https://rin-effort.com/2019/12/31/machine-learning-8/

Pour expliquer brièvement la vérification croisée

  1. Divisez les données d'entraînement (10 cette fois)
  2. Apprendre en utilisant l'un d'entre eux comme validation et le reste comme données d'entraînement
  3. Évaluer avec les données de validation
  4. Répétez l'apprentissage → l'évaluation en modifiant les données de validation par le montant divisé
  5. Évaluez le modèle en faisant la moyenne de ces scores

J'ai essayé de sauvegarder le modèle que j'ai créé plus tard. C'est un tracas à apprendre à chaque fois.

Lorsqu'il est exécuté de la même manière que le code d'origine, une carte de valeurs valides prédites et un graphique des caractéristiques importantes sont générés. C'est toute une corrélation! image.png Le type de bâtiment nouvellement acquis n'a pas beaucoup contribué. image.png

Création de données de propriété rentable

Create_Otoku_data.py


import pandas as pd
import numpy as np
import lightgbm as lgb
import pickle

#Lire les données
df = pd.read_csv('otokuSearch/Featurevalue/Fettur_evalue.csv', sep='\t', encoding='utf-16')

#Chargement du modèle entraîné
with open('otokuSearch/model/model.pickle', mode='rb') as fp:
    gbm = pickle.load(fp)


#Création de données immobilières rentables
y = df["real_rent"]
X = df.drop(['real_rent',"name"], axis=1)
pred = list(gbm.predict(X, num_iteration=gbm.best_iteration))
pred = pd.Series(pred, name="Valeur prédite")
diff = pd.Series(df["real_rent"]-pred,name="Différence par rapport à la valeur prédite")
df_for_search = pd.read_csv('otokuSearch/Preprocessing/df_for_search.csv', sep='\t', encoding='utf-16')
df_for_search['Location+Frais de gestion'] = df_for_search['Location'] + df_for_search['Frais de gestion']
df_search = pd.concat([df_for_search,diff,pred], axis=1)
df_search = df_search.sort_values("Différence par rapport à la valeur prédite")
df_search = df_search[["Nom de l'appartement",'Location+Frais de gestion', 'Valeur prédite',  'Valeur préditeとの差', 'URL détaillée', 'Plan d'étage', 'Zone occupée', 'hiérarchie', 'Station 1', '1 à pied', 'Plan d'étageDK', 'Plan d'étageK', 'Plan d'étageL']]
df_search.to_csv('otokuSearch/Otoku_data/otoku.csv', sep = '\t',encoding='utf-16')

Aucun changement majeur Nous venons de lire le modèle d'entraînement et d'ajouter des colonnes pour les données de sortie.

Cliquez ici pour le premier endroit qui brille du fichier de sortie! image.png A 2 minutes à pied de la gare! 3LDK! Avec cela, le loyer de 82 000 yens est magnifique! Cependant, l'itinéraire est un peu local. .. ..

résultat

Il est maintenant possible de créer des données de propriété raisonnables. Cependant, il n'y a pas du tout d'EDA (Exploratory Data Analysis), donc plus d'analyses sont nécessaires pour améliorer la précision. Après cela, il serait bon d'augmenter les données qui sont grattées. Par exemple, il existe différents types tels que le gaz de ville et les climatiseurs. Il n'y a pas de fin à d'autres choses comme le réglage des hyper paramètres. Eh bien, j'ai pu faire ce que je voulais faire, alors Yoshi!

Après avoir géré divers codes, j'ai enfin compris la nécessité de git. Il existe différentes récoltes telles que l'utilisation d'Atom et l'apprentissage de l'utilisation de git, J'ai réalisé que la programmation était la meilleure façon d'apprendre dans la pratique.

à partir de maintenant

Je voudrais en quelque sorte amener le modèle créé cette fois à l'aide de Django sous la forme d'un système. Lorsque vous entrez l'URL de la page, il semble que le loyer est prédit et que le profit est donné. J'écrirai un article si je peux l'essayer.

Recommended Posts

J'étais frustré par Kaggle, alors j'ai essayé de trouver une bonne propriété locative en grattant et en apprentissage automatique
[Keras] J'ai essayé de résoudre le problème de classification des zones de type beignet par apprentissage automatique [Étude]
Gratter et manger des bûches - je veux trouver un bon restaurant! ~ (Travail)
J'ai essayé de vérifier la meilleure façon de trouver un bon partenaire de mariage
[Pour les super débutants] Construction de l'environnement Python et grattage et apprentissage automatique et application pratique dont vous pouvez profiter en vous déplaçant avec copie [Trouvons une bonne propriété locative avec SUUMO! ]
J'ai essayé d'obtenir une image en grattant
J'ai essayé de prédire la présence ou l'absence de neige par apprentissage automatique.
J'ai essayé de prédire l'évolution de la quantité de neige pendant 2 ans par apprentissage automatique
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
J'ai essayé de déplacer l'apprentissage automatique (détection d'objet) avec TouchDesigner
J'ai essayé de faire une simulation de séparation de source sonore en temps réel avec l'apprentissage automatique Python
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
Application correspondante, j'ai essayé de prendre des statistiques de personnes fortes et j'ai essayé de créer un modèle d'apprentissage automatique
J'ai essayé de vérifier la classification yin et yang des membres hololive par apprentissage automatique
Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 1)
J'ai essayé d'utiliser Tensorboard, un outil de visualisation pour l'apprentissage automatique
J'ai essayé l'apprentissage automatique pour convertir des phrases en style XX
J'ai trébuché lorsque j'ai essayé d'installer Basemap, donc un mémorandum
[Apprentissage automatique] J'ai essayé de résumer la théorie d'Adaboost
J'ai essayé d'écrire dans un modèle de langage profondément appris
J'ai essayé HR Tech pour développer un moteur de recherche expert par apprentissage automatique des informations de réunion en interne
J'ai essayé de trouver la différence entre A + = B et A = A + B en Python, alors notez
J'ai essayé de créer un pointage de crédit simple avec régression logistique.
[Python] J'ai essayé d'implémenter un tri stable, alors notez
Mémorandum of scraping & machine learning [technique de développement] par Python (chapitre 4)
Je souhaite créer un service d'apprentissage automatique sans programmation! API Web
Mémorandum of scraping & machine learning [technique de développement] par Python (chapitre 5)
[Apprentissage automatique] J'ai essayé de faire quelque chose comme passer des images
J'ai essayé l'apprentissage automatique avec liblinear
(Apprentissage automatique) J'ai essayé de comprendre attentivement l'algorithme EM dans la distribution gaussienne mixte avec l'implémentation.
J'ai changé de travail pour devenir ingénieur en apprentissage automatique chez AtCoder Jobs
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.
Mayungo's Python Learning Episode 6: J'ai essayé de convertir une chaîne de caractères en nombre
J'ai essayé de classer les accords de guitare en temps réel en utilisant l'apprentissage automatique
(Apprentissage automatique) J'ai essayé de comprendre attentivement la régression linéaire bayésienne avec l'implémentation
J'ai essayé de trouver l'itinéraire optimal du pays des rêves par recuit (quantique)
J'ai essayé de classer les nombres de mnist par apprentissage non supervisé [PCA, t-SNE, k-means]
J'ai essayé de visualiser le modèle avec la bibliothèque d'apprentissage automatique low-code "PyCaret"
J'ai essayé de classer Oba Hanana et Otani Emiri par apprentissage profond
J'ai essayé de vérifier le résultat du test A / B avec le test du chi carré
Je souhaite créer un service d'apprentissage automatique sans programmation!
J'étais accro à essayer Cython avec PyCharm, alors prenez note
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
J'ai essayé de créer un linebot (préparation)
J'ai essayé d'apprendre avec le Titanic de Kaggle (kaggle②)
[Kaggle] J'ai essayé l'apprentissage d'ensemble avec LightGBM
J'ai créé une API Web
J'ai essayé d'utiliser pipenv, alors prenez note
Essayez de dessiner un "front de type carte météo" par apprentissage automatique basé sur les données météorologiques (3)
[Python] Deep Learning: J'ai essayé d'implémenter Deep Learning (DBN, SDA) sans utiliser de bibliothèque.
Un débutant en apprentissage automatique a essayé de créer un modèle de prédiction de courses de chevaux avec python
Essayez de dessiner un "front de type carte météo" par apprentissage automatique basé sur des données météorologiques (1)
Essayez de dessiner un "front de type carte météo" par apprentissage automatique basé sur des données météorologiques (4)
[Azure] J'ai essayé de créer une machine virtuelle Linux avec Azure de Microsoft Learn
J'ai essayé d'extraire le dessin au trait de l'image avec Deep Learning
Essayez de dessiner un "front de type carte météo" par apprentissage automatique basé sur des données météorologiques (2)
J'ai essayé d'implémenter diverses méthodes d'apprentissage automatique (modèle de prédiction) en utilisant scicit-learn
J'ai essayé de traiter et de transformer l'image et d'élargir les données pour l'apprentissage automatique