Wie ein Programmierer ein Auto gekauft hat

Vor kurzem war ich verwirrt von der Suche nach gebrauchten Auto, anstatt nur verkauft, und wie es normalerweise der Fall ist, behaupteten mehrere Wettbewerber diese Rolle.

Wie Sie wissen, gibt es in der Russischen Föderation mehrere große seriöse Websites (auto.ru, drom.ru, avito.ru), nach denen ich lieber gesucht habe, um ein Auto zu kaufen. Hunderte und für einige Modelle und Tausende von Autos von den oben aufgeführten Standorten erfüllten meine Anforderungen. Abgesehen von der Tatsache, dass es unpraktisch ist, mehrere Ressourcen zu durchsuchen, bevor ich ein Auto „live“ sehe, möchte ich vorteilhafte (deren Preis unter dem Marktpreis liegt) Angebote für a priori-Informationen auswählen, die jede der Ressourcen bereitstellt. Natürlich wollte ich eigentlich mehrere überbestimmte algebraische Gleichungssysteme (möglicherweise nichtlineare) mit hoher Dimension manuell lösen, aber ich habe mich selbst überwältigt und beschlossen, diesen Prozess zu automatisieren.
Bild

Datenerfassung


Ich habe Daten aus allen oben beschriebenen Ressourcen gesammelt und mich für die folgenden Parameter interessiert:

  • Preis
  • Baujahr (Jahr)
  • Laufleistung
  • Motorvolumen (Motorleistung)
  • Motorleistung (engine.power)
  • Motortyp (2 Indikatoren, die sich gegenseitig ausschließen, Diesel- und Hybridmotoren mit den Werten 0 oder 1 für Diesel- bzw. Hybridmotoren). Der Standardmotortyp ist Benzin (nicht in die dritte Variable verschoben, um Multikollinearität zu vermeiden ).

    Also:

    Bild

    Weiterhin ist eine ähnliche Logik für Indikatorvariablen standardmäßig impliziert.
  • Getriebetyp (Anzeigevariable mt (Schaltgetriebe), die für ein Schaltgetriebe einen Booleschen Wert annimmt). Der voreingestellte Getriebetyp ist automatisch.

    Es ist anzumerken, dass ich Automatikgetrieben nicht nur eine klassische Hydraulikmaschine, sondern auch Robotermechanik und einen Variator zuschrieb.
  • Antriebstyp (2 Indikatorvariablen front.drive und rear.drive, die Boolesche Werte akzeptieren). Der Standardlaufwerktyp ist voll.
  • Körpertyp (7 Indikatorvariablen Limousine, Schrägheck, Kombi, Coupé, Cabriolet, Minivan, Pickup, Boolesche Werte). Der Standardkörpertyp ist SUV / Crossover

Ungefüllt faul Verkäufer Details I als NA festgestellt (nicht verfügbar), in der Lage sein, korrekt unter Verwendung dieser Werte zu behandeln die R .

Datenvisualisierung


Um nicht in die Trockentheorie einzusteigen, schauen wir uns ein konkretes Beispiel an. Wir werden nach rentablen Mercedes-Benz E-Klassen suchen, die nicht älter als 2010 sind und in Moskau bis zu 1,5 Millionen Rubel kosten. Um mit den Daten arbeiten zu können, füllen Sie zunächst die fehlenden Werte (NA) mit Medianwerten aus. Glücklicherweise gibt es in R eine median () -Funktion.

dat <- read.csv("dataset.txt") # загружаем выборку в R
dat$mileage[is.na(dat$mileage)] <- median(na.omit(dat$mileage)) # например для пробега

Für die übrigen Variablen ist die Prozedur identisch, so dass ich diesen Punkt weglassen werde.

Nun wollen wir sehen, wie der Preis von den Regressoren abhängt (wir sind nicht daran interessiert, Indikatorvariablen in dieser Phase zu visualisieren).

Bild

Es stellt sich heraus, dass es 2013 mehrere Autos und 2014 sogar eines gibt!

Bild

Je niedriger die Laufleistung, desto höher der Preis.

Bild

Bild

Auf einigen Diagrammen sehen wir Punkte, die sich von der allgemeinen Stichprobe abheben - Emissionen , mit Ausnahme derer wir eine Annahme über die lineare Abhängigkeit des Preises von den Fahrzeugparametern treffen können.

Ich möchte Ihre Aufmerksamkeit auf die Tatsache lenken, dass in den meisten Artikeln über maschinelles Lernen, die mir in letzter Zeit begegnet sind, einschließlich „Habré“, nur sehr wenig darauf geachtet wird, die Rechtmäßigkeit der Verwendung des ausgewählten Modells, seiner Diagnose und seiner Fehler zu belegen.

