My First Data Science Bootcamp Project — Predicting Record Prices
By: Bethany Baumann
Tags: Bootcamp, Regression, Ridge Regression, Lasso Regression, Vinyl

I began by using BeautifulSoup to web scrape search pages for the top 1,000 most-collected records on Discogs.com, a popular record collecting database and resale site. From the search results I could extract some basic album info, but I also collected links to each artist and album that I further scraped for stats.

Streaming is by far the most common way music is consumed today. I was interested in the relationship of fanbase streaming-behavior and record prices, so I scraped each artist’s total monthly listeners on Spotify.com. Spotify is dynamic and javascript-enabled, so I had to use Selenium and a Chromium WebDriver to automatically search for artist names, and find and follow links to their pages. It was surreal watching Chrome doing this all by itself.

My target variable, median sale price, was heavily skewed toward cheap records, with some very high outliers (over $1,000 for John Coltrane’s first album). Log transforming median sale price made its distribution appear more normal. Normal distribution of the target variable is not required for linear regression, but this transformation improved the linear relationship (R²) between median sale price and almost all of the predictor variables, and this linear relationship is an assumption of linear regression.

I noticed that there was an interesting drop-off in album price when the albums were more than 30 years old. This may be because CDs were introduced about 30 years ago, and the market is more flooded with records before that time. It might also be because records of this age have more wear, or because older collectors are selling more of their records.

To improve my model, I decided to create an additional categorical predictor for whether or not the record was over 30 years old. However, I also retained the original years_since_release continuous predictor, since there is an overall positive trend.

Relationship between log median price and age of album for three genres

Using my training dataset, I applied sklearn’s PolynomialFeatures to explore interactions between my variables. An interaction means that you can get more information about the value of your target from a combination of predictor variables than from both predictor variables alone. An example might be a certain genre of music being worth more if produced by a certain record label. A typical linear regression formula might look like:

y = B0 + B1*X1 + B2*X2

Adding an interaction term would look like this:

y = B0 + B1*X1 + B2*X2 + B3*(X1*X2)

In my dataset I had several interaction terms with significant coefficients in a quick statsmodels linear regression. One interesting find is that if an album is < 30yr old and the artist has a lot of Spotify monthly listeners the album is worth less than average, but conversely if the album is > 30yr old it is worth more than average.

I selected a few dozen interaction terms, as well as quadratic terms, to add to my model, giving me slighty over 70 predictive variables. This high number of predictive variables means my model may become over-fit to the training set. Also, some variables are likely correlated, which could add instability to the model because coefficients of correlated variables can take on a wide range of values. For example, coefficients of negatively correlated variables can become very high, because they counteract each other, but then if the correlation is not as strong in the test data these variables would have an oversized effect.

Therefore, I planned to use regularized regression methods such as Ridge and Lasso, which can correct for these problems. As a reminder, linear regression normally solves for the coefficients that minimizes the sum of the squared errors of the model:

Linear Regression Cost =

sum(( y_actual — y_predicted)² )

Ridge regression minimizes the sum of the squared errors plus an adjustable constant lambda times the sum of the squared coefficients:

Ridge Regression Cost =

sum(( y_actual — y_predicted)² ) + lambda * sum(coefficient²)

This keeps the coefficients small, which reduces overfitting. It also reduces the coefficients for correlated variables together, keeping them as small as possible and splitting the weight between the two variables because, for example, the term lambda*sum(2²+ 2²) is less than lambda*sum(4² + 0²).

Lasso regression is slightly different in that it minimizes the sum of the squared errors plus a constant lambda times the sum of the absolute value of the coefficients:

Lasso Regression Cost =

sum(( y_actual — y_predicted)² ) + lambda * sum(|coefficient|)

This also reduces overfitting by keeping coefficients small. But, unlike Ridge, for correlated coefficients Lasso has a tendency to put all the weight into one of them and reduce the other’s coefficient to zero, performing feature selection and model simplification.

Overall, Ridge performs better when all the variables are somewhat useful in prediction, and Lasso performs better when there are a lot of extraneous or nonpredictive variables.

The evenly spread distribution of residuals (errors) suggests a good fit of the model to the data

Before testing regularization, I scaled my variables to have the same mean and standard deviation using sklearn’s StandardScaler. Then I used cross-validation in sklearn’s LassoCV and RidgeCV functions to select the optimal lambda values for each. I compared the average mean square error by 10-fold cross-validation for linear regression, Ridge and Lasso. Lasso performed the best on my dataset, but only reduced a handful of coefficients to zero, leaving me with over 60 features in my model.

The features with the biggest effect on predictions in my final model

I finally assessed my Lasso model on my holdout test set. It had an average absolute error (MAE) of $17.82, which is still a bit high in my opinion, because the mean price of records in this dataset was in the mid $30s. However, my test set MAE was lower than my training set MAE, which is a good sign regularization worked.

Next, I challenged my fiancé to a record pricing showdown. I selected 50 albums from my test set at random and asked him to estimate the median sale price for a first edition of that album on Discogs.com. I also told him the average price of the records in my dataset. On this test subset he had an MAE of $23.59, and my model had an MAE of $14.88! Note that he owns more records than were in my training set. In light of this, I think the model performed well!

I think that increasing the size of my dataset and removing outliers would significantly improve the model. Overall, album prices may be difficult to predict because of highly unique, difficult to model, features.

Hits and misses in my model’s holdout test set predictions

Links:

GitHub repository: https://github.com/Beth526/metis_project2

Cleaned dataset uploaded to Kaggle: https://www.kaggle.com/bethbaumann/first-edition-record-data-from-discogs