This project utilizes linear regression on the Boston Housing dataset to predict house prices by optimizing a least squares loss function, aiming to model the relationship between various housing attributes and prices for accurate predictions.
This dataset contains information about houses in the Boston, Massachusetts area, United States.
The Boston Housing dataset consists of 506 samples and 13 attributes, detailing information about the surrounding environment of houses, such as the ratio of bathrooms, crime rates, distance to commercial centers and bus terminals, average apartment size nearby, and several other attributes:
# Đọc dữ liệu từ file CSV vào DataFrame df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv') # Hiển thị 5 dòng đầu tiên của dữ liệu Boston display(df.head())
# Thống kê mô tả của giá trị trung bình của giá nhà (MEDV) print(df['medv'].describe())
A. Approach to the Problem:
The first step involves data preprocessing to explore correlations between attributes and the predictive target using a correlation matrix, as well as addressing outliers.
Following this approach, the dataset is split into training and testing sets.
Subsequently, linear regression is applied to predict house prices by optimizing a loss function based on the method of least squares.
By computing the inverse matrix of the transpose of the input matrix multiplied by the input matrix, optimal parameters for the linear regression model can be calculated.
Finally, the model is used to predict house prices on the test set, and the model's effectiveness is evaluated by computing the RMSE and R-squared metrics.
B. Least Squares Method:
The Least Squares Method has two variants: Univariable least square (used when only one independent variable predicts the dependent variable) and Multivariable least square (employed when multiple independent variables predict the dependent variable).
In this project, we'll be utilizing Multivariable least squares.
With Multivariable least squares, our goal is to find the best-fitting linear line to model the relationship between the dependent variable and multiple independent variables in multidimensional datasets.
The multivariable linear regression model is in the form of:
Y = β0 + β1X1 + β2X2 + … + βnXn + εIn which:
θ̂ = (XTX)-1XTy = minθ ||y - Xθ||22In which:
A. Calculate the correlation matrix among the attributes:
The concept of the correlation matrix:
sns.heatmap(corr_matrix, annot=True, fmt=".1f", cmap ="crest")
ssns.pairplot(df[['rm', 'lstat', 'medv']])
# Chọn các biến độc lập và biến phụ thuộc Independent_vars = df[['rm', 'lstat']].values # Thêm một cột chứa giá trị 1 vào ma trận X để tính toán hệ số chặn Independent_vars = np.insert(Independent_vars, 0, 1, axis=1) # Tính toán VIF cho các biến độc lập vif = pd.DataFrame() vif["VIF Factor"] = [variance_inflation_factor(Independent_vars, i) for i in range(1, Independent_vars.shape[1])] vif["features"] = ['rm', 'lstat'] # In kết quả print(vif)
VIF Factor | Features |
---|---|
1.60452 | rm |
1.60452 | lstat |
#Tính độ lệch của phân phối RM và LSTAT skew_rm = skew(df['rm']) skew_lstat = skew(df['lstat']) print(f"Độ lệch của rm: {skew_rm:.2f}") print(f"Độ lệch của lstat: {skew_lstat:.2f}")
Features | Skewness |
---|---|
rm | 0.40 |
lstat | 0.90 |
# Vẽ boxplot cho biến lstat plt.boxplot(df['lstat'], vert= False) plt.title('Boxplot cho biến LSTAT') plt.show()
#Tính IQR q1 = np.percentile(df['lstat'], 25) q3 = np.percentile(df['lstat'], 75) iqr = q3 - q1 #Tính giá trị lower_bound và upper_bound lower_bound = q1 - 1.5 * iqr upper_bound = q3 + 1.5 * iqr #Loại bỏ các giá trị ngoại lai của LSTAT df = df[(df['lstat'] > lower_bound) & (df['lstat'] < upper_bound)] # Vẽ boxplot cho biến LSTAT sau khi loại bỏ Outlier plt.boxplot(df['lstat'], vert= False) plt.title('Boxplot cho biến LSTAT sau khi loại bỏ Outlier') plt.show()
# Chọn các thuộc tính RM và LSTAT làm biến độc lập, MEDV làm biến phụ thuộc X = df[['rm', 'lstat']].values y = df['medv'].values # Thêm một cột chứa giá trị 1 vào ma trận X để tính toán hệ số chặn X = np.insert(X, 0, 1, axis=1) Chia dữ liệu thành tập train và tập test tỉ lệ 70:30 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
#Kiểm tra ma trận X^T X có thể đảo ngược hay không XTX = X_train.T.dot(X_train) det = np.linalg.det(XTX) if det == 0: print("Ma trận X^T X không thể đảo ngược.") else: print("Ma trận X^T X có thể đảo ngược.")
# Tính toán bộ tham số theta bằng phương pháp bình phương tối tiểu XT = np.transpose(X_train) XTX1 = np.linalg.inv(XT.dot(X_train)) XTY = XT.dot(y_train) theta = XTX1.dot(XTY) print(theta) print(f"MEDV = {theta[0]} + {theta[1]} * RM + {theta[2]}* LSTAT")
MEDV = 2.95 + 4.64 * RM - 0.75 * LSTATThe slope coefficient for RM is 4.64, indicating a positive correlation between RM and MEDV.
x_min = np.min(X[:, 1]) x_max = np.max(X[:, 1]) y_min = np.min(X[:, 2]) y_max = np.max(X[:, 2]) xx, yy = np.meshgrid(np.linspace(x_min, x_max), np.linspace(y_min, y_max)) Z = theta[0] + theta[1] * xx + theta[2] * yy fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(X[:, 1], X[:, 2], y) ax.plot_surface(xx, yy, Z, alpha=0.5) ax.set_xlabel('RM') ax.set_ylabel('LSTAT') ax.set_zlabel('MEDV') plt.show()
# Dự đoán giá trị nhà cho tập kiểm tra y_pred = np.dot(X_test, theta) residuals = y_test - y_pred fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) # Vẽ biểu đồ so sánh giá trị thực tế và giá trị dự đoán ax1.scatter(y_test, y_pred, alpha=0.5) ax1.plot([0, max(y_test)], [0, max(y_test)], '--', color='red') ax1.set_xlabel('Giá trị thực tế') ax1.set_ylabel('Giá trị dự đoán') ax1.set_title('Biểu đồ so sánh giá trị thực tế và giá trị dự đoán') # Vẽ đồ thị Residual Plot ax2.scatter(y_pred, residuals) ax2.axhline(y=0, color='r', linestyle='-') ax2.set_xlabel('Giá trị dự đoán') ax2.set_ylabel('Sai số (Residual)') ax2.set_title('Biểu đồ phân tán của sai số') plt.tight_layout() plt.show()
RMSE = √( 1⁄ n Σ i=1 n ( ytest_i - ypred_i )2 )In which:
# Tính toán sai số RMSE rmse = np.sqrt(np.mean((y_test - y_pred) ** 2)) # Tính giá trị trung bình của biến mục tiêu y_mean = np.mean(y_test) print('Giá trị trung bình của biến mục tiêu:', y_mean) print('RMSE:', rmse) # Nhận xét kết quả if rmse < y_mean: print('RMSE nhỏ hơn giá trị trung bình của biến mục tiêu, mô hình có độ chính xác tương đối tốt.') else: print('RMSE lớn hơn giá trị trung bình của biến mục tiêu, mô hình có độ chính xác tương đối thấp.')
R2 = 1 - SSres⁄SStotIn which:
SSres = ∑i=1(ytest_i - ypred_i)2
SStot = ∑i=1(ytest_i - ȳ)2
#Tính R-squared SS_res = sum((y_test - y_pred)**2) SS_tot = sum((y_test - y_mean)**2) R_squared = (1 - SS_res/SS_tot) print(R_squared)