Damit die von uns erhaltenen Schätzungen konsistent sind, ist es sinnvoll, die Richtigkeit des von uns gewählten Modells zu prüfen.

Modelldiagnose


Im vorherigen Abschnitt wurde auf der Grundlage von experimentellen Daten eine Annahme über die Linearität des betrachteten Modells in Bezug auf den Preis getroffen. In diesem Abschnitt werden wir daher über die multiple lineare Regression , ihre Diagnose und Fehler sprechen .

Damit das Modell korrekt ist, müssen die Bedingungen des Gauß-Markov-Theorems erfüllt sein :

  1. Das Datenmodell ist korrekt spezifiziert, d.h.
    • fehlende fehlende Werte.

      Weitere Details
      Diese Bedingung ist erfüllt (siehe Abschnitt Visualisierung der erhaltenen Daten), die fehlenden Werte werden durch die mittleren ersetzt.

    • Es gibt keine Multikollinearität zwischen den Regressoren.

      Weitere Details
      Überprüfen Sie, ob diese Bedingung erfüllt ist:

      dat_cor <- as.matrix(cor(dat)) # рассчет корреляции между переменными
      dat_cor[is.na(dat_cor)] <- 0 # заменяем пропущенные значения на 0 (т.к. например в кузове пикап или минивен искомого авто не бывает)
      library(corrplot) # подключаем библиотеку corrplot, для красивой визуализации
      palette <-colorRampPalette(c("#7F0000","red","#FF7F00","yellow","#7FFF7F", "cyan", "#007FFF", "blue","#00007F"))
      corrplot(dat_cor, method="color", col=palette(20), cl.length=21,order = "AOE", addCoef.col="green") # рисуем таблицу зависимостей между переменными
      

      Bild

      Es ist zu sehen, dass es eine große Korrelation (> 0,7) zwischen dem Volumen und der Leistung des Motors gibt. Daher werden wir bei der weiteren Analyse die Variable engine.capacity nicht berücksichtigen, weil Es ist die Motorleistung, die es uns ermöglicht, ein Regressionsmodell im Vergleich zur Motorgröße genauer zu erstellen (atmosphärisches Benzin, turbogeladenes Benzin, Dieselmotoren - bei gleichem Volumen können sie unterschiedliche Leistungen haben).

    • keine Emissionen .

      Weitere Details
      Emissionsindikatoren, die sich von der allgemeinen Stichprobe unterscheiden (siehe Abschnitt Visualisierung der erhaltenen Daten), haben einen erheblichen Einfluss auf die Schätzungen der Koeffizienten des Regressionsmodells. Eine statistische Methode, die unter Ausreißerbedingungen ausgeführt werden kann, wird als robust bezeichnet - eine lineare Regression gilt für sie nicht, anders als beispielsweise die robuste Huber-Regression oder die Methode der abgeschnittenen Quadrate.

      Die Messung der Auswirkung von Emissionen auf Modellschätzungen kann in allgemeine und spezifische unterteilt werden. Allgemeine Messwerte wie Cook-Abstand, Dffits, Covariacin-Verhältnis (Covratio), Mahalanobis-Abstand zeigen, wie sich die i-te Beobachtung auf die Position der gesamten Regressionsabhängigkeit auswirkt, und wir werden sie verwenden, um Ausreißer zu identifizieren. Spezifische Einflussgrößen wie dfbetas zeigen den Einfluss der i-ten Beobachtung auf die einzelnen Parameter des Regressionsmodells.

      Das Covariacin-Verhältnis (Covratio) ist ein gängiges Maß für die Wirkung der Beobachtung. Es ist das Verhältnis der Determinante der Kovarianzmatrix mit der entfernten i-ten Beobachtung zur Determinante der Kovarianzmatrix für den gesamten Datensatz.

      Die Kochdistanz ist eine quadratische Abhängigkeit vom internen studentisierten Rest, die für die Erkennung von Ausreißern nicht empfohlen wird, im Gegensatz zum externen studentisierten Rest, von dem die Dffits linear abhängen.

      Die Entfernung von Mahalanobis ist ein Maß für die Entfernung der Beobachtung vom Zentrum des Systems, aber weil Es berücksichtigt nicht die abhängige oder unabhängige Natur der Variablen und behandelt sie in der streuenden Wolke gleichermaßen, diese Maßnahme ist nicht für die Regressionsanalyse vorgesehen.
      Daher werden wir die dffits- und covratio-Maßnahmen verwenden, um Emissionen zu ermitteln.

      model <- lm(price ~ year + mileage  + diesel + hybrid + mt + front.drive + rear.drive + engine.power + sedan + hatchback + wagon + coupe + cabriolet + minivan + pickup, data = dat) # линейная модель
      model.dffits <- dffits(model) # рассчитаем меру dffits
      

      Maßgebend für das Maß dffits sind Indikatoren, die 2 * sqrt (k / n) = 0,42 überschreiten. Sie sollten sie daher verwerfen (k ist die Anzahl der Variablen, n ist die Anzahl der Zeilen in der Stichprobe).

      model.dffits.we <- model.dffits[model.dffits < 0.42]
      model.covratio <- covratio(model)  # рассчитаем ковариационное отношения для модели
      

      Signifikante Maßnahmen für Kovratio - Maßnahmen ergeben sich aus der Ungleichheit model.covratio [i] -1 | > (3 * k) / n.

      model.covratio.we <- model.covratio[abs(model.covratio -1) < 0.13]
      dat.we <- dat[intersect(c(rownames(as.matrix(model.dffits.we))), c(rownames(as.matrix(model.covratio.we)))),] # наблюдения без выбросов
      model.we <- lm(price ~ year + mileage  + diesel + hybrid + mt + front.drive + rear.drive + engine.power + sedan + hatchback + wagon + coupe + cabriolet + minivan + pickup, data = dat.we) # линейная модель построенная по выборке без выбросов
      

      Nachdem wir nun die Beobachtungen entfernt haben, die sich von der allgemeinen Stichprobe abheben, schauen wir uns die Diagramme der Abhängigkeit des Preises von den Regressoren an.

      Bild

      Bild

      Bild

      Insgesamt konnten wir mit der gewählten Methode zur Ermittlung von Ausreißern 18 Beobachtungen aus der Gesamtstichprobe ausschließen, was sich zweifellos positiv auf die Genauigkeit der Bestimmung der Koeffizienten des linearen Modells mit OLS auswirkt .


  2. Alle Regressoren sind deterministisch und nicht gleich.

    Weitere Details
    Diese Bedingung ist erfüllt.

  3. Fehler sind nicht systematisch, die Varianz der Fehler ist gleich ( Homoskedastizität )

    Weitere Details
    Schauen wir uns an, wie die Modellfehler verteilt sind (um die Modellfehler in R zu berechnen, gibt es eine resid () -Funktion).

    plot(dat.we$year, resid(model.we))
    plot(dat.we$mileage, resid(model.we))
    plot(dat.we$engine.power, resid(model.we))
    

    Bild

    Bild

    Bild

    Die Fehler sind relativ zur horizontalen Achse mehr oder weniger gleichmäßig verteilt, so dass wir keinen Zweifel daran haben können, dass die Homoskedastizitätsbedingung erfüllt ist.

  4. Fehler werden normal verteilt.

    Weitere Details
    Um diesen Zustand zu überprüfen, konstruieren wir ein Diagramm der Quantile von Resten gegenüber Quantilen, was erwartet werden könnte, vorausgesetzt, die Reste sind normalverteilt.

    qqnorm(resid(model.we)) 
    qqline(resid(model.we))
    

    Bild

Das ausgewählte Modell testen


Es ist also die Zeit gekommen, in der die Bürokratie vorbei ist, und die Richtigkeit der Verwendung des linearen Regressionsmodells steht außer Zweifel. Wir können nur die Koeffizienten der linearen Gleichung berechnen, mit denen wir unsere prognostizierten Autopreise ermitteln und mit den Preisen aus den Anzeigen vergleichen können.

model.we <- lm(price ~ year + mileage  + diesel + hybrid + mt + front.drive + rear.drive + engine.power + sedan + hatchback + wagon + coupe + cabriolet + minivan + pickup, data = dat.we)
coef(model.we) # коэффициенты линейной модели
  (Intercept)  year  mileage  diesel  rear.drive  engine.power  sedan 
  -1.76e+08  8.79e+04  -1.4e+00  2.5e+04  4.14e+04  2.11e+03  -2.866407e+04        
predicted.price <- predict(model.we, dat) # предскажем цену по полученным коэффициентам
real.price <- dat$price # вектор цен на автомобили полученный из объявлений
profit <- predicted.price - real.price # выгода между предсказанной нами ценой и ценой из объявлений

Lassen Sie uns nun die gesammelten Forschungsergebnisse zusammenfassen, um eines der aussagekräftigsten Diagramme zu erhalten, das uns den für jeden Autohändler wünschenswertesten Wert zeigt, nämlich den Nutzen, den der Kauf eines bestimmten Autos im Verhältnis zum Marktpreis hat.

plot(real.price,profit)
abline(0,0)

Bild

Und welchen prozentualen Nutzen können Sie erwarten?

sorted <- sort(predicted.price /real.price, decreasing = TRUE)
sorted[1:10]
      69       42      122      248      168       15      244      271      109      219 
1.590489 1.507614 1.386353 1.279716 1.279380 1.248001 1.227829 1.209341 1.209232 1.204062 

Ja, 59% sparen ist sehr cool, aber sehr zweifelhaft, man muss ein Auto "live" sehen, weil Freier Käse ist normalerweise in einer Mausefalle, oder der Verkäufer braucht dringend Geld. Ab dem 4. Platz (Einsparung 28%) und darüber hinaus erscheint das Ergebnis jedoch recht realistisch.

Ich möchte darauf hinweisen, dass die Koeffizienten des linearen Modells durch Messungen mit ausgeschlossenen Emissionen gebildet werden, um den Fehler der Vorhersageanalyse zu verringern, während wir den Preis für alle Angebote auf dem Markt vorhersagen, was zweifellos die Wahrscheinlichkeit eines Fehlers bei der Vorhersage des Emissionspreises erhöht (z. B. in In unserem Fall können alle Fahrzeuge mit einer Kombi-Karosserie in Emissionen geraten, wodurch die Korrektur, die durch die entsprechende Indikatorvariable vorgenommen werden sollte, nicht berücksichtigt wird. Dies ist ein Nachteil des ausgewählten Modells . Natürlich können Sie den Preis für Angebote, die sich stark von der Gesamtstichprobe unterscheiden, nicht vorhersagen, aber es ist sehr wahrscheinlich, dass es sich dabei um die vorteilhaftesten Angebote handelt.

Am Ende


Liebe Freunde, ich selbst hätte nach dem Lesen eines ähnlichen Artikels in erster Linie drei Fragen gestellt:

  1. Was ist die Genauigkeit des Modells?
  2. Warum wird die einfachste lineare Regression gewählt und wo wird mit anderen Modellen verglichen?
  3. Warum nicht einen Dienst zur Suche nach rentablen Autos machen?

Deshalb antworte ich:

  1. Wir werden das Modell nach dem 80/20 Schema testen.

    set.seed(1) # инициализируем генератор случайных чисел (для воспроизводимости)
    split <- runif(dim(dat)[1]) > 0.2 # разделяем нашу выборку
    train <- dat[split,] # выборка для обучения
    test <- dat[!split,] # тестовая выборка
    train.model <- lm(price ~ year + mileage  + diesel + hybrid + mt + front.drive + rear.drive + engine.power + sedan + hatchback + wagon + coupe + cabriolet + minivan + pickup, data = train) # линейная модель построенная по выборке для обучения
    train.dffits <- dffits(train.model) # рассчитаем меру dffits
    train.dffits.we <- train.dffits[train.dffits < 0.42] # удалим значимые для меры dffits показатели
    train.covratio <- covratio(train.model)  # рассчитаем ковариационное отношения для модели
    train.covratio.we <- model.covratio[abs(model.covratio -1) < 0.13] # удалим значимые для меры covratio показатели
    train.we <- dat[intersect(c(rownames(as.matrix(train.dffits.we))), c(rownames(as.matrix(train.covratio.we)))),] # выборка для обучения без выбросов
    train.model.we <- lm(price ~ year + mileage  + diesel + hybrid + mt + front.drive + rear.drive + engine.power + sedan + hatchback + wagon + coupe + cabriolet + minivan + pickup, data = train.we) # линейная модель построенная по выборке для обучения без выбросов
    predictions <- predict(train.model.we, test) # проверим точность на тестовой выборке
    print(sqrt(sum((as.vector(predictions - test$price))^2)/length(predictions))) # средняя ошибка прогноза цены (в рублях)
    [1] 121231.5
    

    Es ist viel oder wenig - kann nur durch Vergleich gefunden werden.
  2. Die lineare Regression als eine der Grundlagen des maschinellen Lernens ermöglicht es Ihnen, sich nicht vom Studium des Algorithmus ablenken zu lassen, sondern sich vollständig auf die eigentliche Aufgabe einzulassen.

    Aus diesem Grund habe ich beschlossen, meine Geschichte in zwei Artikel zu unterteilen.

    Der nächste Artikel konzentriert sich auf den Vergleich von Modellen, um unser Problem zu lösen und den Gewinner zu identifizieren.
  3. Zu diesem Thema wurde ein Service entwickelt, der auf dem Gewinnermodell basiert, das im nächsten Artikel erörtert wird.

    Und so kam es, dass die Mercedes-Benz E-Klasse nicht älter als 2010 ist und in Moskau einen Wert von bis zu 1,5 Millionen Rubel hat .

    Bild

    Noch
    Bild


Referenzen


1. Quelldaten im CSV-Format - dataset.txt

Jetzt auch beliebt: